diff --git a/NOTICE.TXT b/NOTICE.TXT
index 13005458b7b612f82c1f8f461c5f6ff7722e4b54..682cc99d79d072aa8242dc60c0ca9da2f653fe92 100644
--- a/NOTICE.TXT
+++ b/NOTICE.TXT
@@ -131,7 +131,6 @@ This product uses software based on the BSD License
 * Antlr (BSD license) [http://www.antlr.org]
 * PostgreSQL JDBC Driver(BSD License) [http://jdbc.postgresql.org]
 * Modernizr JS Library (BSD License) [http://modernizr.com]
-* Datatable JavaScript table UI library (BSD License) [https://datatables.net]
 
 -----------------------------------------------------------------------
 This product uses software based on the Common Public License Version
diff --git a/pom.xml b/pom.xml
index b3f53c7a36f38200812d98b3cfc844a1be28022f..e8ddb26c5075d7268abe01c02429e1058db7e346 100644
--- a/pom.xml
+++ b/pom.xml
@@ -248,9 +248,7 @@
 											<removeIncluded>false</removeIncluded>
 											<includes>
 												<include>${basedir}/target/jquery/jquery/tagsinput/bootstrap-tagsinput.min.css</include>
-												<include>${basedir}/target/jquery/jquery/uilayout/layout-default-latest.min.css</include>
 												<include>${basedir}/target/jquery/jquery/fullcalendar/fullcalendar.min.css</include>
-												<include>${basedir}/src/main/webapp/static/js/jquery/datatables/css/jquery.dataTables.css</include>
 											</includes>
 										</aggregation>
 									</aggregations>
diff --git a/src/main/java/org/olat/core/commons/fullWebApp/_content/fullwebapplayout.html b/src/main/java/org/olat/core/commons/fullWebApp/_content/fullwebapplayout.html
index 4426e1c3ba692458bc3ace79ca24501d1d14962e..7e54735c3f17cc94a1460b0c521eda8537400b47 100644
--- a/src/main/java/org/olat/core/commons/fullWebApp/_content/fullwebapplayout.html
+++ b/src/main/java/org/olat/core/commons/fullWebApp/_content/fullwebapplayout.html
@@ -107,7 +107,6 @@ function b_start(){
 ## <link type="text/css" href='$r.staticLink("js/jquery/uilayout/layout-default-latest.css")' rel="stylesheet"/>
 <link type="text/css" href='$r.staticLink("js/jquery/tagsinput/bootstrap-tagsinput.css")' rel="stylesheet"/>
 <link type="text/css" href='$r.staticLink("js/jquery/fullcalendar/fullcalendar.css")' rel="stylesheet"/>
-<link type="text/css" href='$r.staticLink("js/jquery/datatables/css/jquery.dataTables.css")' rel="stylesheet"/>
 ## FIXME:oo10 add plugin min
 ##<link type="text/css" href='$r.staticLink("js/js.plugins.min.css")' rel="stylesheet"/>
 <link type="text/css" href='$r.staticLink("js/jquery/ui/jquery-ui-1.10.4.custom.min.css")' rel="stylesheet"/>
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java
index 9ce358183f1726e42d707326f4865dfb5893f3b6..219398290b6f1fe41be4733232e0f2f69595ffd4 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/elements/FlexiTableElement.java
@@ -118,13 +118,15 @@ public interface FlexiTableElement extends FormItem {
 	 * 
 	 * @return
 	 */
-	public int getColumnLabelForDragAndDrop();
+	public int getColumnIndexForDragAndDropLabel();
 
 	/**
+	 * Setting a value enable the drag and drop on this table. Drag and drop
+	 * is only implemented for the classic voew.
 	 * 
 	 * @param columnLabelForDragAndDrop
 	 */
-	public void setColumnLabelForDragAndDrop(int columnLabelForDragAndDrop);
+	public void setColumnIndexForDragAndDropLabel(int columnLabelForDragAndDrop);
 	
 	/**
 	 * @return true if the links select all / unselect all are enabled
@@ -226,7 +228,7 @@ public interface FlexiTableElement extends FormItem {
 	 * 
 	 * @param callout
 	 */
-	public void setExtendedSearch(ExtendedFlexiTableSearchController controller, boolean callout);
+	public void setExtendedSearch(ExtendedFlexiTableSearchController controller);
 	
 	
 	public boolean isExtendedSearchExpanded();
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java
index 5cdc55f67749699bb7bf9a01780efa91f02ba97a..a55a51864f3a1566ac2182eb7eb283c34c6a0c6d 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/AbstractFlexiTableRenderer.java
@@ -53,7 +53,7 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 
 		renderHeaderButtons(renderer, sb, ftE, ubu, translator, renderResult, args);
 		
-		sb.append("<div class=\"o_table_wrapper o_table_flexi")
+		sb.append("<div class='o_table_wrapper o_table_flexi")
 		  .append(" o_table_edit", ftE.isEditMode());
 		String css = ftE.getElementCssClass();
 		if (css != null) {
@@ -62,9 +62,14 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 		switch(ftE.getRendererType()) {
 			case custom: sb.append(" o_rendertype_custom"); break;
 			case classic: sb.append(" o_rendertype_classic"); break;
-			case dataTables: sb.append(" o_rendertype_dataTables"); break;
 		}
-		sb.append(" table-responsive\">");
+		sb.append(" table-responsive'");
+		String wrapperSelector = ftE.getWrapperSelector();
+		if (wrapperSelector != null) {
+			sb.append(" id='").append(wrapperSelector).append("'");
+		}
+		sb.append(">");
+		
 		String id = ftC.getFormDispatchId();
 		sb.append("<table id=\"").append(id).append("\" class=\"table table-condensed  table-striped table-hover table-responsive\">");
 		
@@ -74,8 +79,29 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 		sb.append("<tbody>");
 		renderBody(renderer, sb, ftC, ubu, translator, renderResult);
 		sb.append("</tbody></table>");
-		
 		renderFooterButtons(sb, ftC, translator);
+		//draggable
+		if(ftE.getColumnIndexForDragAndDropLabel() > 0) {
+		
+			sb.append("<script type='text/javascript'>")
+			  .append("/* <![CDATA[ */ \n")
+			  .append("jQuery(function() {\n")
+			  .append(" console.log(jQuery('.o_table_flexi table tr'));\n")
+			  .append(" jQuery('.o_table_flexi table tr').draggable({\n")
+	          .append("  containment: '#o_main',\n")
+	          .append("	 zIndex: 10000,\n")
+	          .append("	 cursorAt: {left: 0, top: 0},\n")
+	          .append("	 accept: function(event,ui){ return true; },\n")
+	          .append("	 helper: function(event,ui,zt) {\n")
+	          .append("    var helperText = jQuery(this).children('.o_dnd_label').text();\n")
+	          .append("    return jQuery(\"<div class='ui-widget-header b_table_drag'>\" + helperText + \"</div>\").appendTo('body').css('zIndex',5).show();\n")
+	          .append("  }\n")
+	          .append("});\n")
+	          .append("});\n")
+	          .append("/* ]]> */\n")
+			  .append("</script>\n");
+		}
+		
 		sb.append("</div>");
 		
 		//source
@@ -90,7 +116,7 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 			RenderResult renderResult, String[] args) {
 
 		Component searchCmp = ftE.getExtendedSearchComponent();
-		if(searchCmp != null && !ftE.isExtendedSearchCallout() && ftE.isExtendedSearchExpanded()) {
+		if(searchCmp != null && ftE.isExtendedSearchExpanded()) {
 			renderer.render(searchCmp, sb, args);
 			sb.append("<div class='row clearfix'><div class='col-lg-6'></div>");
 		} else {
@@ -240,10 +266,6 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 					renderFormItem(renderer, sb, ftE.getClassicTypeButton(), ubu, translator, renderResult, args);
 					break;
 				}
-				case dataTables: {
-					renderFormItem(renderer, sb, ftE.getDataTablesTypeButton(), ubu, translator, renderResult, args);
-					break;
-				}
 			}
 		}
 	}
@@ -257,7 +279,6 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 	}
 	
 	protected void renderFooterButtons(StringOutput sb, FlexiTableComponent ftC, Translator translator) {
-
 		FlexiTableElementImpl ftE = ftC.getFlexiTableElement();
 		if(ftE.isSelectAllEnable()) {
 			String formName = ftE.getRootForm().getFormName();
@@ -280,7 +301,7 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 			sb.append("</div></div>");
 		}
 		
-		if(ftE.getRendererType() != FlexiTableRendererType.dataTables && ftE.getPageSize() > 0) {
+		if(ftE.getPageSize() > 0) {
 			renderPagesLinks(sb, ftC);
 		}
 	}
@@ -348,33 +369,26 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 		String rowIdPrefix = "row_" + id + "-";
 		for (int i = firstRow; i < lastRow; i++) {
 			if(dataModel.isRowLoaded(i)) {
-				renderRow(renderer, target, ftC, rowIdPrefix,	i, rows, ubu, translator, renderResult);
+				renderRow(renderer, target, ftC, rowIdPrefix, i, ubu, translator, renderResult);
 			}
 		}				
 		// end of table table
 	}
 	
 	protected void renderRow(Renderer renderer, StringOutput target, FlexiTableComponent ftC, String rowIdPrefix,
-			int row, int rows, URLBuilder ubu, Translator translator, RenderResult renderResult) {
+			int row, URLBuilder ubu, Translator translator, RenderResult renderResult) {
 
 		FlexiTableElementImpl ftE = ftC.getFlexiTableElement();
 		FlexiTableColumnModel columnsModel = ftE.getTableDataModel().getTableColumnModel();
 		int numOfCols = columnsModel.getColumnCount();
 		
 		// use alternating css class
-		String cssClass;
-		if (row % 2 == 0) cssClass = "";
-		else cssClass = "b_table_odd";
-		// add css class for first and last column to support older browsers
-		if (row == 0) cssClass += " b_first_child";
-		if (row == rows-1) cssClass += " b_last_child";
-
 		target.append("<tr id='").append(rowIdPrefix).append(row)
-				  .append("' class=\"").append(cssClass).append("\">");
+				  .append("'>");
 				
 		int col = 0;
 		if(ftE.isMultiSelect()) {
-			target.append("<td class='b_first_child'>")
+			target.append("<td>")
 			      .append("<input type='checkbox' name='tb_ms' value='").append(rowIdPrefix).append(row).append("'");
 			if(ftE.isAllSelectedIndex() || ftE.isMultiSelectedIndex(row)) {
 				target.append(" checked='checked'");
@@ -386,25 +400,25 @@ public abstract class AbstractFlexiTableRenderer extends DefaultComponentRendere
 		for (int j = 0; j<numOfCols; j++) {
 			FlexiColumnModel fcm = columnsModel.getColumnModel(j);
 			if(ftE.isColumnModelVisible(fcm)) {
-				renderCell(renderer, target, ftC, fcm, row, col++, numOfCols, ubu, translator, renderResult);
+				renderCell(renderer, target, ftC, fcm, row, col++, ubu, translator, renderResult);
 			}
 		}
 		target.append("</tr>");
 	}
 
 	protected void renderCell(Renderer renderer, StringOutput target, FlexiTableComponent ftC, FlexiColumnModel fcm,
-			int row, int col, int numOfCols, URLBuilder ubu, Translator translator, RenderResult renderResult) {
+			int row, int col, URLBuilder ubu, Translator translator, RenderResult renderResult) {
 
 		FlexiTableElementImpl ftE = ftC.getFlexiTableElement();
 		FlexiTableDataModel<?> dataModel = ftE.getTableDataModel();
 
 		int alignment = fcm.getAlignment();
 		String cssClass = (alignment == FlexiColumnModel.ALIGNMENT_LEFT ? "text-left" : (alignment == FlexiColumnModel.ALIGNMENT_RIGHT ? "text-right" : "text-center"));
-		// add css class for first and last column to support older browsers
-		if (col == 0) cssClass += " b_first_child";
-		if (col == numOfCols-1) cssClass += " b_last_child";				
-		target.append("<td class=\"").append(cssClass).append("\">");
-		if (col == 0) target.append("<a name=\"table\"></a>"); //add once for accessabillitykey
+
+		target.append("<td class=\"").append(cssClass).append(" ")
+		  .append("o_dnd_label", ftE.getColumnIndexForDragAndDropLabel() == fcm.getColumnIndex())
+		  .append("\">");
+		if (col == 0) target.append("<a name='table'></a>"); //add once for accessabillitykey
 
 		int columnIndex = fcm.getColumnIndex();
 		Object cellValue = columnIndex >= 0 ? 
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java
deleted file mode 100644
index cc17eedbe1cc276bbcc19d110a1e0b8086080526..0000000000000000000000000000000000000000
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiDataTablesRenderer.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- * <a href="http://www.openolat.org">
- * OpenOLAT - Online Learning and Training</a><br>
- * <p>
- * Licensed under the Apache License, Version 2.0 (the "License"); <br>
- * you may not use this file except in compliance with the License.<br>
- * You may obtain a copy of the License at the
- * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
- * <p>
- * Unless required by applicable law or agreed to in writing,<br>
- * software distributed under the License is distributed on an "AS IS" BASIS, <br>
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
- * See the License for the specific language governing permissions and <br>
- * limitations under the License.
- * <p>
- * Initial code contributed and copyrighted by<br>
- * frentix GmbH, http://www.frentix.com
- * <p>
- */
-package org.olat.core.gui.components.form.flexible.impl.elements.table;
-
-
-import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.ComponentRenderer;
-import org.olat.core.gui.components.form.flexible.impl.Form;
-import org.olat.core.gui.components.form.flexible.impl.FormJSHelper;
-import org.olat.core.gui.render.RenderResult;
-import org.olat.core.gui.render.Renderer;
-import org.olat.core.gui.render.StringOutput;
-import org.olat.core.gui.render.URLBuilder;
-import org.olat.core.gui.translator.Translator;
-import org.olat.core.util.StringHelper;
-
-/**
- * Render the table using the jQuery plugin DataTables
- * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
- */
-class FlexiDataTablesRenderer extends AbstractFlexiTableRenderer implements ComponentRenderer {
-
-	/**
-	 * @see org.olat.core.gui.components.ComponentRenderer#render(org.olat.core.gui.render.Renderer,
-	 *      org.olat.core.gui.render.StringOutput,
-	 *      org.olat.core.gui.components.Component,
-	 *      org.olat.core.gui.render.URLBuilder,
-	 *      org.olat.core.gui.translator.Translator,
-	 *      org.olat.core.gui.render.RenderResult, java.lang.String[])
-	 */
-	@Override
-	public void render(Renderer renderer, StringOutput target, Component source,
-			URLBuilder ubu, Translator translator, RenderResult renderResult,
-			String[] args) {
-
-		super.render(renderer, target, source, ubu, translator, renderResult, args);
-		
-		FlexiTableComponent ftC = (FlexiTableComponent) source;
-		FlexiTableElementImpl ftE = ftC.getFlexiTableElement();
-		FlexiTableDataModel<?> dataModel = ftE.getTableDataModel();
-		FlexiTableColumnModel columnsModel = dataModel.getTableColumnModel();
-		
-		Form rootForm = ftE.getRootForm();
-		String id = ftC.getFormDispatchId();
-		int loadedRows = dataModel.getRowCount();
-
-		int selectPos = -1;
-		Object selectedObject = ftE.getSelectedObj();
-		if(selectedObject != null) {
-			for(int i=0; i<dataModel.getRowCount(); i++) {
-				if(dataModel.isRowLoaded(i) && selectedObject.equals(dataModel.getObject(i))) {
-					selectPos = i;
-					break;
-				}
-			}
-		}
-		
-		String scrollHeight;
-		String wrapperSelector = ftE.getWrapperSelector();
-		if(StringHelper.containsNonWhitespace(wrapperSelector)) {
-			StringBuilder sb = new StringBuilder();
-			sb.append("Math.max((jQuery('").append(wrapperSelector).append("').height() - 130),100) + 'px'");
-			scrollHeight = sb.toString();
-		} else {
-			scrollHeight = "'100px'";
-		}
-
-		target.append("<script type='text/javascript'>")
-		  .append("/* <![CDATA[ */ \n")
-		  .append("jQuery(function() {\n")
-		  .append(" var scrollHeight = ").append(scrollHeight).append(";\n")
-		  .append(" var selectedIndex =").append(selectPos).append(";\n")
-		  .append("	jQuery('#").append(id).append("').dataTable( {\n")
-		  .append("		'bScrollInfinite': true,\n")
-		  .append("		'bScrollCollapse': true,\n")
-		  .append("		'bFilter': false,\n")
-		  .append("		'sScrollY': ").append(scrollHeight).append(",\n")
-		  .append("		'bProcessing': true,\n")
-		  .append("		'bServerSide': true,\n")
-		  .append("		'iDisplayLength': ").append(ftE.getPageSize()).append(",\n")
-		  .append("		'iDeferLoading': ").append(loadedRows).append(",\n")
-		  .append("		'sAjaxSource': '").append(ftE.getMapperUrl()).append("',\n")
-		  .append("		'oLanguage': {\n")
-		  .append("		  'sInfo': '").append(translator.translate("table.sInfo")).append("',\n")
-		  .append("		  'sEmptyTable': '").append(translator.translate("table.sEmptyTable")).append("'\n")
-		  .append("    },\n")
-		  .append("   'asStripeClasses': ['','b_table_odd'],\n")
-		  .append("		'aoColumns': [\n");
-		int count = 0;
-		if(ftE.isMultiSelect()) {
-			target.append("			{'mData':'multiSelectCol', bSortable: false }\n");
-			count++;
-		}
-		int colDnd = 0;
-		for(int i=0; i<columnsModel.getColumnCount(); i++) {
-			FlexiColumnModel col = columnsModel.getColumnModel(i);
-			if(ftE.isColumnModelVisible(col)) {
-				if(count > 0) target.append(",");
-				count++;
-				target.append("			{'mData':'").append(col.getColumnKey())
-			  	.append("', bSortable: ").append(col.isSortable()).append(" }\n");
-			}
-			if(col.getColumnIndex() == ftE.getColumnLabelForDragAndDrop()) {
-				colDnd = count;
-			}
-		}
-    target.append("		],\n")
-      .append("		'fnRowCallback': function( nRow, aData, iDisplayIndex, iDisplayIndexFull) {\n")
-      .append("     if(selectedIndex == iDisplayIndexFull) {\n")
-      .append("       jQuery(nRow).addClass('o_row_selected');\n")
-      .append("     }\n")
-      .append("			jQuery(nRow).draggable({ \n")
-      .append("				containment: '#o_main',\n")
-      .append("				zIndex: 10000,\n")
-      .append("				cursorAt: {left: 0, top: 0},\n")
-      .append("				accept: function(event,ui){ return true; },\n")
-      .append("				helper: function(event,ui,zt) {\n")
-      .append("				  var helperText = jQuery(this).children(\"td:nth-child(").append(colDnd + 1).append(")\").text();\n")
-      .append("				  return jQuery(\"<div class='ui-widget-header b_table_drag'>\" + helperText + \"</div>\").appendTo('body').css('zIndex',5).show();\n")
-      .append("				}\n")
-      .append("			});\n")
-      .append("		},\n")
-      .append("	  fnInitComplete: function (oSettings, json) {\n")
-      .append("     if(selectedIndex < 0) return;\n")
-      .append("     var scrollTo = 0;\n")
-      .append("     jQuery('#").append(id).append(" tbody tr').each(function(index, el) { ")
-      .append("	    	if(index < selectedIndex) {\n")
-      .append("         scrollTo += jQuery(el).outerHeight();\n")
-      .append("       }\n")
-      .append("	    });\n")
-      .append("     jQuery('#").append(id).append("').parent().scrollTop(scrollTo - 40);\n")
-      .append("	  }\n")
-      .append("	});\n")
-      //clic rows
-      .append("	jQuery('#").append(id).append(" tbody').click(function(event, ui) {\n")
-      .append("   var link = false;\n")
-      .append("   var rowId = null;\n")
-      .append("   if(event.target.tagName == 'A' || event.target.tagName == 'INPUT') {\n")
-      .append("     return;\n")
-      .append("   }\n")
-      .append("   jQuery(event.target).parents().each(function(index,el) {\n")
-      .append("     if(el.tagName == 'A' || el.tagName == 'INPUT') {\n")
-      .append("       link = true;\n")
-      .append("     } else if (el.tagName == 'TR' && rowId == null) {\n")
-      .append("       jQuery('#").append(id).append(" tbody tr').each(function(index, trEl) {\n")
-      .append("         jQuery(trEl).removeClass('o_row_selected');\n")
-      .append("       });\n")
-      .append("       jQuery(el).addClass('o_row_selected');\n")
-      .append("       rowId = jQuery(el).attr('id');\n")
-      .append("       return false;\n")
-      .append("     }\n")
-      .append("   });\n")
-      .append("	  if(!link) {\n")
-      .append(FormJSHelper.generateXHRFnCallVariables(rootForm, id, 1))
-      .append("    o_ffXHREvent(formNam, dispIdField, dispId, eventIdField, eventInt,'rSelect',rowId);")
-      .append("   };")
-      .append("	});\n")
-      .append("});\n")
-      .append("/* ]]> */\n")
-		  .append("</script>\n");
-	}
-
-	@Override
-	protected void renderHeaderSort(StringOutput target, FlexiTableComponent ftC, FlexiColumnModel fcm, int colPos, Translator translator) {
-		//nothing to do, dataTables do it alone
-	}
-}
\ No newline at end of file
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java
index 44333bc3253bea007e82c43a9da8d8f556443c5c..4e4505bd804aba06dd8b1cecd0de5df60eddd522 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableComponent.java
@@ -31,13 +31,11 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.ComponentCollection;
 import org.olat.core.gui.components.ComponentRenderer;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.impl.FormBaseComponentImpl;
-import org.olat.core.gui.render.ValidationResult;
 import org.olat.core.gui.translator.Translator;
 
 /**
@@ -45,7 +43,6 @@ import org.olat.core.gui.translator.Translator;
  */
 public class FlexiTableComponent extends FormBaseComponentImpl implements ComponentCollection {
 
-	private static final ComponentRenderer DATATABLES_RENDERER = new FlexiDataTablesRenderer();
 	private static final ComponentRenderer CLASSIC_RENDERER = new FlexiTableClassicRenderer();
 	private static final ComponentRenderer CUSTOM_RENDERER = new FlexiTableCustomRenderer();
 	
@@ -66,15 +63,6 @@ public class FlexiTableComponent extends FormBaseComponentImpl implements Compon
 		return element;
 	}
 
-	@Override
-	public void validate(UserRequest ureq, ValidationResult vr) {
-		super.validate(ureq, vr);
-		if(element.getRendererType() == FlexiTableRendererType.dataTables) {
-			//inject javascript
-			vr.getJsAndCSSAdder().addRequiredStaticJsFile("js/jquery/datatables/jquery.dataTables.min.js");
-		}
-	}
-
 	@Override
 	public Component getComponent(String name) {
 		FormItem item = element.getFormComponent(name);
@@ -110,7 +98,6 @@ public class FlexiTableComponent extends FormBaseComponentImpl implements Compon
 	public ComponentRenderer getHTMLRendererSingleton() {
 		switch(element.getRendererType()) {
 			case classic: return CLASSIC_RENDERER;
-			case dataTables: return DATATABLES_RENDERER;
 			case custom: return CUSTOM_RENDERER;
 			default: return CLASSIC_RENDERER;
 		}
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java
index 97c50b952c096b288b1a12a3f1c533bb9a9d7050..8d9f07c7de9540f2afb98cf35df1c5eccec82efe 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableCustomRenderer.java
@@ -86,7 +86,7 @@ class FlexiTableCustomRenderer extends AbstractFlexiTableRenderer implements Com
 
 	@Override
 	protected void renderRow(Renderer renderer, StringOutput sb, FlexiTableComponent ftC, String rowIdPrefix,
-			int row, int rows, URLBuilder ubu, Translator translator, RenderResult renderResult) {
+			int row, URLBuilder ubu, Translator translator, RenderResult renderResult) {
 		sb.append("<div class='o_table_row row'>");
 
 		FlexiTableElementImpl ftE = ftC.getFlexiTableElement();
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
index 183d78fbc7578a6d5628cecd525ffa533a05c1ec..a074f0b6c001f9b0e4030d461ca9b7f11f92a92c 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableElementImpl.java
@@ -99,14 +99,13 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	private boolean searchEnabled;
 	private boolean selectAllEnabled;
 	private boolean extendedSearchExpanded = false;
-	private boolean extendedSearchCallout;
 	private int columnLabelForDragAndDrop;
 	
 	private VelocityContainer rowRenderer;
 
 	private FormLink customButton, exportButton;
 	private FormLink searchButton, extendedSearchButton;
-	private FormLink classicTypeButton, customTypeButton, dataTablesTypeButton;
+	private FormLink classicTypeButton, customTypeButton;
 	private TextElement searchFieldEl;
 	private ExtendedFlexiTableSearchController extendedSearchCtrl;
 	
@@ -175,12 +174,12 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	}
 
 	@Override
-	public int getColumnLabelForDragAndDrop() {
+	public int getColumnIndexForDragAndDropLabel() {
 		return columnLabelForDragAndDrop;
 	}
 
 	@Override
-	public void setColumnLabelForDragAndDrop(int columnLabelForDragAndDrop) {
+	public void setColumnIndexForDragAndDropLabel(int columnLabelForDragAndDrop) {
 		this.columnLabelForDragAndDrop = columnLabelForDragAndDrop;
 	}
 
@@ -198,9 +197,6 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		if(classicTypeButton != null) {
 			classicTypeButton.setActive(FlexiTableRendererType.classic == rendererType);
 		}
-		if(dataTablesTypeButton != null) {
-			dataTablesTypeButton.setActive(FlexiTableRendererType.dataTables == rendererType);
-		}
 		// update render type
 		this.rendererType = rendererType;
 		if(component != null) {
@@ -229,17 +225,10 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			classicTypeButton.setIconLeftCSS("o_icon o_icon_table o_icon-lg");
 			classicTypeButton.setActive(FlexiTableRendererType.classic == rendererType);
 			components.put("rTypeClassic", classicTypeButton);
-			//jquery tables
-			dataTablesTypeButton = new FormLinkImpl(dispatchId + "_dataTablesRTypeButton", "rDataTablesRTypeButton", "", Link.BUTTON + Link.NONTRANSLATED);
-			dataTablesTypeButton.setTranslator(translator);
-			dataTablesTypeButton.setIconLeftCSS("o_icon o_icon_table o_icon-lg");
-			dataTablesTypeButton.setActive(FlexiTableRendererType.dataTables == rendererType);
-			components.put("rTypeDataTables", dataTablesTypeButton);
 			
 			if(getRootForm() != null) {
 				rootFormAvailable(customTypeButton);
 				rootFormAvailable(classicTypeButton);
-				rootFormAvailable(dataTablesTypeButton);
 			}
 		}
 	}
@@ -252,10 +241,6 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		return customTypeButton;
 	}
 
-	public FormLink getDataTablesTypeButton() {
-		return dataTablesTypeButton;
-	}
-
 	@Override
 	public boolean isMultiSelect() {
 		return multiSelect;
@@ -469,18 +454,15 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		return extendedSearchExpanded;
 	}
 	
-	public boolean isExtendedSearchCallout() {
-		return extendedSearchCallout;
-	}
+
 	
 	public Component getExtendedSearchComponent() {
 		return (extendedSearchCtrl == null) ? null : extendedSearchCtrl.getInitialComponent();
 	}
 	
 	@Override
-	public void setExtendedSearch(ExtendedFlexiTableSearchController controller, boolean callout) {
+	public void setExtendedSearch(ExtendedFlexiTableSearchController controller) {
 		extendedSearchCtrl = controller;
-		extendedSearchCallout = callout;
 		if(extendedSearchCtrl != null) {
 			extendedSearchCtrl.addControllerListener(this);
 			
@@ -490,10 +472,8 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			extendedSearchButton.setIconLeftCSS("o_icon o_icon_search");
 			components.put("rExtSearchB", extendedSearchButton);
 			rootFormAvailable(extendedSearchButton);
-			
-			if(!callout) {
-				components.put("rExtSearchCmp", controller.getInitialFormItem());
-			}
+
+			components.put("rExtSearchCmp", controller.getInitialFormItem());
 		}
 	}
 	
@@ -668,10 +648,6 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 				&& classicTypeButton.getFormDispatchId().equals(dispatchuri)) {
 			setRendererType(FlexiTableRendererType.classic);
 			saveCustomSettings(ureq);
-		} else if(dataTablesTypeButton != null
-				&& dataTablesTypeButton.getFormDispatchId().equals(dispatchuri)) {
-			setRendererType(FlexiTableRendererType.dataTables);
-			saveCustomSettings(ureq);
 		} else {
 			FlexiTableColumnModel colModel = dataModel.getTableColumnModel();
 			for(int i=colModel.getColumnCount(); i-->0; ) {
@@ -738,10 +714,8 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 				}
 			}
 		}
-		
-		if(rendererType != FlexiTableRendererType.dataTables) {
-			component.setDirty(true);
-		}
+
+		component.setDirty(true);
 	}
 	
 	private void doFilter(String filterKey) {
@@ -766,9 +740,9 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 			currentPage = 0;
 			currentFirstResult = 0;
 
-			List<String> conditionalQueries = Collections.singletonList(filterKey);
+			List<String> addQueries = Collections.singletonList(filterKey);
 			dataSource.clear();
-			dataSource.load(null, conditionalQueries, 0, getPageSize(), orderBy);
+			dataSource.load(null, addQueries, 0, getPageSize(), orderBy);
 		}
 		component.setDirty(true);
 	}
@@ -786,23 +760,13 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 	
 	@Override
 	public void expandExtendedSearch(UserRequest ureq) {
-		if(extendedSearchCallout) {
-			callout = new CloseableCalloutWindowController(ureq, wControl, extendedSearchCtrl.getInitialComponent(),
-				extendedSearchButton, getTranslator().translate("search"), true, "o_sel_flexi_search_callout");
-			callout.activate();
-			callout.addControllerListener(this);
-		} else {
-			component.setDirty(true);
-		}
+		component.setDirty(true);
 		extendedSearchExpanded = true;
 		extendedSearchCtrl.setEnabled(true);
 	}
 	
 	@Override
 	public void collapseExtendedSearch() {
-		if(callout != null) {
-			callout.deactivate();
-		}
 		extendedSearchExpanded = false;
 		extendedSearchCtrl.setEnabled(false);
 	}
@@ -938,8 +902,8 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		getRootForm().fireFormEvent(ureq, new SelectionEvent(ROM_SELECT_EVENT, index, this, FormEvent.ONCLICK));
 	}
 	
-	protected void doSelect(UserRequest ureq, String action, int index) {
-		getRootForm().fireFormEvent(ureq, new SelectionEvent(action, index, this, FormEvent.ONCLICK));
+	protected void doSelect(UserRequest ureq, String selectAction, int index) {
+		getRootForm().fireFormEvent(ureq, new SelectionEvent(selectAction, index, this, FormEvent.ONCLICK));
 	}
 
 	
@@ -1112,7 +1076,6 @@ public class FlexiTableElementImpl extends FormItemImpl implements FlexiTableEle
 		rootFormAvailable(extendedSearchButton);
 		rootFormAvailable(customTypeButton);
 		rootFormAvailable(classicTypeButton);
-		rootFormAvailable(dataTablesTypeButton);
 	}
 	
 	private final void rootFormAvailable(FormItem item) {
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java
index f7710585544cd94f02c884cb49dd46dccfb111fe..0ae502aeb0f14647b6de0778cd0e574f091babc9 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/FlexiTableRendererType.java
@@ -26,7 +26,6 @@ package org.olat.core.gui.components.form.flexible.impl.elements.table;
  */
 public enum FlexiTableRendererType {
 	classic,
-	dataTables,
 	custom
 
 }
diff --git a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiCellRenderer.java b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiCellRenderer.java
index b7fe903db6cc434607b07df5f69395f681e2f8ee..5e9359a00429dc5b0f2553b343bf9652a457e2cc 100644
--- a/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiCellRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/form/flexible/impl/elements/table/StaticFlexiCellRenderer.java
@@ -67,12 +67,12 @@ public class StaticFlexiCellRenderer implements FlexiCellRenderer {
 	public void render(Renderer renderer, StringOutput target, Object cellValue, int row,
 			FlexiTableComponent source, URLBuilder ubu, Translator translator) {
 		
-		String action = getAction();
-		if(StringHelper.containsNonWhitespace(action)) {
+		String cellAction = getAction();
+		if(StringHelper.containsNonWhitespace(cellAction)) {
 			FlexiTableElementImpl ftE = source.getFlexiTableElement();
 			String id = source.getFormDispatchId();
 			Form rootForm = ftE.getRootForm();
-			NameValuePair pair = new NameValuePair(action, Integer.toString(row));
+			NameValuePair pair = new NameValuePair(cellAction, Integer.toString(row));
 			String jsCode = FormJSHelper.getXHRFnCallFor(rootForm, id, 1, pair);
 			target.append("<a href=\"javascript:").append(jsCode).append("\">");
 			if(StringHelper.containsNonWhitespace(iconCSS)) {
diff --git a/src/main/java/org/olat/core/gui/components/tree/MenuTree.java b/src/main/java/org/olat/core/gui/components/tree/MenuTree.java
index 0713271ed41cdcd5dc3a22bc16369debdffa889a..3cacc0ccca56461cdd9d82177318bb8add23b788 100644
--- a/src/main/java/org/olat/core/gui/components/tree/MenuTree.java
+++ b/src/main/java/org/olat/core/gui/components/tree/MenuTree.java
@@ -150,7 +150,6 @@ public class MenuTree extends AbstractComponent {
 			return;
 		}
 		
-		//fxdiff VCRP-9: drag and drop in menu tree
 		String cmd = ureq.getParameter(COMMAND_ID);
 		String nodeId = ureq.getParameter(NODE_IDENT);
 		if(COMMAND_TREENODE_CLICKED.equals(cmd)) {
@@ -192,7 +191,6 @@ public class MenuTree extends AbstractComponent {
 	}
 	
 	// -- recorder methods
-	//fxdiff VCRP-9: drag and drop in menu tree
 	private void handleDropped(UserRequest ureq, String droppedNodeId, String targetNodeId, boolean sibling, boolean atTheEnd) {
 		TreeDropEvent te = new TreeDropEvent(COMMAND_TREENODE_DROP, droppedNodeId, targetNodeId, !sibling, atTheEnd);
 		fireEvent(ureq, te);
diff --git a/src/main/java/org/olat/core/gui/control/floatingresizabledialog/FloatingResizableDialogController.java b/src/main/java/org/olat/core/gui/control/floatingresizabledialog/FloatingResizableDialogController.java
index 3e87c395d4890363b23bc1ab35c2b4fe8086c094..ac6b17387e29a287d66e17996623a6275d403ee6 100644
--- a/src/main/java/org/olat/core/gui/control/floatingresizabledialog/FloatingResizableDialogController.java
+++ b/src/main/java/org/olat/core/gui/control/floatingresizabledialog/FloatingResizableDialogController.java
@@ -31,7 +31,6 @@ import java.util.regex.Pattern;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSComponent;
 import org.olat.core.gui.components.velocity.VelocityContainer;
 import org.olat.core.gui.control.Event;
 import org.olat.core.gui.control.WindowControl;
@@ -124,10 +123,6 @@ public class FloatingResizableDialogController extends BasicController {
 		wrapper.put("panelContent", content);
 		if (collabsibleContent != null) {
 			wrapper.put("collapsibleContent", collabsibleContent);
-			
-			String[] js = new String[]{"js/jquery/uilayout/jquery.layout-latest.min.js"};
-			JSAndCSSComponent jsAndCssComp = new JSAndCSSComponent("layouting", js, null);
-			wrapper.put("layout", jsAndCssComp);
 		}
 		
 		String escapedTitle = StringHelper.escapeHtml(title);
diff --git a/src/main/java/org/olat/core/gui/exception/_content/exception_page.html b/src/main/java/org/olat/core/gui/exception/_content/exception_page.html
index cd525c97f4763ae0091e54192a01bfb4675a519e..d37989a4c2d624d1534b8c4a31b4cfa932bee375 100644
--- a/src/main/java/org/olat/core/gui/exception/_content/exception_page.html
+++ b/src/main/java/org/olat/core/gui/exception/_content/exception_page.html
@@ -78,7 +78,6 @@ var o_info = new Object();
 
 ## Always loaded
 <link type="text/css" href='$r.staticLink("js/jquery/fullcalendar/fullcalendar.css")' rel="stylesheet"/>
-<link type="text/css" href='$r.staticLink("js/jquery/datatables/css/jquery.dataTables.css")' rel="stylesheet"/>
 ## FIXME:oo10 add plugin min
 ##<link type="text/css" href='$r.staticLink("js/js.plugins.min.css")' rel="stylesheet"/>
 <link type="text/css" href='$r.staticLink("js/jquery/ui/jquery-ui-1.10.4.custom.min.css")' rel="stylesheet"/>
diff --git a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
index 91507e98cf8cd47bdda595d72ad5b279e78a55b2..cc9852878f0c5df2962962d0d0e48db90b5bfa94 100644
--- a/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
+++ b/src/main/java/org/olat/group/ui/main/AbstractBusinessGroupListController.java
@@ -198,7 +198,7 @@ public abstract class AbstractBusinessGroupListController extends FormBasicContr
 		listenTo(searchCtrl);
 		
 		tableEl.setSearchEnabled(true);
-		tableEl.setExtendedSearch(searchCtrl, false);
+		tableEl.setExtendedSearch(searchCtrl);
 		
 		initButtons(formLayout, ureq);
 	}
diff --git a/src/main/java/org/olat/login/_chelp/about.html b/src/main/java/org/olat/login/_chelp/about.html
index 0edd9d2a7c41345af8ce6dc2ed31508314b572ec..556e23135cee90d2256d48ed429952cdd3acda1c 100644
--- a/src/main/java/org/olat/login/_chelp/about.html
+++ b/src/main/java/org/olat/login/_chelp/about.html
@@ -172,7 +172,6 @@ This product uses software based on the BSD License
 * Antlr (BSD license) [http://www.antlr.org]
 * PostgreSQL JDBC Driver(BSD License) [http://jdbc.postgresql.org]
 * Modernizr JS Library (BSD License) [http://modernizr.com]
-* Datatable JavaScript table UI library (BSD License) [https://datatables.net]
 
 -----------------------------------------------------------------------
 This product uses software based on the Common Public License Version
diff --git a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java
index 9ad21354344840368956c57b8bc1ac1cda429e08..b7c6150dd4e2ddb91de946c578c559ff9eef8a98 100644
--- a/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/AbstractItemListController.java
@@ -35,6 +35,7 @@ import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItem;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement;
+import org.olat.core.gui.components.form.flexible.elements.FlexiTableSortOptions;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
@@ -81,19 +82,19 @@ public abstract class AbstractItemListController extends FormBasicController
 	protected final QPoolService qpoolService;
 	
 	private EventBus eventBus;
-	private QuestionItemsSource source;
+	private QuestionItemsSource itemsSource;
 	
 	public AbstractItemListController(UserRequest ureq, WindowControl wControl, QuestionItemsSource source, String key) {
 		super(ureq, wControl, "item_list");
 
-		this.source = source;
+		this.itemsSource = source;
 		markManager = CoreSpringFactory.getImpl(MarkManager.class);
 		qpoolService = CoreSpringFactory.getImpl(QPoolService.class);
 
 		eventBus = ureq.getUserSession().getSingleUserEventCenter();
 		eventBus.registerFor(this, getIdentity(), QuestionPoolMainEditorController.QITEM_MARKED);
 		
-		extendedSearchCtrl = new ExtendedSearchController(ureq, getWindowControl(), key);
+		extendedSearchCtrl = new ExtendedSearchController(ureq, getWindowControl(), key, mainForm);
 		listenTo(extendedSearchCtrl);
 		
 		initForm(ureq);
@@ -138,13 +139,15 @@ public abstract class AbstractItemListController extends FormBasicController
 		
 		model = new QuestionItemDataModel(columnsModel, this, getTranslator());
 		itemsTable = uifactory.addTableElement(ureq, getWindowControl(), "items", model, 50, true, getTranslator(), formLayout);
-		itemsTable.setWrapperSelector("#qitems");
+		itemsTable.setWrapperSelector("qitems");
 		itemsTable.setSelectAllEnable(true);
 		itemsTable.setMultiSelect(true);
 		itemsTable.setSearchEnabled(true);
-		itemsTable.setExtendedSearch(extendedSearchCtrl, true);
-		itemsTable.setRendererType(FlexiTableRendererType.dataTables);
-		itemsTable.setColumnLabelForDragAndDrop(Cols.title.ordinal());
+		itemsTable.setSortSettings(new FlexiTableSortOptions(true));
+		itemsTable.setExtendedSearch(extendedSearchCtrl);
+		itemsTable.setAvailableRendererTypes(FlexiTableRendererType.classic, FlexiTableRendererType.custom);
+		itemsTable.setRendererType(FlexiTableRendererType.classic);
+		itemsTable.setColumnIndexForDragAndDropLabel(Cols.title.ordinal());
 
 		initButtons(ureq, formLayout);
 	}
@@ -152,7 +155,7 @@ public abstract class AbstractItemListController extends FormBasicController
 	protected abstract void initButtons(UserRequest ureq, FormItemContainer formLayout);
 
     protected void setSource(QuestionItemsSource source) {
-        this.source = source;
+        this.itemsSource = source;
     }
 	
 	protected FlexiTableElement getItemsTable() {
@@ -172,11 +175,11 @@ public abstract class AbstractItemListController extends FormBasicController
 	}
 	
 	public QuestionItemsSource getSource() {
-		return source;
+		return itemsSource;
 	}
 	
 	public void updateSource(QuestionItemsSource source) {
-		this.source = source;
+		this.itemsSource = source;
 		model.clear();
 		itemsTable.reset();
 	}
@@ -207,7 +210,8 @@ public abstract class AbstractItemListController extends FormBasicController
 				} else if("select-item".equals(se.getCommand())) {
 					ItemRow row = getModel().getObject(se.getIndex());
 					if(row != null) {
-						doSelect(ureq, row);
+						//doSelect(ureq, row);
+						doClick(ureq, row);
 					}
 				}
 			}
@@ -325,7 +329,7 @@ public abstract class AbstractItemListController extends FormBasicController
 
 	@Override
 	public int getRowCount() {
-		return source.getNumOfItems();
+		return itemsSource.getNumOfItems();
 	}
 
 	@Override
@@ -335,7 +339,7 @@ public abstract class AbstractItemListController extends FormBasicController
 			itemToReload.add(row.getKey());
 		}
 
-		List<QuestionItemView> reloadedItems = source.getItems(itemToReload);
+		List<QuestionItemView> reloadedItems = itemsSource.getItems(itemToReload);
 		List<ItemRow> reloadedRows = new ArrayList<ItemRow>(reloadedItems.size());
 		for(QuestionItemView item:reloadedItems) {
 			ItemRow reloadedRow = forgeRow(item);
@@ -346,7 +350,7 @@ public abstract class AbstractItemListController extends FormBasicController
 
 	@Override
 	public ResultInfos<ItemRow> getRows(String query, List<String> condQueries, int firstResult, int maxResults, SortKey... orderBy) {
-		ResultInfos<QuestionItemView> items = source.getItems(query, condQueries, firstResult, maxResults, orderBy);
+		ResultInfos<QuestionItemView> items = itemsSource.getItems(query, condQueries, firstResult, maxResults, orderBy);
 		List<ItemRow> rows = new ArrayList<ItemRow>(items.getObjects().size());
 		for(QuestionItemView item:items.getObjects()) {
 			ItemRow row = forgeRow(item);
diff --git a/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java b/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java
index 3294ae036ef86f132d659a046de8cd9d8c2b077c..52cd89cc23fa59e6fd75ad0c3663e251eef0d411 100644
--- a/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/CollectionListController.java
@@ -92,7 +92,7 @@ public class CollectionListController extends FormBasicController {
 		model = new CollectionsDataModel(colls, columnsModel);
 		collectionsTable = uifactory.addTableElement(ureq, getWindowControl(), "collections", model, getTranslator(), formLayout);
 		collectionsTable.setMultiSelect(true);
-		collectionsTable.setRendererType(FlexiTableRendererType.dataTables);
+		collectionsTable.setRendererType(FlexiTableRendererType.classic);
 		
 		FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
 		buttonsCont.setRootForm(mainForm);
diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java
index 470f842e53cd34c3969a211de83cae40c41b9e47..1574136ccd405892c4c3a66eb6896e7d0a0e7b51 100644
--- a/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/QuestionPoolMainEditorController.java
@@ -412,11 +412,10 @@ public class QuestionPoolMainEditorController extends BasicController implements
 	
 	private void doSelectPool(UserRequest ureq, Pool pool, TreeNode node, List<ContextEntry> entries, StateEntry state) {
 		ControlledTreeNode cNode = (ControlledTreeNode)node;
-		Roles roles = ureq.getUserSession().getRoles();
 		QuestionsController selectedPoolCtrl = cNode.getController();
 
 		DefaultItemsSource source = new PoolItemsSource(getIdentity(), roles, pool);
-		source.setRemoveEnabled(isShareAdmin(roles, pool));
+		source.setRemoveEnabled(isShareAdmin(pool));
 		if(selectedPoolCtrl == null) {
 			WindowControl swControl = addToHistory(ureq, pool, null);
 			selectedPoolCtrl = new QuestionsController(ureq, swControl, source, "poll-" + pool.getKey());
@@ -436,7 +435,7 @@ public class QuestionPoolMainEditorController extends BasicController implements
 	 * @param pool
 	 * @return
 	 */
-	private boolean isShareAdmin(Roles roles, Pool pool) {
+	private boolean isShareAdmin(Pool pool) {
 		return roles != null && (roles.isOLATAdmin() || roles.isPoolAdmin() || pool.isPublicPool()
 				|| qpoolService.isOwner(getIdentity(), pool));
 	}
@@ -444,8 +443,7 @@ public class QuestionPoolMainEditorController extends BasicController implements
 	private void doSelectGroup(UserRequest ureq, BusinessGroup group, TreeNode node, List<ContextEntry> entries, StateEntry state) {
 		ControlledTreeNode cNode = (ControlledTreeNode)node;
 		QuestionsController sharedItemsCtrl = cNode.getController();
-		Roles roles = ureq.getUserSession().getRoles();
-		boolean shareAdmin = isShareAdmin(roles, group);
+		boolean shareAdmin = isShareAdmin(group);
 		SharedItemsSource source = new SharedItemsSource(group, getIdentity(), roles, shareAdmin);
 
 		if(sharedItemsCtrl == null) {
@@ -461,7 +459,7 @@ public class QuestionPoolMainEditorController extends BasicController implements
 		setContent(ureq, sharedItemsCtrl, entries, state);
 	}
 	
-	private boolean isShareAdmin(Roles roles, BusinessGroup group) {
+	private boolean isShareAdmin(BusinessGroup group) {
 		return roles != null && (roles.isOLATAdmin() || roles.isPoolAdmin()
 				|| businessGroupService.isIdentityInBusinessGroup(getIdentity(), group.getKey(), true, false, null));
 	}
diff --git a/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java b/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java
index fe52c0f2af5a3b33522963193b6664177df87705..392d5488d505bafc5fbf35c9b227164e5e98b647 100644
--- a/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/QuestionsController.java
@@ -23,10 +23,8 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
-import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
-import org.olat.core.gui.components.htmlheader.jscss.JSAndCSSComponent;
 import org.olat.core.gui.components.link.Link;
 import org.olat.core.gui.components.link.LinkFactory;
 import org.olat.core.gui.components.stack.BreadcrumbPanel;
@@ -49,6 +47,7 @@ import org.olat.modules.qpool.QuestionItemShort;
 import org.olat.modules.qpool.QuestionItemView;
 import org.olat.modules.qpool.ui.events.QItemViewEvent;
 import org.olat.modules.qpool.ui.events.QPoolEvent;
+import org.springframework.beans.factory.annotation.Autowired;
 
 /**
  * 
@@ -73,14 +72,14 @@ public class QuestionsController extends BasicController implements Activateable
 	private final VelocityContainer mainVC;
 	private DialogBoxController confirmDeleteBox;
 	
-	private final QPoolService qpoolService;
+	@Autowired
+	private QPoolService qpoolService;
 	private QuestionItemsSource dataSource;
 	
 	public QuestionsController(UserRequest ureq, WindowControl wControl, QuestionItemsSource source, String key) {
 		super(ureq, wControl);
 		
 		this.dataSource = source;
-		qpoolService = CoreSpringFactory.getImpl(QPoolService.class);
 
 		listCtrl = new QuestionListController(ureq, wControl, source, key);
 		listenTo(listCtrl);
@@ -102,10 +101,6 @@ public class QuestionsController extends BasicController implements Activateable
 		}
 		selectItem = LinkFactory.createButton("select.item", mainVC, this);
 		selectItem.setEnabled(false);
-
-		String[] js = new String[]{"js/jquery/uilayout/jquery.layout-latest.min.js"};
-		JSAndCSSComponent jsAndCssComp = new JSAndCSSComponent("layouting", js, null);
-		mainVC.put("layout", jsAndCssComp);
 		
 		Object northHeight = ureq.getUserSession().getGuiPreferences().get(source.getClass(), SPLIT_VIEW_NORTH_HEIGHT);
 		Object westWidth = ureq.getUserSession().getGuiPreferences().get(source.getClass(), SPLIT_VIEW_WEST_WIDTH);
@@ -246,6 +241,8 @@ public class QuestionsController extends BasicController implements Activateable
 		previewCtrl.updateItem(ureq, item);
 		
 		selectItem.setEnabled(true);
+		
+		mainVC.contextPut("details", Boolean.TRUE);
 	}
 	
 	private void doDelete(UserRequest ureq, QuestionItemShort item) {
diff --git a/src/main/java/org/olat/modules/qpool/ui/_content/items.html b/src/main/java/org/olat/modules/qpool/ui/_content/items.html
index aef8004559345fb672bed1d0dfe9995afdbf56ec..621431199e26006f26049c4bcead4ef9903c33db 100644
--- a/src/main/java/org/olat/modules/qpool/ui/_content/items.html
+++ b/src/main/java/org/olat/modules/qpool/ui/_content/items.html
@@ -1,83 +1,15 @@
-<div id="qpoolcontainer">
-	<div id="qitems" class="pane ui-layout-north">$r.render("items")</div>
-	<div id="qdetails" class="pane ui-layout-center">$r.render("details")</div>
-	<div id="qpreview" class="pane ui-layout-west">$r.render("preview")</div>
-</div>
-<div id="qbuttons" class="b_clearfix o_qpool_button_bar_box">
-	<div class="o_buttons_box_center">
-		$r.render("select.item")
-		#if($r.available("delete.item"))
-			$r.render("delete.item")
-		#end
+#if($details)
+	<div class="container-fluid">
+		<div class="row">
+			<div class="col-sm-4">
+				$r.render("items")
+			</div>
+			<div class="col-sm-8">
+				$r.render("details")
+				$r.render("preview")
+			</div>
+		</div>
 	</div>
-</div>
-<script type="text/javascript">
-## global variable to initialize the qPool view
-var qPoolInit = function() {	
-	if (jQuery('#qpoolcontainer').length == 0) {
-		## detatch on-resize code and remove global method code
-		jQuery(window).off("resize", qPoolInit);
-		delete window.qPoolInit;
-	}
-	
-	## padding arount table = relative position of table (space for search field) + height of action buttons below table + some extra space
-	var dataTablesPos = jQuery('.dataTables_wrapper').position()
-	var panePadding = (dataTablesPos ? dataTablesPos.top : 0) + jQuery('.o_qpool_button_bar_box').height() + jQuery('.b_table_footer').height() + 80;
-
-	## Calculate max height to use full browser height minus the header. Footer can be pushed below to max for table space
-	var winHeight = jQuery(window).height();
-	var containerTop = jQuery('#qpoolcontainer').offset().top;
-	var buttonsHeight = jQuery('#qbuttons').height()
-	var maxHeight = winHeight - containerTop - buttonsHeight;
-	## Add footer when enouth space
-	if (maxHeight > 1000) {
-		maxHeight -= jQuery('#b_footer').height() + 50;
-	}
-
-	## Calculate width and height for layouter
-	var width = jQuery('#o_main_center_content_inner').width();
-	var northHeight = '$northHeight';
-	var westWidth = '$westWidth';
-	var centerWidth = '50%';
-	if(northHeight == null || northHeight == "") {
-		northHeight = '50%';
-	}
-	if(westWidth == null || westWidth == "") {
-		westWidth = '50%';
-	} else {
-		centerWidth = width - westWidth;
-	}
-
-	jQuery('#qpoolcontainer').width(width).height(maxHeight).layout({
-		north: { size: northHeight },
-		center: { size: centerWidth },
-		west: { size: westWidth },
-		south: {},
-		north__onresize: function (pane, ui) {
-			var paneHeight = ui.height();
-			jQuery('#$tableId').each(function(index, el) {
-				var oSettings = jQuery(el).dataTable().fnSettings();
-				oSettings.oScroll.sY = (paneHeight - panePadding) + "px";
-				jQuery('div.dataTables_scrollBody', jQuery('#qitems')).height(paneHeight - panePadding);
-			});
-			jQuery.post('$r.commandURI("saveNorthHeight")' + paneHeight);
-		},
-		west__onresize: function (pane, ui) {
-			jQuery.post('$r.commandURI("saveWestWidth")' + ui.width());
-		}
-	});
-	
-	jQuery('#$tableId').each(function(index, el) {
-		var paneHeight = jQuery('#qitems').height();
-		var oSettings = jQuery(el).dataTable().fnSettings();
-		oSettings.oScroll.sY = (paneHeight - panePadding) + "px";
-		jQuery('div.dataTables_scrollBody', jQuery('#qitems')).height(paneHeight - panePadding);
-	});
-}
-
-## initialize pool view when done with rendering and execute again on window resize
-jQuery(function() {
-	qPoolInit();
-	jQuery(window).on("resize", qPoolInit);
-});
-</script>
\ No newline at end of file
+#else
+	$r.render("items")
+#end
diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java
index 795172d87a6dd2c882c178ef0c3f0b9d6da59a59..b6b555660d69a5e6c6c18a5242a2d5127eac4932 100644
--- a/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/metadata/ExtendedSearchController.java
@@ -30,6 +30,7 @@ import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
 import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
+import org.olat.core.gui.components.form.flexible.impl.Form;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
 import org.olat.core.gui.components.form.flexible.impl.FormEvent;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
@@ -73,8 +74,8 @@ public class ExtendedSearchController extends FormBasicController implements Ext
 	
 	private final QPoolService qpoolService;
 
-	public ExtendedSearchController(UserRequest ureq, WindowControl wControl, String prefsKey) {
-		super(ureq, wControl, "extended_search");
+	public ExtendedSearchController(UserRequest ureq, WindowControl wControl, String prefsKey, Form mainForm) {
+		super(ureq, wControl, LAYOUT_CUSTOM, "extended_search", mainForm);
 		setTranslator(Util.createPackageTranslator(QuestionsController.class, getLocale(), getTranslator()));
 		
 		qpoolService = CoreSpringFactory.getImpl(QPoolService.class);
@@ -107,6 +108,7 @@ public class ExtendedSearchController extends FormBasicController implements Ext
 		buttonsCont.setRootForm(mainForm);
 		formLayout.add(buttonsCont);
 		searchButton = uifactory.addFormLink("search", buttonsCont, Link.BUTTON);
+		uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl());
 	}
 	
 	@Override
@@ -121,6 +123,11 @@ public class ExtendedSearchController extends FormBasicController implements Ext
 		}
 	}
 
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+
 	@Override
 	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
 		if(source == searchButton) {
diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java b/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java
index d85e1174d396f84871e308338678b8c23956031d..024fef74d92fa2e7e6e237673b519742ab2bc778 100644
--- a/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java
+++ b/src/main/java/org/olat/modules/qpool/ui/metadata/MetadatasController.java
@@ -260,13 +260,13 @@ public class MetadatasController extends BasicController {
 		return item;
 	}
 	
-	private void reloadData(QuestionItem item) {
-		this.item = item;
-		generalCtrl.setItem(item);
-		educationalCtrl.setItem(item);
-		questionCtrl.setItem(item);
-		lifecycleCtrl.setItem(item);
-		rightsCtrl.setItem(item);
-		technicalCtrl.setItem(item);
+	private void reloadData(QuestionItem reloadedItem) {
+		this.item = reloadedItem;
+		generalCtrl.setItem(reloadedItem);
+		educationalCtrl.setItem(reloadedItem);
+		questionCtrl.setItem(reloadedItem);
+		lifecycleCtrl.setItem(reloadedItem);
+		rightsCtrl.setItem(reloadedItem);
+		technicalCtrl.setItem(reloadedItem);
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/modules/qpool/ui/metadata/_content/extended_search.html b/src/main/java/org/olat/modules/qpool/ui/metadata/_content/extended_search.html
index 76a3714158f71256c004bad98f059cb6fe1573cf..90ddfcfc1beaff5a3cd7c74cff3dba8a53ebaf2a 100644
--- a/src/main/java/org/olat/modules/qpool/ui/metadata/_content/extended_search.html
+++ b/src/main/java/org/olat/modules/qpool/ui/metadata/_content/extended_search.html
@@ -1,11 +1,18 @@
-<div class="b_clearfix"><table><tbody>
+<table class="table"><tbody>
 #foreach($query in $uiQueries)
 	<tr>
 		<td>$r.render($query.attributChoice.name)</td>
 		<td>$r.render($query.parameterItem.name)</td>
-		<td>$r.render($query.addButton.component.componentName)</td>
-		<td>$r.render($query.removeButton.component.componentName)</td>
+		<td>
+			$r.render($query.addButton.component.componentName)
+			$r.render($query.removeButton.component.componentName)
+		</td>
 	</tr>
 #end
-</tbody></table></div>
-$r.render("buttons")
\ No newline at end of file
+</tbody></table>
+<div class="container-fluid">
+	<div class="row"><div class="col-sm-offset-3 col-sm-9">
+		$r.render("buttons")
+	</div></div>
+</div>
+
diff --git a/src/main/java/org/olat/repository/ui/author/AuthorListController.java b/src/main/java/org/olat/repository/ui/author/AuthorListController.java
index e523bbb05a1a999c5b33a34ab716e18f3ea5b57b..abed4520f7de00f2ee7184d1b8afb0baccdb6f9b 100644
--- a/src/main/java/org/olat/repository/ui/author/AuthorListController.java
+++ b/src/main/java/org/olat/repository/ui/author/AuthorListController.java
@@ -218,7 +218,7 @@ public class AuthorListController extends FormBasicController implements Activat
 		tableEl = uifactory.addTableElement(ureq, getWindowControl(), "table", model, 20, !startExtendedSearch, getTranslator(), formLayout);
 		tableEl.setSearchEnabled(true);
 		tableEl.setExportEnabled(true);
-		tableEl.setExtendedSearch(searchCtrl, false);
+		tableEl.setExtendedSearch(searchCtrl);
 		tableEl.setCustomizeColumns(true);
 		tableEl.setElementCssClass("o_coursetable");
 		tableEl.setMultiSelect(true);
diff --git a/src/main/webapp/static/js/jquery/datatables/css/jquery.dataTables.css b/src/main/webapp/static/js/jquery/datatables/css/jquery.dataTables.css
deleted file mode 100644
index 35f16e64ab3c86248b23289a57c64de1c2f6da69..0000000000000000000000000000000000000000
--- a/src/main/webapp/static/js/jquery/datatables/css/jquery.dataTables.css
+++ /dev/null
@@ -1,46 +0,0 @@
-table.dataTable{margin:0 auto;clear:both;width:100%}
-table.dataTable thead th{padding:3px 18px 3px 10px;border-bottom:1px solid black;font-weight:bold;cursor:pointer;*cursor:hand}
-table.dataTable tfoot th{padding:3px 18px 3px 10px;border-top:1px solid black;font-weight:bold}
-table.dataTable td{padding:3px 10px}
-table.dataTable td.center,table.dataTable td.dataTables_empty{text-align:center}
-table.dataTable tr.odd{background-color:#e2e4ff}
-table.dataTable tr.even{background-color:white}
-table.dataTable tr.odd td.sorting_1{background-color:#d3d6ff}
-table.dataTable tr.odd td.sorting_2{background-color:#dadcff}
-table.dataTable tr.odd td.sorting_3{background-color:#e0e2ff}
-table.dataTable tr.even td.sorting_1{background-color:#eaebff}
-table.dataTable tr.even td.sorting_2{background-color:#f2f3ff}
-table.dataTable tr.even td.sorting_3{background-color:#f9f9ff}
-.dataTables_wrapper{position:relative;clear:both;*zoom:1}
-.dataTables_length{float:left}
-.dataTables_filter{float:right;text-align:right}
-.dataTables_info{clear:both;float:left}
-.dataTables_paginate{float:right;text-align:right}
-.paginate_disabled_previous,.paginate_enabled_previous,.paginate_disabled_next,.paginate_enabled_next{height:19px;float:left;cursor:pointer;*cursor:hand;color:#111!important}
-.paginate_disabled_previous:hover,.paginate_enabled_previous:hover,.paginate_disabled_next:hover,.paginate_enabled_next:hover{text-decoration:none!important}
-.paginate_disabled_previous:active,.paginate_enabled_previous:active,.paginate_disabled_next:active,.paginate_enabled_next:active{outline:0}
-.paginate_disabled_previous,.paginate_disabled_next{color:#666!important}
-.paginate_disabled_previous,.paginate_enabled_previous{padding-left:23px}
-.paginate_disabled_next,.paginate_enabled_next{padding-right:23px;margin-left:10px}
-.paginate_enabled_previous{background:url('../images/back_enabled.png') no-repeat top left}
-.paginate_enabled_previous:hover{background:url('../images/back_enabled_hover.png') no-repeat top left}
-.paginate_disabled_previous{background:url('../images/back_disabled.png') no-repeat top left}
-.paginate_enabled_next{background:url('../images/forward_enabled.png') no-repeat top right}
-.paginate_enabled_next:hover{background:url('../images/forward_enabled_hover.png') no-repeat top right}
-.paginate_disabled_next{background:url('../images/forward_disabled.png') no-repeat top right}
-.paging_full_numbers{height:22px;line-height:22px}
-.paging_full_numbers a:active{outline:0}
-.paging_full_numbers a:hover{text-decoration:none}
-.paging_full_numbers a.paginate_button,.paging_full_numbers a.paginate_active{border:1px solid #aaa;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;padding:2px 5px;margin:0 3px;cursor:pointer;*cursor:hand;color:#333!important}
-.paging_full_numbers a.paginate_button{background-color:#ddd}
-.paging_full_numbers a.paginate_button:hover{background-color:#ccc;text-decoration:none!important}
-.paging_full_numbers a.paginate_active{background-color:#99b3ff}
-.dataTables_processing{position:absolute;top:50%;left:50%;width:250px;height:30px;margin-left:-125px;margin-top:-15px;padding:14px 0 2px 0;border:1px solid #ddd;text-align:center;color:#999;font-size:14px;background-color:white}
-.sorting{background:url('../images/sort_both.png') no-repeat center right}
-.sorting_asc{background:url('../images/sort_asc.png') no-repeat center right}
-.sorting_desc{background:url('../images/sort_desc.png') no-repeat center right}
-.sorting_asc_disabled{background:url('../images/sort_asc_disabled.png') no-repeat center right}
-.sorting_desc_disabled{background:url('../images/sort_desc_disabled.png') no-repeat center right}
-table.dataTable thead th:active,table.dataTable thead td:active{outline:0}
-.dataTables_scroll{clear:both}
-.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}
\ No newline at end of file
diff --git a/src/main/webapp/static/js/jquery/datatables/images/back_disabled.png b/src/main/webapp/static/js/jquery/datatables/images/back_disabled.png
deleted file mode 100644
index 881de7976ff98955e2a5487dca66e618a0655f3d..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/back_disabled.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/back_enabled.png b/src/main/webapp/static/js/jquery/datatables/images/back_enabled.png
deleted file mode 100644
index c608682b04a6d9b8002602450c8ef7e80ebba099..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/back_enabled.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/back_enabled_hover.png b/src/main/webapp/static/js/jquery/datatables/images/back_enabled_hover.png
deleted file mode 100644
index d300f1064b3beac1d7d5274e294494d3143e53a2..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/back_enabled_hover.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/forward_disabled.png b/src/main/webapp/static/js/jquery/datatables/images/forward_disabled.png
deleted file mode 100644
index 6a6ded7de821619aedc71d1738c0b73463a4452e..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/forward_disabled.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/forward_enabled.png b/src/main/webapp/static/js/jquery/datatables/images/forward_enabled.png
deleted file mode 100644
index a4e6b5384b8454ee7f44a8f7c75b0321b7eeb9b1..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/forward_enabled.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/forward_enabled_hover.png b/src/main/webapp/static/js/jquery/datatables/images/forward_enabled_hover.png
deleted file mode 100644
index fc46c5ebf0524b72a509fe2d7c1bc74995cb8a9d..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/forward_enabled_hover.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/sort_asc.png b/src/main/webapp/static/js/jquery/datatables/images/sort_asc.png
deleted file mode 100644
index a88d7975fe9017e4e5f2289a94bd1ed66a5f59dc..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/sort_asc.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/sort_asc_disabled.png b/src/main/webapp/static/js/jquery/datatables/images/sort_asc_disabled.png
deleted file mode 100644
index 4e144cf0b1f786a9248a2998311e8109998d8a2d..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/sort_asc_disabled.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/sort_both.png b/src/main/webapp/static/js/jquery/datatables/images/sort_both.png
deleted file mode 100644
index 18670406bc01ab2721781822dd6478917745ff54..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/sort_both.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/sort_desc.png b/src/main/webapp/static/js/jquery/datatables/images/sort_desc.png
deleted file mode 100644
index def071ed5afd264a036f6d9e75856366fd6ad153..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/sort_desc.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/images/sort_desc_disabled.png b/src/main/webapp/static/js/jquery/datatables/images/sort_desc_disabled.png
deleted file mode 100644
index 7824973cc60fc1841b16f2cb39323cefcdc3f942..0000000000000000000000000000000000000000
Binary files a/src/main/webapp/static/js/jquery/datatables/images/sort_desc_disabled.png and /dev/null differ
diff --git a/src/main/webapp/static/js/jquery/datatables/jquery.dataTables.js b/src/main/webapp/static/js/jquery/datatables/jquery.dataTables.js
deleted file mode 100644
index 1d8a220ba8077aa314a28b90331c7cba9b4811c8..0000000000000000000000000000000000000000
--- a/src/main/webapp/static/js/jquery/datatables/jquery.dataTables.js
+++ /dev/null
@@ -1,12099 +0,0 @@
-/**
- * @summary     DataTables
- * @description Paginate, search and sort HTML tables
- * @version     1.9.4
- * @file        jquery.dataTables.js
- * @author      Allan Jardine (www.sprymedia.co.uk)
- * @contact     www.sprymedia.co.uk/contact
- *
- * @copyright Copyright 2008-2012 Allan Jardine, all rights reserved.
- *
- * This source file is free software, under either the GPL v2 license or a
- * BSD style license, available at:
- *   http://datatables.net/license_gpl2
- *   http://datatables.net/license_bsd
- * 
- * This source file is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
- * 
- * For details please refer to: http://www.datatables.net
- */
-
-/*jslint evil: true, undef: true, browser: true */
-/*globals $, jQuery,define,_fnExternApiFunc,_fnInitialise,_fnInitComplete,_fnLanguageCompat,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnCreateTr,_fnGatherData,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnServerParams,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAdjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnDetectHeader,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap,_fnGetRowData,_fnGetCellData,_fnSetCellData,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnApplyColumnDefs,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnJsonString,_fnRender,_fnNodeToColumnIndex,_fnInfoMacros,_fnBrowserDetect,_fnGetColumns*/
-
-(/** @lends <global> */function( window, document, undefined ) {
-
-(function( factory ) {
-	"use strict";
-
-	// Define as an AMD module if possible
-	if ( typeof define === 'function' && define.amd )
-	{
-		define( ['jquery'], factory );
-	}
-	/* Define using browser globals otherwise
-	 * Prevent multiple instantiations if the script is loaded twice
-	 */
-	else if ( jQuery && !jQuery.fn.dataTable )
-	{
-		factory( jQuery );
-	}
-}
-(/** @lends <global> */function( $ ) {
-	"use strict";
-	/** 
-	 * DataTables is a plug-in for the jQuery Javascript library. It is a 
-	 * highly flexible tool, based upon the foundations of progressive 
-	 * enhancement, which will add advanced interaction controls to any 
-	 * HTML table. For a full list of features please refer to
-	 * <a href="http://datatables.net">DataTables.net</a>.
-	 *
-	 * Note that the <i>DataTable</i> object is not a global variable but is
-	 * aliased to <i>jQuery.fn.DataTable</i> and <i>jQuery.fn.dataTable</i> through which 
-	 * it may be  accessed.
-	 *
-	 *  @class
-	 *  @param {object} [oInit={}] Configuration object for DataTables. Options
-	 *    are defined by {@link DataTable.defaults}
-	 *  @requires jQuery 1.3+
-	 * 
-	 *  @example
-	 *    // Basic initialisation
-	 *    $(document).ready( function {
-	 *      $('#example').dataTable();
-	 *    } );
-	 *  
-	 *  @example
-	 *    // Initialisation with configuration options - in this case, disable
-	 *    // pagination and sorting.
-	 *    $(document).ready( function {
-	 *      $('#example').dataTable( {
-	 *        "bPaginate": false,
-	 *        "bSort": false 
-	 *      } );
-	 *    } );
-	 */
-	var DataTable = function( oInit )
-	{
-		
-		
-		/**
-		 * Add a column to the list used for the table with default values
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {node} nTh The th element for this column
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAddColumn( oSettings, nTh )
-		{
-			var oDefaults = DataTable.defaults.columns;
-			var iCol = oSettings.aoColumns.length;
-			var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
-				"sSortingClass": oSettings.oClasses.sSortable,
-				"sSortingClassJUI": oSettings.oClasses.sSortJUI,
-				"nTh": nTh ? nTh : document.createElement('th'),
-				"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
-				"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
-				"mData": oDefaults.mData ? oDefaults.oDefaults : iCol
-			} );
-			oSettings.aoColumns.push( oCol );
-			
-			/* Add a column specific filter */
-			if ( oSettings.aoPreSearchCols[ iCol ] === undefined || oSettings.aoPreSearchCols[ iCol ] === null )
-			{
-				oSettings.aoPreSearchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch );
-			}
-			else
-			{
-				var oPre = oSettings.aoPreSearchCols[ iCol ];
-				
-				/* Don't require that the user must specify bRegex, bSmart or bCaseInsensitive */
-				if ( oPre.bRegex === undefined )
-				{
-					oPre.bRegex = true;
-				}
-				
-				if ( oPre.bSmart === undefined )
-				{
-					oPre.bSmart = true;
-				}
-				
-				if ( oPre.bCaseInsensitive === undefined )
-				{
-					oPre.bCaseInsensitive = true;
-				}
-			}
-			
-			/* Use the column options function to initialise classes etc */
-			_fnColumnOptions( oSettings, iCol, null );
-		}
-		
-		
-		/**
-		 * Apply options for a column
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iCol column index to consider
-		 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnColumnOptions( oSettings, iCol, oOptions )
-		{
-			var oCol = oSettings.aoColumns[ iCol ];
-			
-			/* User specified column options */
-			if ( oOptions !== undefined && oOptions !== null )
-			{
-				/* Backwards compatibility for mDataProp */
-				if ( oOptions.mDataProp && !oOptions.mData )
-				{
-					oOptions.mData = oOptions.mDataProp;
-				}
-		
-				if ( oOptions.sType !== undefined )
-				{
-					oCol.sType = oOptions.sType;
-					oCol._bAutoType = false;
-				}
-				
-				$.extend( oCol, oOptions );
-				_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
-		
-				/* iDataSort to be applied (backwards compatibility), but aDataSort will take
-				 * priority if defined
-				 */
-				if ( oOptions.iDataSort !== undefined )
-				{
-					oCol.aDataSort = [ oOptions.iDataSort ];
-				}
-				_fnMap( oCol, oOptions, "aDataSort" );
-			}
-		
-			/* Cache the data get and set functions for speed */
-			var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
-			var mData = _fnGetObjectDataFn( oCol.mData );
-		
-			oCol.fnGetData = function (oData, sSpecific) {
-				var innerData = mData( oData, sSpecific );
-		
-				if ( oCol.mRender && (sSpecific && sSpecific !== '') )
-				{
-					return mRender( innerData, sSpecific, oData );
-				}
-				return innerData;
-			};
-			oCol.fnSetData = _fnSetObjectDataFn( oCol.mData );
-			
-			/* Feature sorting overrides column specific when off */
-			if ( !oSettings.oFeatures.bSort )
-			{
-				oCol.bSortable = false;
-			}
-			
-			/* Check that the class assignment is correct for sorting */
-			if ( !oCol.bSortable ||
-				 ($.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1) )
-			{
-				oCol.sSortingClass = oSettings.oClasses.sSortableNone;
-				oCol.sSortingClassJUI = "";
-			}
-			else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) == -1 )
-			{
-				oCol.sSortingClass = oSettings.oClasses.sSortable;
-				oCol.sSortingClassJUI = oSettings.oClasses.sSortJUI;
-			}
-			else if ( $.inArray('asc', oCol.asSorting) != -1 && $.inArray('desc', oCol.asSorting) == -1 )
-			{
-				oCol.sSortingClass = oSettings.oClasses.sSortableAsc;
-				oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIAscAllowed;
-			}
-			else if ( $.inArray('asc', oCol.asSorting) == -1 && $.inArray('desc', oCol.asSorting) != -1 )
-			{
-				oCol.sSortingClass = oSettings.oClasses.sSortableDesc;
-				oCol.sSortingClassJUI = oSettings.oClasses.sSortJUIDescAllowed;
-			}
-		}
-		
-		
-		/**
-		 * Adjust the table column widths for new data. Note: you would probably want to 
-		 * do a redraw after calling this function!
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAdjustColumnSizing ( oSettings )
-		{
-			/* Not interested in doing column width calculation if auto-width is disabled */
-			if ( oSettings.oFeatures.bAutoWidth === false )
-			{
-				return false;
-			}
-			
-			_fnCalculateColumnWidths( oSettings );
-			for ( var i=0 , iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				oSettings.aoColumns[i].nTh.style.width = oSettings.aoColumns[i].sWidth;
-			}
-		}
-		
-		
-		/**
-		 * Covert the index of a visible column to the index in the data array (take account
-		 * of hidden columns)
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iMatch Visible column index to lookup
-		 *  @returns {int} i the data index
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnVisibleToColumnIndex( oSettings, iMatch )
-		{
-			var aiVis = _fnGetColumns( oSettings, 'bVisible' );
-		
-			return typeof aiVis[iMatch] === 'number' ?
-				aiVis[iMatch] :
-				null;
-		}
-		
-		
-		/**
-		 * Covert the index of an index in the data array and convert it to the visible
-		 *   column index (take account of hidden columns)
-		 *  @param {int} iMatch Column index to lookup
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {int} i the data index
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnColumnIndexToVisible( oSettings, iMatch )
-		{
-			var aiVis = _fnGetColumns( oSettings, 'bVisible' );
-			var iPos = $.inArray( iMatch, aiVis );
-		
-			return iPos !== -1 ? iPos : null;
-		}
-		
-		
-		/**
-		 * Get the number of visible columns
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {int} i the number of visible columns
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnVisbleColumns( oSettings )
-		{
-			return _fnGetColumns( oSettings, 'bVisible' ).length;
-		}
-		
-		
-		/**
-		 * Get an array of column indexes that match a given property
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {string} sParam Parameter in aoColumns to look for - typically 
-		 *    bVisible or bSearchable
-		 *  @returns {array} Array of indexes with matched properties
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetColumns( oSettings, sParam )
-		{
-			var a = [];
-		
-			$.map( oSettings.aoColumns, function(val, i) {
-				if ( val[sParam] ) {
-					a.push( i );
-				}
-			} );
-		
-			return a;
-		}
-		
-		
-		/**
-		 * Get the sort type based on an input string
-		 *  @param {string} sData data we wish to know the type of
-		 *  @returns {string} type (defaults to 'string' if no type can be detected)
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnDetectType( sData )
-		{
-			var aTypes = DataTable.ext.aTypes;
-			var iLen = aTypes.length;
-			
-			for ( var i=0 ; i<iLen ; i++ )
-			{
-				var sType = aTypes[i]( sData );
-				if ( sType !== null )
-				{
-					return sType;
-				}
-			}
-			
-			return 'string';
-		}
-		
-		
-		/**
-		 * Figure out how to reorder a display list
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns array {int} aiReturn index list for reordering
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnReOrderIndex ( oSettings, sColumns )
-		{
-			var aColumns = sColumns.split(',');
-			var aiReturn = [];
-			
-			for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				for ( var j=0 ; j<iLen ; j++ )
-				{
-					if ( oSettings.aoColumns[i].sName == aColumns[j] )
-					{
-						aiReturn.push( j );
-						break;
-					}
-				}
-			}
-			
-			return aiReturn;
-		}
-		
-		
-		/**
-		 * Get the column ordering that DataTables expects
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {string} comma separated list of names
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnColumnOrdering ( oSettings )
-		{
-			var sNames = '';
-			for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				sNames += oSettings.aoColumns[i].sName+',';
-			}
-			if ( sNames.length == iLen )
-			{
-				return "";
-			}
-			return sNames.slice(0, -1);
-		}
-		
-		
-		/**
-		 * Take the column definitions and static columns arrays and calculate how
-		 * they relate to column indexes. The callback function will then apply the
-		 * definition found for a column to a suitable configuration object.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
-		 *  @param {array} aoCols The aoColumns array that defines columns individually
-		 *  @param {function} fn Callback function - takes two parameters, the calculated
-		 *    column index and the definition for that column.
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
-		{
-			var i, iLen, j, jLen, k, kLen;
-		
-			// Column definitions with aTargets
-			if ( aoColDefs )
-			{
-				/* Loop over the definitions array - loop in reverse so first instance has priority */
-				for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
-				{
-					/* Each definition can target multiple columns, as it is an array */
-					var aTargets = aoColDefs[i].aTargets;
-					if ( !$.isArray( aTargets ) )
-					{
-						_fnLog( oSettings, 1, 'aTargets must be an array of targets, not a '+(typeof aTargets) );
-					}
-		
-					for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
-					{
-						if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
-						{
-							/* Add columns that we don't yet know about */
-							while( oSettings.aoColumns.length <= aTargets[j] )
-							{
-								_fnAddColumn( oSettings );
-							}
-		
-							/* Integer, basic index */
-							fn( aTargets[j], aoColDefs[i] );
-						}
-						else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
-						{
-							/* Negative integer, right to left column counting */
-							fn( oSettings.aoColumns.length+aTargets[j], aoColDefs[i] );
-						}
-						else if ( typeof aTargets[j] === 'string' )
-						{
-							/* Class name matching on TH element */
-							for ( k=0, kLen=oSettings.aoColumns.length ; k<kLen ; k++ )
-							{
-								if ( aTargets[j] == "_all" ||
-								     $(oSettings.aoColumns[k].nTh).hasClass( aTargets[j] ) )
-								{
-									fn( k, aoColDefs[i] );
-								}
-							}
-						}
-					}
-				}
-			}
-		
-			// Statically defined columns array
-			if ( aoCols )
-			{
-				for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
-				{
-					fn( i, aoCols[i] );
-				}
-			}
-		}
-		
-		/**
-		 * Add a data array to the table, creating DOM node etc. This is the parallel to 
-		 * _fnGatherData, but for adding rows from a Javascript source, rather than a
-		 * DOM source.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {array} aData data array to be added
-		 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAddData ( oSettings, aDataSupplied )
-		{
-			var oCol;
-			
-			/* Take an independent copy of the data source so we can bash it about as we wish */
-			var aDataIn = ($.isArray(aDataSupplied)) ?
-				aDataSupplied.slice() :
-				$.extend( true, {}, aDataSupplied );
-			
-			/* Create the object for storing information about this new row */
-			var iRow = oSettings.aoData.length;
-			var oData = $.extend( true, {}, DataTable.models.oRow );
-			oData._aData = aDataIn;
-			oSettings.aoData.push( oData );
-		
-			/* Create the cells */
-			var nTd, sThisType;
-			for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				oCol = oSettings.aoColumns[i];
-		
-				/* Use rendered data for filtering / sorting */
-				if ( typeof oCol.fnRender === 'function' && oCol.bUseRendered && oCol.mData !== null )
-				{
-					_fnSetCellData( oSettings, iRow, i, _fnRender(oSettings, iRow, i) );
-				}
-				else
-				{
-					_fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
-				}
-				
-				/* See if we should auto-detect the column type */
-				if ( oCol._bAutoType && oCol.sType != 'string' )
-				{
-					/* Attempt to auto detect the type - same as _fnGatherData() */
-					var sVarType = _fnGetCellData( oSettings, iRow, i, 'type' );
-					if ( sVarType !== null && sVarType !== '' )
-					{
-						sThisType = _fnDetectType( sVarType );
-						if ( oCol.sType === null )
-						{
-							oCol.sType = sThisType;
-						}
-						else if ( oCol.sType != sThisType && oCol.sType != "html" )
-						{
-							/* String is always the 'fallback' option */
-							oCol.sType = 'string';
-						}
-					}
-				}
-			}
-			
-			/* Add to the display array */
-			oSettings.aiDisplayMaster.push( iRow );
-		
-			/* Create the DOM information */
-			if ( !oSettings.oFeatures.bDeferRender )
-			{
-				_fnCreateTr( oSettings, iRow );
-			}
-		
-			return iRow;
-		}
-		
-		
-		/**
-		 * Read in the data from the target table from the DOM
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGatherData( oSettings )
-		{
-			var iLoop, i, iLen, j, jLen, jInner,
-			 	nTds, nTrs, nTd, nTr, aLocalData, iThisIndex,
-				iRow, iRows, iColumn, iColumns, sNodeName,
-				oCol, oData;
-			
-			/*
-			 * Process by row first
-			 * Add the data object for the whole table - storing the tr node. Note - no point in getting
-			 * DOM based data if we are going to go and replace it with Ajax source data.
-			 */
-			if ( oSettings.bDeferLoading || oSettings.sAjaxSource === null )
-			{
-				nTr = oSettings.nTBody.firstChild;
-				while ( nTr )
-				{
-					if ( nTr.nodeName.toUpperCase() == "TR" )
-					{
-						iThisIndex = oSettings.aoData.length;
-						nTr._DT_RowIndex = iThisIndex;
-						oSettings.aoData.push( $.extend( true, {}, DataTable.models.oRow, {
-							"nTr": nTr
-						} ) );
-		
-						oSettings.aiDisplayMaster.push( iThisIndex );
-						nTd = nTr.firstChild;
-						jInner = 0;
-						while ( nTd )
-						{
-							sNodeName = nTd.nodeName.toUpperCase();
-							if ( sNodeName == "TD" || sNodeName == "TH" )
-							{
-								_fnSetCellData( oSettings, iThisIndex, jInner, $.trim(nTd.innerHTML) );
-								jInner++;
-							}
-							nTd = nTd.nextSibling;
-						}
-					}
-					nTr = nTr.nextSibling;
-				}
-			}
-			
-			/* Gather in the TD elements of the Table - note that this is basically the same as
-			 * fnGetTdNodes, but that function takes account of hidden columns, which we haven't yet
-			 * setup!
-			 */
-			nTrs = _fnGetTrNodes( oSettings );
-			nTds = [];
-			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
-			{
-				nTd = nTrs[i].firstChild;
-				while ( nTd )
-				{
-					sNodeName = nTd.nodeName.toUpperCase();
-					if ( sNodeName == "TD" || sNodeName == "TH" )
-					{
-						nTds.push( nTd );
-					}
-					nTd = nTd.nextSibling;
-				}
-			}
-			
-			/* Now process by column */
-			for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
-			{
-				oCol = oSettings.aoColumns[iColumn];
-		
-				/* Get the title of the column - unless there is a user set one */
-				if ( oCol.sTitle === null )
-				{
-					oCol.sTitle = oCol.nTh.innerHTML;
-				}
-				
-				var
-					bAutoType = oCol._bAutoType,
-					bRender = typeof oCol.fnRender === 'function',
-					bClass = oCol.sClass !== null,
-					bVisible = oCol.bVisible,
-					nCell, sThisType, sRendered, sValType;
-				
-				/* A single loop to rule them all (and be more efficient) */
-				if ( bAutoType || bRender || bClass || !bVisible )
-				{
-					for ( iRow=0, iRows=oSettings.aoData.length ; iRow<iRows ; iRow++ )
-					{
-						oData = oSettings.aoData[iRow];
-						nCell = nTds[ (iRow*iColumns) + iColumn ];
-						
-						/* Type detection */
-						if ( bAutoType && oCol.sType != 'string' )
-						{
-							sValType = _fnGetCellData( oSettings, iRow, iColumn, 'type' );
-							if ( sValType !== '' )
-							{
-								sThisType = _fnDetectType( sValType );
-								if ( oCol.sType === null )
-								{
-									oCol.sType = sThisType;
-								}
-								else if ( oCol.sType != sThisType && 
-								          oCol.sType != "html" )
-								{
-									/* String is always the 'fallback' option */
-									oCol.sType = 'string';
-								}
-							}
-						}
-		
-						if ( oCol.mRender )
-						{
-							// mRender has been defined, so we need to get the value and set it
-							nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
-						}
-						else if ( oCol.mData !== iColumn )
-						{
-							// If mData is not the same as the column number, then we need to
-							// get the dev set value. If it is the column, no point in wasting
-							// time setting the value that is already there!
-							nCell.innerHTML = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
-						}
-						
-						/* Rendering */
-						if ( bRender )
-						{
-							sRendered = _fnRender( oSettings, iRow, iColumn );
-							nCell.innerHTML = sRendered;
-							if ( oCol.bUseRendered )
-							{
-								/* Use the rendered data for filtering / sorting */
-								_fnSetCellData( oSettings, iRow, iColumn, sRendered );
-							}
-						}
-						
-						/* Classes */
-						if ( bClass )
-						{
-							nCell.className += ' '+oCol.sClass;
-						}
-						
-						/* Column visibility */
-						if ( !bVisible )
-						{
-							oData._anHidden[iColumn] = nCell;
-							nCell.parentNode.removeChild( nCell );
-						}
-						else
-						{
-							oData._anHidden[iColumn] = null;
-						}
-		
-						if ( oCol.fnCreatedCell )
-						{
-							oCol.fnCreatedCell.call( oSettings.oInstance,
-								nCell, _fnGetCellData( oSettings, iRow, iColumn, 'display' ), oData._aData, iRow, iColumn
-							);
-						}
-					}
-				}
-			}
-		
-			/* Row created callbacks */
-			if ( oSettings.aoRowCreatedCallback.length !== 0 )
-			{
-				for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
-				{
-					oData = oSettings.aoData[i];
-					_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, i] );
-				}
-			}
-		}
-		
-		
-		/**
-		 * Take a TR element and convert it to an index in aoData
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {node} n the TR element to find
-		 *  @returns {int} index if the node is found, null if not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnNodeToDataIndex( oSettings, n )
-		{
-			return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
-		}
-		
-		
-		/**
-		 * Take a TD element and convert it into a column data index (not the visible index)
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iRow The row number the TD/TH can be found in
-		 *  @param {node} n The TD/TH element to find
-		 *  @returns {int} index if the node is found, -1 if not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnNodeToColumnIndex( oSettings, iRow, n )
-		{
-			var anCells = _fnGetTdNodes( oSettings, iRow );
-		
-			for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				if ( anCells[i] === n )
-				{
-					return i;
-				}
-			}
-			return -1;
-		}
-		
-		
-		/**
-		 * Get an array of data for a given row from the internal data cache
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iRow aoData row id
-		 *  @param {string} sSpecific data get type ('type' 'filter' 'sort')
-		 *  @param {array} aiColumns Array of column indexes to get data from
-		 *  @returns {array} Data array
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetRowData( oSettings, iRow, sSpecific, aiColumns )
-		{
-			var out = [];
-			for ( var i=0, iLen=aiColumns.length ; i<iLen ; i++ )
-			{
-				out.push( _fnGetCellData( oSettings, iRow, aiColumns[i], sSpecific ) );
-			}
-			return out;
-		}
-		
-		
-		/**
-		 * Get the data for a given cell from the internal cache, taking into account data mapping
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iRow aoData row id
-		 *  @param {int} iCol Column index
-		 *  @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
-		 *  @returns {*} Cell data
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
-		{
-			var sData;
-			var oCol = oSettings.aoColumns[iCol];
-			var oData = oSettings.aoData[iRow]._aData;
-		
-			if ( (sData=oCol.fnGetData( oData, sSpecific )) === undefined )
-			{
-				if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
-				{
-					_fnLog( oSettings, 0, "Requested unknown parameter "+
-						(typeof oCol.mData=='function' ? '{mData function}' : "'"+oCol.mData+"'")+
-						" from the data source for row "+iRow );
-					oSettings.iDrawError = oSettings.iDraw;
-				}
-				return oCol.sDefaultContent;
-			}
-		
-			/* When the data source is null, we can use default column data */
-			if ( sData === null && oCol.sDefaultContent !== null )
-			{
-				sData = oCol.sDefaultContent;
-			}
-			else if ( typeof sData === 'function' )
-			{
-				/* If the data source is a function, then we run it and use the return */
-				return sData();
-			}
-		
-			if ( sSpecific == 'display' && sData === null )
-			{
-				return '';
-			}
-			return sData;
-		}
-		
-		
-		/**
-		 * Set the value for a specific cell, into the internal data cache
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iRow aoData row id
-		 *  @param {int} iCol Column index
-		 *  @param {*} val Value to set
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSetCellData( oSettings, iRow, iCol, val )
-		{
-			var oCol = oSettings.aoColumns[iCol];
-			var oData = oSettings.aoData[iRow]._aData;
-		
-			oCol.fnSetData( oData, val );
-		}
-		
-		
-		// Private variable that is used to match array syntax in the data property object
-		var __reArray = /\[.*?\]$/;
-		
-		/**
-		 * Return a function that can be used to get data from a source object, taking
-		 * into account the ability to use nested objects as a source
-		 *  @param {string|int|function} mSource The data source for the object
-		 *  @returns {function} Data get function
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetObjectDataFn( mSource )
-		{
-			if ( mSource === null )
-			{
-				/* Give an empty string for rendering / sorting etc */
-				return function (data, type) {
-					return null;
-				};
-			}
-			else if ( typeof mSource === 'function' )
-			{
-				return function (data, type, extra) {
-					return mSource( data, type, extra );
-				};
-			}
-			else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )
-			{
-				/* If there is a . in the source string then the data source is in a 
-				 * nested object so we loop over the data for each level to get the next
-				 * level down. On each loop we test for undefined, and if found immediately
-				 * return. This allows entire objects to be missing and sDefaultContent to
-				 * be used if defined, rather than throwing an error
-				 */
-				var fetchData = function (data, type, src) {
-					var a = src.split('.');
-					var arrayNotation, out, innerSrc;
-		
-					if ( src !== "" )
-					{
-						for ( var i=0, iLen=a.length ; i<iLen ; i++ )
-						{
-							// Check if we are dealing with an array notation request
-							arrayNotation = a[i].match(__reArray);
-		
-							if ( arrayNotation ) {
-								a[i] = a[i].replace(__reArray, '');
-		
-								// Condition allows simply [] to be passed in
-								if ( a[i] !== "" ) {
-									data = data[ a[i] ];
-								}
-								out = [];
-								
-								// Get the remainder of the nested object to get
-								a.splice( 0, i+1 );
-								innerSrc = a.join('.');
-		
-								// Traverse each entry in the array getting the properties requested
-								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
-									out.push( fetchData( data[j], type, innerSrc ) );
-								}
-		
-								// If a string is given in between the array notation indicators, that
-								// is used to join the strings together, otherwise an array is returned
-								var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
-								data = (join==="") ? out : out.join(join);
-		
-								// The inner call to fetchData has already traversed through the remainder
-								// of the source requested, so we exit from the loop
-								break;
-							}
-		
-							if ( data === null || data[ a[i] ] === undefined )
-							{
-								return undefined;
-							}
-							data = data[ a[i] ];
-						}
-					}
-		
-					return data;
-				};
-		
-				return function (data, type) {
-					return fetchData( data, type, mSource );
-				};
-			}
-			else
-			{
-				/* Array or flat object mapping */
-				return function (data, type) {
-					return data[mSource];	
-				};
-			}
-		}
-		
-		
-		/**
-		 * Return a function that can be used to set data from a source object, taking
-		 * into account the ability to use nested objects as a source
-		 *  @param {string|int|function} mSource The data source for the object
-		 *  @returns {function} Data set function
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSetObjectDataFn( mSource )
-		{
-			if ( mSource === null )
-			{
-				/* Nothing to do when the data source is null */
-				return function (data, val) {};
-			}
-			else if ( typeof mSource === 'function' )
-			{
-				return function (data, val) {
-					mSource( data, 'set', val );
-				};
-			}
-			else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || mSource.indexOf('[') !== -1) )
-			{
-				/* Like the get, we need to get data from a nested object */
-				var setData = function (data, val, src) {
-					var a = src.split('.'), b;
-					var arrayNotation, o, innerSrc;
-		
-					for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
-					{
-						// Check if we are dealing with an array notation request
-						arrayNotation = a[i].match(__reArray);
-		
-						if ( arrayNotation )
-						{
-							a[i] = a[i].replace(__reArray, '');
-							data[ a[i] ] = [];
-							
-							// Get the remainder of the nested object to set so we can recurse
-							b = a.slice();
-							b.splice( 0, i+1 );
-							innerSrc = b.join('.');
-		
-							// Traverse each entry in the array setting the properties requested
-							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
-							{
-								o = {};
-								setData( o, val[j], innerSrc );
-								data[ a[i] ].push( o );
-							}
-		
-							// The inner call to setData has already traversed through the remainder
-							// of the source and has set the data, thus we can exit here
-							return;
-						}
-		
-						// If the nested object doesn't currently exist - since we are
-						// trying to set the value - create it
-						if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
-						{
-							data[ a[i] ] = {};
-						}
-						data = data[ a[i] ];
-					}
-		
-					// If array notation is used, we just want to strip it and use the property name
-					// and assign the value. If it isn't used, then we get the result we want anyway
-					data[ a[a.length-1].replace(__reArray, '') ] = val;
-				};
-		
-				return function (data, val) {
-					return setData( data, val, mSource );
-				};
-			}
-			else
-			{
-				/* Array or flat object mapping */
-				return function (data, val) {
-					data[mSource] = val;	
-				};
-			}
-		}
-		
-		
-		/**
-		 * Return an array with the full table data
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns array {array} aData Master data array
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetDataMaster ( oSettings )
-		{
-			var aData = [];
-			var iLen = oSettings.aoData.length;
-			for ( var i=0 ; i<iLen; i++ )
-			{
-				aData.push( oSettings.aoData[i]._aData );
-			}
-			return aData;
-		}
-		
-		
-		/**
-		 * Nuke the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnClearTable( oSettings )
-		{
-			oSettings.aoData.splice( 0, oSettings.aoData.length );
-			oSettings.aiDisplayMaster.splice( 0, oSettings.aiDisplayMaster.length );
-			oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length );
-			_fnCalculateEnd( oSettings );
-		}
-		
-		
-		 /**
-		 * Take an array of integers (index array) and remove a target integer (value - not 
-		 * the key!)
-		 *  @param {array} a Index array to target
-		 *  @param {int} iTarget value to find
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnDeleteIndex( a, iTarget )
-		{
-			var iTargetIndex = -1;
-			
-			for ( var i=0, iLen=a.length ; i<iLen ; i++ )
-			{
-				if ( a[i] == iTarget )
-				{
-					iTargetIndex = i;
-				}
-				else if ( a[i] > iTarget )
-				{
-					a[i]--;
-				}
-			}
-			
-			if ( iTargetIndex != -1 )
-			{
-				a.splice( iTargetIndex, 1 );
-			}
-		}
-		
-		
-		 /**
-		 * Call the developer defined fnRender function for a given cell (row/column) with
-		 * the required parameters and return the result.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iRow aoData index for the row
-		 *  @param {int} iCol aoColumns index for the column
-		 *  @returns {*} Return of the developer's fnRender function
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnRender( oSettings, iRow, iCol )
-		{
-			var oCol = oSettings.aoColumns[iCol];
-		
-			return oCol.fnRender( {
-				"iDataRow":    iRow,
-				"iDataColumn": iCol,
-				"oSettings":   oSettings,
-				"aData":       oSettings.aoData[iRow]._aData,
-				"mDataProp":   oCol.mData
-			}, _fnGetCellData(oSettings, iRow, iCol, 'display') );
-		}
-		/**
-		 * Create a new TR element (and it's TD children) for a row
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iRow Row to consider
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnCreateTr ( oSettings, iRow )
-		{
-			var oData = oSettings.aoData[iRow];
-			var nTd;
-		
-			if ( oData.nTr === null )
-			{
-				oData.nTr = document.createElement('tr');
-		
-				/* Use a private property on the node to allow reserve mapping from the node
-				 * to the aoData array for fast look up
-				 */
-				oData.nTr._DT_RowIndex = iRow;
-		
-				/* Special parameters can be given by the data source to be used on the row */
-				if ( oData._aData.DT_RowId )
-				{
-					oData.nTr.id = oData._aData.DT_RowId;
-				}
-		
-				if ( oData._aData.DT_RowClass )
-				{
-					oData.nTr.className = oData._aData.DT_RowClass;
-				}
-		
-				/* Process each column */
-				for ( var i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-				{
-					var oCol = oSettings.aoColumns[i];
-					nTd = document.createElement( oCol.sCellType );
-		
-					/* Render if needed - if bUseRendered is true then we already have the rendered
-					 * value in the data source - so can just use that
-					 */
-					nTd.innerHTML = (typeof oCol.fnRender === 'function' && (!oCol.bUseRendered || oCol.mData === null)) ?
-						_fnRender( oSettings, iRow, i ) :
-						_fnGetCellData( oSettings, iRow, i, 'display' );
-				
-					/* Add user defined class */
-					if ( oCol.sClass !== null )
-					{
-						nTd.className = oCol.sClass;
-					}
-					
-					if ( oCol.bVisible )
-					{
-						oData.nTr.appendChild( nTd );
-						oData._anHidden[i] = null;
-					}
-					else
-					{
-						oData._anHidden[i] = nTd;
-					}
-		
-					if ( oCol.fnCreatedCell )
-					{
-						oCol.fnCreatedCell.call( oSettings.oInstance,
-							nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), oData._aData, iRow, i
-						);
-					}
-				}
-		
-				_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [oData.nTr, oData._aData, iRow] );
-			}
-		}
-		
-		
-		/**
-		 * Create the HTML header for the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnBuildHead( oSettings )
-		{
-			var i, nTh, iLen, j, jLen;
-			var iThs = $('th, td', oSettings.nTHead).length;
-			var iCorrector = 0;
-			var jqChildren;
-			
-			/* If there is a header in place - then use it - otherwise it's going to get nuked... */
-			if ( iThs !== 0 )
-			{
-				/* We've got a thead from the DOM, so remove hidden columns and apply width to vis cols */
-				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-				{
-					nTh = oSettings.aoColumns[i].nTh;
-					nTh.setAttribute('role', 'columnheader');
-					if ( oSettings.aoColumns[i].bSortable )
-					{
-						nTh.setAttribute('tabindex', oSettings.iTabIndex);
-						nTh.setAttribute('aria-controls', oSettings.sTableId);
-					}
-		
-					if ( oSettings.aoColumns[i].sClass !== null )
-					{
-						$(nTh).addClass( oSettings.aoColumns[i].sClass );
-					}
-					
-					/* Set the title of the column if it is user defined (not what was auto detected) */
-					if ( oSettings.aoColumns[i].sTitle != nTh.innerHTML )
-					{
-						nTh.innerHTML = oSettings.aoColumns[i].sTitle;
-					}
-				}
-			}
-			else
-			{
-				/* We don't have a header in the DOM - so we are going to have to create one */
-				var nTr = document.createElement( "tr" );
-				
-				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-				{
-					nTh = oSettings.aoColumns[i].nTh;
-					nTh.innerHTML = oSettings.aoColumns[i].sTitle;
-					nTh.setAttribute('tabindex', '0');
-					
-					if ( oSettings.aoColumns[i].sClass !== null )
-					{
-						$(nTh).addClass( oSettings.aoColumns[i].sClass );
-					}
-					
-					nTr.appendChild( nTh );
-				}
-				$(oSettings.nTHead).html( '' )[0].appendChild( nTr );
-				_fnDetectHeader( oSettings.aoHeader, oSettings.nTHead );
-			}
-			
-			/* ARIA role for the rows */	
-			$(oSettings.nTHead).children('tr').attr('role', 'row');
-			
-			/* Add the extra markup needed by jQuery UI's themes */
-			if ( oSettings.bJUI )
-			{
-				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-				{
-					nTh = oSettings.aoColumns[i].nTh;
-					
-					var nDiv = document.createElement('div');
-					nDiv.className = oSettings.oClasses.sSortJUIWrapper;
-					$(nTh).contents().appendTo(nDiv);
-					
-					var nSpan = document.createElement('span');
-					nSpan.className = oSettings.oClasses.sSortIcon;
-					nDiv.appendChild( nSpan );
-					nTh.appendChild( nDiv );
-				}
-			}
-			
-			if ( oSettings.oFeatures.bSort )
-			{
-				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-				{
-					if ( oSettings.aoColumns[i].bSortable !== false )
-					{
-						_fnSortAttachListener( oSettings, oSettings.aoColumns[i].nTh, i );
-					}
-					else
-					{
-						$(oSettings.aoColumns[i].nTh).addClass( oSettings.oClasses.sSortableNone );
-					}
-				}
-			}
-			
-			/* Deal with the footer - add classes if required */
-			if ( oSettings.oClasses.sFooterTH !== "" )
-			{
-				$(oSettings.nTFoot).children('tr').children('th').addClass( oSettings.oClasses.sFooterTH );
-			}
-			
-			/* Cache the footer elements */
-			if ( oSettings.nTFoot !== null )
-			{
-				var anCells = _fnGetUniqueThs( oSettings, null, oSettings.aoFooter );
-				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-				{
-					if ( anCells[i] )
-					{
-						oSettings.aoColumns[i].nTf = anCells[i];
-						if ( oSettings.aoColumns[i].sClass )
-						{
-							$(anCells[i]).addClass( oSettings.aoColumns[i].sClass );
-						}
-					}
-				}
-			}
-		}
-		
-		
-		/**
-		 * Draw the header (or footer) element based on the column visibility states. The
-		 * methodology here is to use the layout array from _fnDetectHeader, modified for
-		 * the instantaneous column visibility, to construct the new layout. The grid is
-		 * traversed over cell at a time in a rows x columns grid fashion, although each 
-		 * cell insert can cover multiple elements in the grid - which is tracks using the
-		 * aApplied array. Cell inserts in the grid will only occur where there isn't
-		 * already a cell in that position.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param array {objects} aoSource Layout array from _fnDetectHeader
-		 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, 
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
-		{
-			var i, iLen, j, jLen, k, kLen, n, nLocalTr;
-			var aoLocal = [];
-			var aApplied = [];
-			var iColumns = oSettings.aoColumns.length;
-			var iRowspan, iColspan;
-		
-			if (  bIncludeHidden === undefined )
-			{
-				bIncludeHidden = false;
-			}
-		
-			/* Make a copy of the master layout array, but without the visible columns in it */
-			for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
-			{
-				aoLocal[i] = aoSource[i].slice();
-				aoLocal[i].nTr = aoSource[i].nTr;
-		
-				/* Remove any columns which are currently hidden */
-				for ( j=iColumns-1 ; j>=0 ; j-- )
-				{
-					if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
-					{
-						aoLocal[i].splice( j, 1 );
-					}
-				}
-		
-				/* Prep the applied array - it needs an element for each row */
-				aApplied.push( [] );
-			}
-		
-			for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
-			{
-				nLocalTr = aoLocal[i].nTr;
-				
-				/* All cells are going to be replaced, so empty out the row */
-				if ( nLocalTr )
-				{
-					while( (n = nLocalTr.firstChild) )
-					{
-						nLocalTr.removeChild( n );
-					}
-				}
-		
-				for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
-				{
-					iRowspan = 1;
-					iColspan = 1;
-		
-					/* Check to see if there is already a cell (row/colspan) covering our target
-					 * insert point. If there is, then there is nothing to do.
-					 */
-					if ( aApplied[i][j] === undefined )
-					{
-						nLocalTr.appendChild( aoLocal[i][j].cell );
-						aApplied[i][j] = 1;
-		
-						/* Expand the cell to cover as many rows as needed */
-						while ( aoLocal[i+iRowspan] !== undefined &&
-						        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
-						{
-							aApplied[i+iRowspan][j] = 1;
-							iRowspan++;
-						}
-		
-						/* Expand the cell to cover as many columns as needed */
-						while ( aoLocal[i][j+iColspan] !== undefined &&
-						        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
-						{
-							/* Must update the applied array over the rows for the columns */
-							for ( k=0 ; k<iRowspan ; k++ )
-							{
-								aApplied[i+k][j+iColspan] = 1;
-							}
-							iColspan++;
-						}
-		
-						/* Do the actual expansion in the DOM */
-						aoLocal[i][j].cell.rowSpan = iRowspan;
-						aoLocal[i][j].cell.colSpan = iColspan;
-					}
-				}
-			}
-		}
-		
-		
-		/**
-		 * Insert the required TR nodes into the table for display
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnDraw( oSettings )
-		{
-			/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
-			var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
-			if ( $.inArray( false, aPreDraw ) !== -1 )
-			{
-				_fnProcessingDisplay( oSettings, false );
-				return;
-			}
-			
-			var i, iLen, n;
-			var anRows = [];
-			var iRowCount = 0;
-			var iStripes = oSettings.asStripeClasses.length;
-			var iOpenRows = oSettings.aoOpenRows.length;
-			
-			oSettings.bDrawing = true;
-			
-			/* Check and see if we have an initial draw position from state saving */
-			if ( oSettings.iInitDisplayStart !== undefined && oSettings.iInitDisplayStart != -1 )
-			{
-				if ( oSettings.oFeatures.bServerSide )
-				{
-					oSettings._iDisplayStart = oSettings.iInitDisplayStart;
-				}
-				else
-				{
-					oSettings._iDisplayStart = (oSettings.iInitDisplayStart >= oSettings.fnRecordsDisplay()) ?
-						0 : oSettings.iInitDisplayStart;
-				}
-				oSettings.iInitDisplayStart = -1;
-				_fnCalculateEnd( oSettings );
-			}
-			
-			/* Server-side processing draw intercept */
-			if ( oSettings.bDeferLoading )
-			{
-				oSettings.bDeferLoading = false;
-				oSettings.iDraw++;
-			}
-			else if ( !oSettings.oFeatures.bServerSide )
-			{
-				oSettings.iDraw++;
-			}
-			else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
-			{
-				return;
-			}
-			
-			if ( oSettings.aiDisplay.length !== 0 )
-			{
-				var iStart = oSettings._iDisplayStart;
-				var iEnd = oSettings._iDisplayEnd;
-				
-				if ( oSettings.oFeatures.bServerSide )
-				{
-					iStart = 0;
-					iEnd = oSettings.aoData.length;
-				}
-				
-				for ( var j=iStart ; j<iEnd ; j++ )
-				{
-					var aoData = oSettings.aoData[ oSettings.aiDisplay[j] ];
-					if ( aoData.nTr === null )
-					{
-						_fnCreateTr( oSettings, oSettings.aiDisplay[j] );
-					}
-		
-					var nRow = aoData.nTr;
-					
-					/* Remove the old striping classes and then add the new one */
-					if ( iStripes !== 0 )
-					{
-						var sStripe = oSettings.asStripeClasses[ iRowCount % iStripes ];
-						if ( aoData._sRowStripe != sStripe )
-						{
-							$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
-							aoData._sRowStripe = sStripe;
-						}
-					}
-					
-					/* Row callback functions - might want to manipulate the row */
-					_fnCallbackFire( oSettings, 'aoRowCallback', null, 
-						[nRow, oSettings.aoData[ oSettings.aiDisplay[j] ]._aData, iRowCount, j] );
-					
-					anRows.push( nRow );
-					iRowCount++;
-					
-					/* If there is an open row - and it is attached to this parent - attach it on redraw */
-					if ( iOpenRows !== 0 )
-					{
-						for ( var k=0 ; k<iOpenRows ; k++ )
-						{
-							if ( nRow == oSettings.aoOpenRows[k].nParent )
-							{
-								anRows.push( oSettings.aoOpenRows[k].nTr );
-								break;
-							}
-						}
-					}
-				}
-			}
-			else
-			{
-				/* Table is empty - create a row with an empty message in it */
-				anRows[ 0 ] = document.createElement( 'tr' );
-				
-				if ( oSettings.asStripeClasses[0] )
-				{
-					anRows[ 0 ].className = oSettings.asStripeClasses[0];
-				}
-		
-				var oLang = oSettings.oLanguage;
-				var sZero = oLang.sZeroRecords;
-				if ( oSettings.iDraw == 1 && oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
-				{
-					sZero = oLang.sLoadingRecords;
-				}
-				else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
-				{
-					sZero = oLang.sEmptyTable;
-				}
-		
-				var nTd = document.createElement( 'td' );
-				nTd.setAttribute( 'valign', "top" );
-				nTd.colSpan = _fnVisbleColumns( oSettings );
-				nTd.className = oSettings.oClasses.sRowEmpty;
-				nTd.innerHTML = _fnInfoMacros( oSettings, sZero );
-				
-				anRows[ iRowCount ].appendChild( nTd );
-			}
-			
-			/* Header and footer callbacks */
-			_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], 
-				_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
-			
-			_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], 
-				_fnGetDataMaster( oSettings ), oSettings._iDisplayStart, oSettings.fnDisplayEnd(), oSettings.aiDisplay ] );
-			
-			/* 
-			 * Need to remove any old row from the display - note we can't just empty the tbody using
-			 * $().html('') since this will unbind the jQuery event handlers (even although the node 
-			 * still exists!) - equally we can't use innerHTML, since IE throws an exception.
-			 */
-			var
-				nAddFrag = document.createDocumentFragment(),
-				nRemoveFrag = document.createDocumentFragment(),
-				nBodyPar, nTrs;
-			
-			if ( oSettings.nTBody )
-			{
-				nBodyPar = oSettings.nTBody.parentNode;
-				nRemoveFrag.appendChild( oSettings.nTBody );
-				
-				/* When doing infinite scrolling, only remove child rows when sorting, filtering or start
-				 * up. When not infinite scroll, always do it.
-				 */
-				if ( !oSettings.oScroll.bInfinite || !oSettings._bInitComplete ||
-				 	oSettings.bSorted || oSettings.bFiltered )
-				{
-					while( (n = oSettings.nTBody.firstChild) )
-					{
-						oSettings.nTBody.removeChild( n );
-					}
-				}
-				
-				/* Put the draw table into the dom */
-				for ( i=0, iLen=anRows.length ; i<iLen ; i++ )
-				{
-					nAddFrag.appendChild( anRows[i] );
-				}
-				
-				oSettings.nTBody.appendChild( nAddFrag );
-				if ( nBodyPar !== null )
-				{
-					nBodyPar.appendChild( oSettings.nTBody );
-				}
-			}
-			
-			/* Call all required callback functions for the end of a draw */
-			_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
-			
-			/* Draw is complete, sorting and filtering must be as well */
-			oSettings.bSorted = false;
-			oSettings.bFiltered = false;
-			oSettings.bDrawing = false;
-			
-			if ( oSettings.oFeatures.bServerSide )
-			{
-				_fnProcessingDisplay( oSettings, false );
-				if ( !oSettings._bInitComplete )
-				{
-					_fnInitComplete( oSettings );
-				}
-			}
-		}
-		
-		
-		/**
-		 * Redraw the table - taking account of the various features which are enabled
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnReDraw( oSettings )
-		{
-			if ( oSettings.oFeatures.bSort )
-			{
-				/* Sorting will refilter and draw for us */
-				_fnSort( oSettings, oSettings.oPreviousSearch );
-			}
-			else if ( oSettings.oFeatures.bFilter )
-			{
-				/* Filtering will redraw for us */
-				_fnFilterComplete( oSettings, oSettings.oPreviousSearch );
-			}
-			else
-			{
-				_fnCalculateEnd( oSettings );
-				_fnDraw( oSettings );
-			}
-		}
-		
-		
-		/**
-		 * Add the options to the page HTML for the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAddOptionsHtml ( oSettings )
-		{
-			/*
-			 * Create a temporary, empty, div which we can later on replace with what we have generated
-			 * we do it this way to rendering the 'options' html offline - speed :-)
-			 */
-			var nHolding = $('<div></div>')[0];
-			oSettings.nTable.parentNode.insertBefore( nHolding, oSettings.nTable );
-			
-			/* 
-			 * All DataTables are wrapped in a div
-			 */
-			oSettings.nTableWrapper = $('<div id="'+oSettings.sTableId+'_wrapper" class="'+oSettings.oClasses.sWrapper+'" role="grid"></div>')[0];
-			oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
-		
-			/* Track where we want to insert the option */
-			var nInsertNode = oSettings.nTableWrapper;
-			
-			/* Loop over the user set positioning and place the elements as needed */
-			var aDom = oSettings.sDom.split('');
-			var nTmp, iPushFeature, cOption, nNewNode, cNext, sAttr, j;
-			for ( var i=0 ; i<aDom.length ; i++ )
-			{
-				iPushFeature = 0;
-				cOption = aDom[i];
-				
-				if ( cOption == '<' )
-				{
-					/* New container div */
-					nNewNode = $('<div></div>')[0];
-					
-					/* Check to see if we should append an id and/or a class name to the container */
-					cNext = aDom[i+1];
-					if ( cNext == "'" || cNext == '"' )
-					{
-						sAttr = "";
-						j = 2;
-						while ( aDom[i+j] != cNext )
-						{
-							sAttr += aDom[i+j];
-							j++;
-						}
-						
-						/* Replace jQuery UI constants */
-						if ( sAttr == "H" )
-						{
-							sAttr = oSettings.oClasses.sJUIHeader;
-						}
-						else if ( sAttr == "F" )
-						{
-							sAttr = oSettings.oClasses.sJUIFooter;
-						}
-						
-						/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
-						 * breaks the string into parts and applies them as needed
-						 */
-						if ( sAttr.indexOf('.') != -1 )
-						{
-							var aSplit = sAttr.split('.');
-							nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
-							nNewNode.className = aSplit[1];
-						}
-						else if ( sAttr.charAt(0) == "#" )
-						{
-							nNewNode.id = sAttr.substr(1, sAttr.length-1);
-						}
-						else
-						{
-							nNewNode.className = sAttr;
-						}
-						
-						i += j; /* Move along the position array */
-					}
-					
-					nInsertNode.appendChild( nNewNode );
-					nInsertNode = nNewNode;
-				}
-				else if ( cOption == '>' )
-				{
-					/* End container div */
-					nInsertNode = nInsertNode.parentNode;
-				}
-				else if ( cOption == 'l' && oSettings.oFeatures.bPaginate && oSettings.oFeatures.bLengthChange )
-				{
-					/* Length */
-					nTmp = _fnFeatureHtmlLength( oSettings );
-					iPushFeature = 1;
-				}
-				else if ( cOption == 'f' && oSettings.oFeatures.bFilter )
-				{
-					/* Filter */
-					nTmp = _fnFeatureHtmlFilter( oSettings );
-					iPushFeature = 1;
-				}
-				else if ( cOption == 'r' && oSettings.oFeatures.bProcessing )
-				{
-					/* pRocessing */
-					nTmp = _fnFeatureHtmlProcessing( oSettings );
-					iPushFeature = 1;
-				}
-				else if ( cOption == 't' )
-				{
-					/* Table */
-					nTmp = _fnFeatureHtmlTable( oSettings );
-					iPushFeature = 1;
-				}
-				else if ( cOption ==  'i' && oSettings.oFeatures.bInfo )
-				{
-					/* Info */
-					nTmp = _fnFeatureHtmlInfo( oSettings );
-					iPushFeature = 1;
-				}
-				else if ( cOption == 'p' && oSettings.oFeatures.bPaginate )
-				{
-					/* Pagination */
-					nTmp = _fnFeatureHtmlPaginate( oSettings );
-					iPushFeature = 1;
-				}
-				else if ( DataTable.ext.aoFeatures.length !== 0 )
-				{
-					/* Plug-in features */
-					var aoFeatures = DataTable.ext.aoFeatures;
-					for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
-					{
-						if ( cOption == aoFeatures[k].cFeature )
-						{
-							nTmp = aoFeatures[k].fnInit( oSettings );
-							if ( nTmp )
-							{
-								iPushFeature = 1;
-							}
-							break;
-						}
-					}
-				}
-				
-				/* Add to the 2D features array */
-				if ( iPushFeature == 1 && nTmp !== null )
-				{
-					if ( typeof oSettings.aanFeatures[cOption] !== 'object' )
-					{
-						oSettings.aanFeatures[cOption] = [];
-					}
-					oSettings.aanFeatures[cOption].push( nTmp );
-					nInsertNode.appendChild( nTmp );
-				}
-			}
-			
-			/* Built our DOM structure - replace the holding div with what we want */
-			nHolding.parentNode.replaceChild( oSettings.nTableWrapper, nHolding );
-		}
-		
-		
-		/**
-		 * Use the DOM source to create up an array of header cells. The idea here is to
-		 * create a layout grid (array) of rows x columns, which contains a reference
-		 * to the cell that that point in the grid (regardless of col/rowspan), such that
-		 * any column / row could be removed and the new grid constructed
-		 *  @param array {object} aLayout Array to store the calculated layout in
-		 *  @param {node} nThead The header/footer element for the table
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnDetectHeader ( aLayout, nThead )
-		{
-			var nTrs = $(nThead).children('tr');
-			var nTr, nCell;
-			var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
-			var bUnique;
-			var fnShiftCol = function ( a, i, j ) {
-				var k = a[i];
-		                while ( k[j] ) {
-					j++;
-				}
-				return j;
-			};
-		
-			aLayout.splice( 0, aLayout.length );
-			
-			/* We know how many rows there are in the layout - so prep it */
-			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
-			{
-				aLayout.push( [] );
-			}
-			
-			/* Calculate a layout array */
-			for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
-			{
-				nTr = nTrs[i];
-				iColumn = 0;
-				
-				/* For every cell in the row... */
-				nCell = nTr.firstChild;
-				while ( nCell ) {
-					if ( nCell.nodeName.toUpperCase() == "TD" ||
-					     nCell.nodeName.toUpperCase() == "TH" )
-					{
-						/* Get the col and rowspan attributes from the DOM and sanitise them */
-						iColspan = nCell.getAttribute('colspan') * 1;
-						iRowspan = nCell.getAttribute('rowspan') * 1;
-						iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
-						iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
-		
-						/* There might be colspan cells already in this row, so shift our target 
-						 * accordingly
-						 */
-						iColShifted = fnShiftCol( aLayout, i, iColumn );
-						
-						/* Cache calculation for unique columns */
-						bUnique = iColspan === 1 ? true : false;
-						
-						/* If there is col / rowspan, copy the information into the layout grid */
-						for ( l=0 ; l<iColspan ; l++ )
-						{
-							for ( k=0 ; k<iRowspan ; k++ )
-							{
-								aLayout[i+k][iColShifted+l] = {
-									"cell": nCell,
-									"unique": bUnique
-								};
-								aLayout[i+k].nTr = nTr;
-							}
-						}
-					}
-					nCell = nCell.nextSibling;
-				}
-			}
-		}
-		
-		
-		/**
-		 * Get an array of unique th elements, one for each column
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {node} nHeader automatically detect the layout from this node - optional
-		 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
-		 *  @returns array {node} aReturn list of unique th's
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
-		{
-			var aReturn = [];
-			if ( !aLayout )
-			{
-				aLayout = oSettings.aoHeader;
-				if ( nHeader )
-				{
-					aLayout = [];
-					_fnDetectHeader( aLayout, nHeader );
-				}
-			}
-		
-			for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
-			{
-				for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
-				{
-					if ( aLayout[i][j].unique && 
-						 (!aReturn[j] || !oSettings.bSortCellsTop) )
-					{
-						aReturn[j] = aLayout[i][j].cell;
-					}
-				}
-			}
-			
-			return aReturn;
-		}
-		
-		
-		
-		/**
-		 * Update the table using an Ajax call
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {boolean} Block the table drawing or not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAjaxUpdate( oSettings )
-		{
-			if ( oSettings.bAjaxDataGet )
-			{
-				oSettings.iDraw++;
-				_fnProcessingDisplay( oSettings, true );
-				var iColumns = oSettings.aoColumns.length;
-				var aoData = _fnAjaxParameters( oSettings );
-				_fnServerParams( oSettings, aoData );
-				
-				oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData,
-					function(json) {
-						_fnAjaxUpdateDraw( oSettings, json );
-					}, oSettings );
-				return false;
-			}
-			else
-			{
-				return true;
-			}
-		}
-		
-		
-		/**
-		 * Build up the parameters in an object needed for a server-side processing request
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {bool} block the table drawing or not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAjaxParameters( oSettings )
-		{
-			var iColumns = oSettings.aoColumns.length;
-			var aoData = [], mDataProp, aaSort, aDataSort;
-			var i, j;
-			
-			aoData.push( { "name": "sEcho",          "value": oSettings.iDraw } );
-			aoData.push( { "name": "iColumns",       "value": iColumns } );
-			aoData.push( { "name": "sColumns",       "value": _fnColumnOrdering(oSettings) } );
-			aoData.push( { "name": "iDisplayStart",  "value": oSettings._iDisplayStart } );
-			aoData.push( { "name": "iDisplayLength", "value": oSettings.oFeatures.bPaginate !== false ?
-				oSettings._iDisplayLength : -1 } );
-				
-			for ( i=0 ; i<iColumns ; i++ )
-			{
-			  mDataProp = oSettings.aoColumns[i].mData;
-				aoData.push( { "name": "mDataProp_"+i, "value": typeof(mDataProp)==="function" ? 'function' : mDataProp } );
-			}
-			
-			/* Filtering */
-			if ( oSettings.oFeatures.bFilter !== false )
-			{
-				aoData.push( { "name": "sSearch", "value": oSettings.oPreviousSearch.sSearch } );
-				aoData.push( { "name": "bRegex",  "value": oSettings.oPreviousSearch.bRegex } );
-				for ( i=0 ; i<iColumns ; i++ )
-				{
-					aoData.push( { "name": "sSearch_"+i,     "value": oSettings.aoPreSearchCols[i].sSearch } );
-					aoData.push( { "name": "bRegex_"+i,      "value": oSettings.aoPreSearchCols[i].bRegex } );
-					aoData.push( { "name": "bSearchable_"+i, "value": oSettings.aoColumns[i].bSearchable } );
-				}
-			}
-			
-			/* Sorting */
-			if ( oSettings.oFeatures.bSort !== false )
-			{
-				var iCounter = 0;
-		
-				aaSort = ( oSettings.aaSortingFixed !== null ) ?
-					oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
-					oSettings.aaSorting.slice();
-				
-				for ( i=0 ; i<aaSort.length ; i++ )
-				{
-					aDataSort = oSettings.aoColumns[ aaSort[i][0] ].aDataSort;
-					
-					for ( j=0 ; j<aDataSort.length ; j++ )
-					{
-						aoData.push( { "name": "iSortCol_"+iCounter,  "value": aDataSort[j] } );
-						aoData.push( { "name": "sSortDir_"+iCounter,  "value": aaSort[i][1] } );
-						iCounter++;
-					}
-				}
-				aoData.push( { "name": "iSortingCols",   "value": iCounter } );
-				
-				for ( i=0 ; i<iColumns ; i++ )
-				{
-					aoData.push( { "name": "bSortable_"+i,  "value": oSettings.aoColumns[i].bSortable } );
-				}
-			}
-			
-			return aoData;
-		}
-		
-		
-		/**
-		 * Add Ajax parameters from plug-ins
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param array {objects} aoData name/value pairs to send to the server
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnServerParams( oSettings, aoData )
-		{
-			_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [aoData] );
-		}
-		
-		
-		/**
-		 * Data the data from the server (nuking the old) and redraw the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {object} json json data return from the server.
-		 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
-		 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
-		 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
-		 *  @param {array} json.aaData The data to display on this page
-		 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnAjaxUpdateDraw ( oSettings, json )
-		{
-			if ( json.sEcho !== undefined )
-			{
-				/* Protect against old returns over-writing a new one. Possible when you get
-				 * very fast interaction, and later queries are completed much faster
-				 */
-				if ( json.sEcho*1 < oSettings.iDraw )
-				{
-					return;
-				}
-				else
-				{
-					oSettings.iDraw = json.sEcho * 1;
-				}
-			}
-			
-			if ( !oSettings.oScroll.bInfinite ||
-				   (oSettings.oScroll.bInfinite && (oSettings.bSorted || oSettings.bFiltered)) )
-			{
-				_fnClearTable( oSettings );
-			}
-			oSettings._iRecordsTotal = parseInt(json.iTotalRecords, 10);
-			oSettings._iRecordsDisplay = parseInt(json.iTotalDisplayRecords, 10);
-			
-			/* Determine if reordering is required */
-			var sOrdering = _fnColumnOrdering(oSettings);
-			var bReOrder = (json.sColumns !== undefined && sOrdering !== "" && json.sColumns != sOrdering );
-			var aiIndex;
-			if ( bReOrder )
-			{
-				aiIndex = _fnReOrderIndex( oSettings, json.sColumns );
-			}
-			
-			var aData = _fnGetObjectDataFn( oSettings.sAjaxDataProp )( json );
-			for ( var i=0, iLen=aData.length ; i<iLen ; i++ )
-			{
-				if ( bReOrder )
-				{
-					/* If we need to re-order, then create a new array with the correct order and add it */
-					var aDataSorted = [];
-					for ( var j=0, jLen=oSettings.aoColumns.length ; j<jLen ; j++ )
-					{
-						aDataSorted.push( aData[i][ aiIndex[j] ] );
-					}
-					_fnAddData( oSettings, aDataSorted );
-				}
-				else
-				{
-					/* No re-order required, sever got it "right" - just straight add */
-					_fnAddData( oSettings, aData[i] );
-				}
-			}
-			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-			
-			oSettings.bAjaxDataGet = false;
-			_fnDraw( oSettings );
-			oSettings.bAjaxDataGet = true;
-			_fnProcessingDisplay( oSettings, false );
-		}
-		
-		
-		
-		/**
-		 * Generate the node required for filtering text
-		 *  @returns {node} Filter control element
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFeatureHtmlFilter ( oSettings )
-		{
-			var oPreviousSearch = oSettings.oPreviousSearch;
-			
-			var sSearchStr = oSettings.oLanguage.sSearch;
-			sSearchStr = (sSearchStr.indexOf('_INPUT_') !== -1) ?
-			  sSearchStr.replace('_INPUT_', '<input type="text" />') :
-			  sSearchStr==="" ? '<input type="text" />' : sSearchStr+' <input type="text" />';
-			
-			var nFilter = document.createElement( 'div' );
-			nFilter.className = oSettings.oClasses.sFilter;
-			nFilter.innerHTML = '<label>'+sSearchStr+'</label>';
-			if ( !oSettings.aanFeatures.f )
-			{
-				nFilter.id = oSettings.sTableId+'_filter';
-			}
-			
-			var jqFilter = $('input[type="text"]', nFilter);
-		
-			// Store a reference to the input element, so other input elements could be
-			// added to the filter wrapper if needed (submit button for example)
-			nFilter._DT_Input = jqFilter[0];
-		
-			jqFilter.val( oPreviousSearch.sSearch.replace('"','&quot;') );
-			jqFilter.bind( 'keyup.DT', function(e) {
-				/* Update all other filter input elements for the new display */
-				var n = oSettings.aanFeatures.f;
-				var val = this.value==="" ? "" : this.value; // mental IE8 fix :-(
-		
-				for ( var i=0, iLen=n.length ; i<iLen ; i++ )
-				{
-					if ( n[i] != $(this).parents('div.dataTables_filter')[0] )
-					{
-						$(n[i]._DT_Input).val( val );
-					}
-				}
-				
-				/* Now do the filter */
-				if ( val != oPreviousSearch.sSearch )
-				{
-					_fnFilterComplete( oSettings, { 
-						"sSearch": val, 
-						"bRegex": oPreviousSearch.bRegex,
-						"bSmart": oPreviousSearch.bSmart ,
-						"bCaseInsensitive": oPreviousSearch.bCaseInsensitive 
-					} );
-				}
-			} );
-		
-			jqFilter
-				.attr('aria-controls', oSettings.sTableId)
-				.bind( 'keypress.DT', function(e) {
-					/* Prevent form submission */
-					if ( e.keyCode == 13 )
-					{
-						return false;
-					}
-				}
-			);
-			
-			return nFilter;
-		}
-		
-		
-		/**
-		 * Filter the table using both the global filter and column based filtering
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {object} oSearch search information
-		 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFilterComplete ( oSettings, oInput, iForce )
-		{
-			var oPrevSearch = oSettings.oPreviousSearch;
-			var aoPrevSearch = oSettings.aoPreSearchCols;
-			var fnSaveFilter = function ( oFilter ) {
-				/* Save the filtering values */
-				oPrevSearch.sSearch = oFilter.sSearch;
-				oPrevSearch.bRegex = oFilter.bRegex;
-				oPrevSearch.bSmart = oFilter.bSmart;
-				oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
-			};
-		
-			/* In server-side processing all filtering is done by the server, so no point hanging around here */
-			if ( !oSettings.oFeatures.bServerSide )
-			{
-				/* Global filter */
-				_fnFilter( oSettings, oInput.sSearch, iForce, oInput.bRegex, oInput.bSmart, oInput.bCaseInsensitive );
-				fnSaveFilter( oInput );
-		
-				/* Now do the individual column filter */
-				for ( var i=0 ; i<oSettings.aoPreSearchCols.length ; i++ )
-				{
-					_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, aoPrevSearch[i].bRegex, 
-						aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
-				}
-				
-				/* Custom filtering */
-				_fnFilterCustom( oSettings );
-			}
-			else
-			{
-				fnSaveFilter( oInput );
-			}
-			
-			/* Tell the draw function we have been filtering */
-			oSettings.bFiltered = true;
-			$(oSettings.oInstance).trigger('filter', oSettings);
-			
-			/* Redraw the table */
-			oSettings._iDisplayStart = 0;
-			_fnCalculateEnd( oSettings );
-			_fnDraw( oSettings );
-			
-			/* Rebuild search array 'offline' */
-			_fnBuildSearchArray( oSettings, 0 );
-		}
-		
-		
-		/**
-		 * Apply custom filtering functions
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFilterCustom( oSettings )
-		{
-			var afnFilters = DataTable.ext.afnFiltering;
-			var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );
-		
-			for ( var i=0, iLen=afnFilters.length ; i<iLen ; i++ )
-			{
-				var iCorrector = 0;
-				for ( var j=0, jLen=oSettings.aiDisplay.length ; j<jLen ; j++ )
-				{
-					var iDisIndex = oSettings.aiDisplay[j-iCorrector];
-					var bTest = afnFilters[i](
-						oSettings,
-						_fnGetRowData( oSettings, iDisIndex, 'filter', aiFilterColumns ),
-						iDisIndex
-					);
-					
-					/* Check if we should use this row based on the filtering function */
-					if ( !bTest )
-					{
-						oSettings.aiDisplay.splice( j-iCorrector, 1 );
-						iCorrector++;
-					}
-				}
-			}
-		}
-		
-		
-		/**
-		 * Filter the table on a per-column basis
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {string} sInput string to filter on
-		 *  @param {int} iColumn column to filter
-		 *  @param {bool} bRegex treat search string as a regular expression or not
-		 *  @param {bool} bSmart use smart filtering or not
-		 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFilterColumn ( oSettings, sInput, iColumn, bRegex, bSmart, bCaseInsensitive )
-		{
-			if ( sInput === "" )
-			{
-				return;
-			}
-			
-			var iIndexCorrector = 0;
-			var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
-			
-			for ( var i=oSettings.aiDisplay.length-1 ; i>=0 ; i-- )
-			{
-				var sData = _fnDataToSearch( _fnGetCellData( oSettings, oSettings.aiDisplay[i], iColumn, 'filter' ),
-					oSettings.aoColumns[iColumn].sType );
-				if ( ! rpSearch.test( sData ) )
-				{
-					oSettings.aiDisplay.splice( i, 1 );
-					iIndexCorrector++;
-				}
-			}
-		}
-		
-		
-		/**
-		 * Filter the data table based on user input and draw the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {string} sInput string to filter on
-		 *  @param {int} iForce optional - force a research of the master array (1) or not (undefined or 0)
-		 *  @param {bool} bRegex treat as a regular expression or not
-		 *  @param {bool} bSmart perform smart filtering or not
-		 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFilter( oSettings, sInput, iForce, bRegex, bSmart, bCaseInsensitive )
-		{
-			var i;
-			var rpSearch = _fnFilterCreateSearch( sInput, bRegex, bSmart, bCaseInsensitive );
-			var oPrevSearch = oSettings.oPreviousSearch;
-			
-			/* Check if we are forcing or not - optional parameter */
-			if ( !iForce )
-			{
-				iForce = 0;
-			}
-			
-			/* Need to take account of custom filtering functions - always filter */
-			if ( DataTable.ext.afnFiltering.length !== 0 )
-			{
-				iForce = 1;
-			}
-			
-			/*
-			 * If the input is blank - we want the full data set
-			 */
-			if ( sInput.length <= 0 )
-			{
-				oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
-				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-			}
-			else
-			{
-				/*
-				 * We are starting a new search or the new search string is smaller 
-				 * then the old one (i.e. delete). Search from the master array
-			 	 */
-				if ( oSettings.aiDisplay.length == oSettings.aiDisplayMaster.length ||
-					   oPrevSearch.sSearch.length > sInput.length || iForce == 1 ||
-					   sInput.indexOf(oPrevSearch.sSearch) !== 0 )
-				{
-					/* Nuke the old display array - we are going to rebuild it */
-					oSettings.aiDisplay.splice( 0, oSettings.aiDisplay.length);
-					
-					/* Force a rebuild of the search array */
-					_fnBuildSearchArray( oSettings, 1 );
-					
-					/* Search through all records to populate the search array
-					 * The the oSettings.aiDisplayMaster and asDataSearch arrays have 1 to 1 
-					 * mapping
-					 */
-					for ( i=0 ; i<oSettings.aiDisplayMaster.length ; i++ )
-					{
-						if ( rpSearch.test(oSettings.asDataSearch[i]) )
-						{
-							oSettings.aiDisplay.push( oSettings.aiDisplayMaster[i] );
-						}
-					}
-			  }
-			  else
-				{
-			  	/* Using old search array - refine it - do it this way for speed
-			  	 * Don't have to search the whole master array again
-					 */
-			  	var iIndexCorrector = 0;
-			  	
-			  	/* Search the current results */
-			  	for ( i=0 ; i<oSettings.asDataSearch.length ; i++ )
-					{
-			  		if ( ! rpSearch.test(oSettings.asDataSearch[i]) )
-						{
-			  			oSettings.aiDisplay.splice( i-iIndexCorrector, 1 );
-			  			iIndexCorrector++;
-			  		}
-			  	}
-			  }
-			}
-		}
-		
-		
-		/**
-		 * Create an array which can be quickly search through
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iMaster use the master data array - optional
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnBuildSearchArray ( oSettings, iMaster )
-		{
-			if ( !oSettings.oFeatures.bServerSide )
-			{
-				/* Clear out the old data */
-				oSettings.asDataSearch = [];
-		
-				var aiFilterColumns = _fnGetColumns( oSettings, 'bSearchable' );
-				var aiIndex = (iMaster===1) ?
-				 	oSettings.aiDisplayMaster :
-				 	oSettings.aiDisplay;
-				
-				for ( var i=0, iLen=aiIndex.length ; i<iLen ; i++ )
-				{
-					oSettings.asDataSearch[i] = _fnBuildSearchRow(
-						oSettings,
-						_fnGetRowData( oSettings, aiIndex[i], 'filter', aiFilterColumns )
-					);
-				}
-			}
-		}
-		
-		
-		/**
-		 * Create a searchable string from a single data row
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {array} aData Row data array to use for the data to search
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnBuildSearchRow( oSettings, aData )
-		{
-			var sSearch = aData.join('  ');
-			
-			/* If it looks like there is an HTML entity in the string, attempt to decode it */
-			if ( sSearch.indexOf('&') !== -1 )
-			{
-				sSearch = $('<div>').html(sSearch).text();
-			}
-			
-			// Strip newline characters
-			return sSearch.replace( /[\n\r]/g, " " );
-		}
-		
-		/**
-		 * Build a regular expression object suitable for searching a table
-		 *  @param {string} sSearch string to search for
-		 *  @param {bool} bRegex treat as a regular expression or not
-		 *  @param {bool} bSmart perform smart filtering or not
-		 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
-		 *  @returns {RegExp} constructed object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFilterCreateSearch( sSearch, bRegex, bSmart, bCaseInsensitive )
-		{
-			var asSearch, sRegExpString;
-			
-			if ( bSmart )
-			{
-				/* Generate the regular expression to use. Something along the lines of:
-				 * ^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$
-				 */
-				asSearch = bRegex ? sSearch.split( ' ' ) : _fnEscapeRegex( sSearch ).split( ' ' );
-				sRegExpString = '^(?=.*?'+asSearch.join( ')(?=.*?' )+').*$';
-				return new RegExp( sRegExpString, bCaseInsensitive ? "i" : "" );
-			}
-			else
-			{
-				sSearch = bRegex ? sSearch : _fnEscapeRegex( sSearch );
-				return new RegExp( sSearch, bCaseInsensitive ? "i" : "" );
-			}
-		}
-		
-		
-		/**
-		 * Convert raw data into something that the user can search on
-		 *  @param {string} sData data to be modified
-		 *  @param {string} sType data type
-		 *  @returns {string} search string
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnDataToSearch ( sData, sType )
-		{
-			if ( typeof DataTable.ext.ofnSearch[sType] === "function" )
-			{
-				return DataTable.ext.ofnSearch[sType]( sData );
-			}
-			else if ( sData === null )
-			{
-				return '';
-			}
-			else if ( sType == "html" )
-			{
-				return sData.replace(/[\r\n]/g," ").replace( /<.*?>/g, "" );
-			}
-			else if ( typeof sData === "string" )
-			{
-				return sData.replace(/[\r\n]/g," ");
-			}
-			return sData;
-		}
-		
-		
-		/**
-		 * scape a string such that it can be used in a regular expression
-		 *  @param {string} sVal string to escape
-		 *  @returns {string} escaped string
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnEscapeRegex ( sVal )
-		{
-			var acEscape = [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ];
-			var reReplace = new RegExp( '(\\' + acEscape.join('|\\') + ')', 'g' );
-			return sVal.replace(reReplace, '\\$1');
-		}
-		
-		
-		/**
-		 * Generate the node required for the info display
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {node} Information element
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFeatureHtmlInfo ( oSettings )
-		{
-			var nInfo = document.createElement( 'div' );
-			nInfo.className = oSettings.oClasses.sInfo;
-			
-			/* Actions that are to be taken once only for this feature */
-			if ( !oSettings.aanFeatures.i )
-			{
-				/* Add draw callback */
-				oSettings.aoDrawCallback.push( {
-					"fn": _fnUpdateInfo,
-					"sName": "information"
-				} );
-				
-				/* Add id */
-				nInfo.id = oSettings.sTableId+'_info';
-			}
-			oSettings.nTable.setAttribute( 'aria-describedby', oSettings.sTableId+'_info' );
-			
-			return nInfo;
-		}
-		
-		
-		/**
-		 * Update the information elements in the display
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnUpdateInfo ( oSettings )
-		{
-			/* Show information about the table */
-			if ( !oSettings.oFeatures.bInfo || oSettings.aanFeatures.i.length === 0 )
-			{
-				return;
-			}
-			
-			var
-				oLang = oSettings.oLanguage,
-				iStart = oSettings._iDisplayStart+1,
-				iEnd = oSettings.fnDisplayEnd(),
-				iMax = oSettings.fnRecordsTotal(),
-				iTotal = oSettings.fnRecordsDisplay(),
-				sOut;
-			
-			if ( iTotal === 0 )
-			{
-				/* Empty record set */
-				sOut = oLang.sInfoEmpty;
-			}
-			else {
-				/* Normal record set */
-				sOut = oLang.sInfo;
-			}
-		
-			if ( iTotal != iMax )
-			{
-				/* Record set after filtering */
-				sOut += ' ' + oLang.sInfoFiltered;
-			}
-		
-			// Convert the macros
-			sOut += oLang.sInfoPostFix;
-			sOut = _fnInfoMacros( oSettings, sOut );
-			
-			if ( oLang.fnInfoCallback !== null )
-			{
-				sOut = oLang.fnInfoCallback.call( oSettings.oInstance, 
-					oSettings, iStart, iEnd, iMax, iTotal, sOut );
-			}
-			
-			var n = oSettings.aanFeatures.i;
-			for ( var i=0, iLen=n.length ; i<iLen ; i++ )
-			{
-				$(n[i]).html( sOut );
-			}
-		}
-		
-		
-		function _fnInfoMacros ( oSettings, str )
-		{
-			var
-				iStart = oSettings._iDisplayStart+1,
-				sStart = oSettings.fnFormatNumber( iStart ),
-				iEnd = oSettings.fnDisplayEnd(),
-				sEnd = oSettings.fnFormatNumber( iEnd ),
-				iTotal = oSettings.fnRecordsDisplay(),
-				sTotal = oSettings.fnFormatNumber( iTotal ),
-				iMax = oSettings.fnRecordsTotal(),
-				sMax = oSettings.fnFormatNumber( iMax );
-		
-			// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
-			// internally
-			if ( oSettings.oScroll.bInfinite )
-			{
-				sStart = oSettings.fnFormatNumber( 1 );
-			}
-		
-			return str.
-				replace(/_START_/g, sStart).
-				replace(/_END_/g,   sEnd).
-				replace(/_TOTAL_/g, sTotal).
-				replace(/_MAX_/g,   sMax);
-		}
-		
-		
-		
-		/**
-		 * Draw the table for the first time, adding all required features
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnInitialise ( oSettings )
-		{
-			var i, iLen, iAjaxStart=oSettings.iInitDisplayStart;
-			
-			/* Ensure that the table data is fully initialised */
-			if ( oSettings.bInitialised === false )
-			{
-				setTimeout( function(){ _fnInitialise( oSettings ); }, 200 );
-				return;
-			}
-			
-			/* Show the display HTML options */
-			_fnAddOptionsHtml( oSettings );
-			
-			/* Build and draw the header / footer for the table */
-			_fnBuildHead( oSettings );
-			_fnDrawHead( oSettings, oSettings.aoHeader );
-			if ( oSettings.nTFoot )
-			{
-				_fnDrawHead( oSettings, oSettings.aoFooter );
-			}
-		
-			/* Okay to show that something is going on now */
-			_fnProcessingDisplay( oSettings, true );
-			
-			/* Calculate sizes for columns */
-			if ( oSettings.oFeatures.bAutoWidth )
-			{
-				_fnCalculateColumnWidths( oSettings );
-			}
-			
-			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				if ( oSettings.aoColumns[i].sWidth !== null )
-				{
-					oSettings.aoColumns[i].nTh.style.width = _fnStringToCss( oSettings.aoColumns[i].sWidth );
-				}
-			}
-			
-			/* If there is default sorting required - let's do it. The sort function will do the
-			 * drawing for us. Otherwise we draw the table regardless of the Ajax source - this allows
-			 * the table to look initialised for Ajax sourcing data (show 'loading' message possibly)
-			 */
-			if ( oSettings.oFeatures.bSort )
-			{
-				_fnSort( oSettings );
-			}
-			else if ( oSettings.oFeatures.bFilter )
-			{
-				_fnFilterComplete( oSettings, oSettings.oPreviousSearch );
-			}
-			else
-			{
-				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-				_fnCalculateEnd( oSettings );
-				_fnDraw( oSettings );
-			}
-			
-			/* if there is an ajax source load the data */
-			if ( oSettings.sAjaxSource !== null && !oSettings.oFeatures.bServerSide )
-			{
-				var aoData = [];
-				_fnServerParams( oSettings, aoData );
-				oSettings.fnServerData.call( oSettings.oInstance, oSettings.sAjaxSource, aoData, function(json) {
-					var aData = (oSettings.sAjaxDataProp !== "") ?
-					 	_fnGetObjectDataFn( oSettings.sAjaxDataProp )(json) : json;
-		
-					/* Got the data - add it to the table */
-					for ( i=0 ; i<aData.length ; i++ )
-					{
-						_fnAddData( oSettings, aData[i] );
-					}
-					
-					/* Reset the init display for cookie saving. We've already done a filter, and
-					 * therefore cleared it before. So we need to make it appear 'fresh'
-					 */
-					oSettings.iInitDisplayStart = iAjaxStart;
-					
-					if ( oSettings.oFeatures.bSort )
-					{
-						_fnSort( oSettings );
-					}
-					else
-					{
-						oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-						_fnCalculateEnd( oSettings );
-						_fnDraw( oSettings );
-					}
-					
-					_fnProcessingDisplay( oSettings, false );
-					_fnInitComplete( oSettings, json );
-				}, oSettings );
-				return;
-			}
-			
-			/* Server-side processing initialisation complete is done at the end of _fnDraw */
-			if ( !oSettings.oFeatures.bServerSide )
-			{
-				_fnProcessingDisplay( oSettings, false );
-				_fnInitComplete( oSettings );
-			}
-		}
-		
-		
-		/**
-		 * Draw the table for the first time, adding all required features
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
-		 *    with client-side processing (optional)
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnInitComplete ( oSettings, json )
-		{
-			oSettings._bInitComplete = true;
-			_fnCallbackFire( oSettings, 'aoInitComplete', 'init', [oSettings, json] );
-		}
-		
-		
-		/**
-		 * Language compatibility - when certain options are given, and others aren't, we
-		 * need to duplicate the values over, in order to provide backwards compatibility
-		 * with older language files.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnLanguageCompat( oLanguage )
-		{
-			var oDefaults = DataTable.defaults.oLanguage;
-		
-			/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
-			 * sZeroRecords - assuming that is given.
-			 */
-			if ( !oLanguage.sEmptyTable && oLanguage.sZeroRecords &&
-				oDefaults.sEmptyTable === "No data available in table" )
-			{
-				_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sEmptyTable' );
-			}
-		
-			/* Likewise with loading records */
-			if ( !oLanguage.sLoadingRecords && oLanguage.sZeroRecords &&
-				oDefaults.sLoadingRecords === "Loading..." )
-			{
-				_fnMap( oLanguage, oLanguage, 'sZeroRecords', 'sLoadingRecords' );
-			}
-		}
-		
-		
-		
-		/**
-		 * Generate the node required for user display length changing
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {node} Display length feature node
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFeatureHtmlLength ( oSettings )
-		{
-			if ( oSettings.oScroll.bInfinite )
-			{
-				return null;
-			}
-			
-			/* This can be overruled by not using the _MENU_ var/macro in the language variable */
-			var sName = 'name="'+oSettings.sTableId+'_length"';
-			var sStdMenu = '<select size="1" '+sName+'>';
-			var i, iLen;
-			var aLengthMenu = oSettings.aLengthMenu;
-			
-			if ( aLengthMenu.length == 2 && typeof aLengthMenu[0] === 'object' && 
-					typeof aLengthMenu[1] === 'object' )
-			{
-				for ( i=0, iLen=aLengthMenu[0].length ; i<iLen ; i++ )
-				{
-					sStdMenu += '<option value="'+aLengthMenu[0][i]+'">'+aLengthMenu[1][i]+'</option>';
-				}
-			}
-			else
-			{
-				for ( i=0, iLen=aLengthMenu.length ; i<iLen ; i++ )
-				{
-					sStdMenu += '<option value="'+aLengthMenu[i]+'">'+aLengthMenu[i]+'</option>';
-				}
-			}
-			sStdMenu += '</select>';
-			
-			var nLength = document.createElement( 'div' );
-			if ( !oSettings.aanFeatures.l )
-			{
-				nLength.id = oSettings.sTableId+'_length';
-			}
-			nLength.className = oSettings.oClasses.sLength;
-			nLength.innerHTML = '<label>'+oSettings.oLanguage.sLengthMenu.replace( '_MENU_', sStdMenu )+'</label>';
-			
-			/*
-			 * Set the length to the current display length - thanks to Andrea Pavlovic for this fix,
-			 * and Stefan Skopnik for fixing the fix!
-			 */
-			$('select option[value="'+oSettings._iDisplayLength+'"]', nLength).attr("selected", true);
-			
-			$('select', nLength).bind( 'change.DT', function(e) {
-				var iVal = $(this).val();
-				
-				/* Update all other length options for the new display */
-				var n = oSettings.aanFeatures.l;
-				for ( i=0, iLen=n.length ; i<iLen ; i++ )
-				{
-					if ( n[i] != this.parentNode )
-					{
-						$('select', n[i]).val( iVal );
-					}
-				}
-				
-				/* Redraw the table */
-				oSettings._iDisplayLength = parseInt(iVal, 10);
-				_fnCalculateEnd( oSettings );
-				
-				/* If we have space to show extra rows (backing up from the end point - then do so */
-				if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() )
-				{
-					oSettings._iDisplayStart = oSettings.fnDisplayEnd() - oSettings._iDisplayLength;
-					if ( oSettings._iDisplayStart < 0 )
-					{
-						oSettings._iDisplayStart = 0;
-					}
-				}
-				
-				if ( oSettings._iDisplayLength == -1 )
-				{
-					oSettings._iDisplayStart = 0;
-				}
-				
-				_fnDraw( oSettings );
-			} );
-		
-		
-			$('select', nLength).attr('aria-controls', oSettings.sTableId);
-			
-			return nLength;
-		}
-		
-		
-		/**
-		 * Recalculate the end point based on the start point
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnCalculateEnd( oSettings )
-		{
-			if ( oSettings.oFeatures.bPaginate === false )
-			{
-				oSettings._iDisplayEnd = oSettings.aiDisplay.length;
-			}
-			else
-			{
-				/* Set the end point of the display - based on how many elements there are
-				 * still to display
-				 */
-				if ( oSettings._iDisplayStart + oSettings._iDisplayLength > oSettings.aiDisplay.length ||
-					   oSettings._iDisplayLength == -1 )
-				{
-					oSettings._iDisplayEnd = oSettings.aiDisplay.length;
-				}
-				else
-				{
-					oSettings._iDisplayEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
-				}
-			}
-		}
-		
-		
-		
-		/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-		 * Note that most of the paging logic is done in 
-		 * DataTable.ext.oPagination
-		 */
-		
-		/**
-		 * Generate the node required for default pagination
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {node} Pagination feature node
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFeatureHtmlPaginate ( oSettings )
-		{
-			if ( oSettings.oScroll.bInfinite )
-			{
-				return null;
-			}
-			
-			var nPaginate = document.createElement( 'div' );
-			nPaginate.className = oSettings.oClasses.sPaging+oSettings.sPaginationType;
-			
-			DataTable.ext.oPagination[ oSettings.sPaginationType ].fnInit( oSettings, nPaginate, 
-				function( oSettings ) {
-					_fnCalculateEnd( oSettings );
-					_fnDraw( oSettings );
-				}
-			);
-			
-			/* Add a draw callback for the pagination on first instance, to update the paging display */
-			if ( !oSettings.aanFeatures.p )
-			{
-				oSettings.aoDrawCallback.push( {
-					"fn": function( oSettings ) {
-						DataTable.ext.oPagination[ oSettings.sPaginationType ].fnUpdate( oSettings, function( oSettings ) {
-							_fnCalculateEnd( oSettings );
-							_fnDraw( oSettings );
-						} );
-					},
-					"sName": "pagination"
-				} );
-			}
-			return nPaginate;
-		}
-		
-		
-		/**
-		 * Alter the display settings to change the page
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
-		 *    or page number to jump to (integer)
-		 *  @returns {bool} true page has changed, false - no change (no effect) eg 'first' on page 1
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnPageChange ( oSettings, mAction )
-		{
-			var iOldStart = oSettings._iDisplayStart;
-			
-			if ( typeof mAction === "number" )
-			{
-				oSettings._iDisplayStart = mAction * oSettings._iDisplayLength;
-				if ( oSettings._iDisplayStart > oSettings.fnRecordsDisplay() )
-				{
-					oSettings._iDisplayStart = 0;
-				}
-			}
-			else if ( mAction == "first" )
-			{
-				oSettings._iDisplayStart = 0;
-			}
-			else if ( mAction == "previous" )
-			{
-				oSettings._iDisplayStart = oSettings._iDisplayLength>=0 ?
-					oSettings._iDisplayStart - oSettings._iDisplayLength :
-					0;
-				
-				/* Correct for under-run */
-				if ( oSettings._iDisplayStart < 0 )
-				{
-				  oSettings._iDisplayStart = 0;
-				}
-			}
-			else if ( mAction == "next" )
-			{
-				if ( oSettings._iDisplayLength >= 0 )
-				{
-					/* Make sure we are not over running the display array */
-					if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
-					{
-						oSettings._iDisplayStart += oSettings._iDisplayLength;
-					}
-				}
-				else
-				{
-					oSettings._iDisplayStart = 0;
-				}
-			}
-			else if ( mAction == "last" )
-			{
-				if ( oSettings._iDisplayLength >= 0 )
-				{
-					var iPages = parseInt( (oSettings.fnRecordsDisplay()-1) / oSettings._iDisplayLength, 10 ) + 1;
-					oSettings._iDisplayStart = (iPages-1) * oSettings._iDisplayLength;
-				}
-				else
-				{
-					oSettings._iDisplayStart = 0;
-				}
-			}
-			else
-			{
-				_fnLog( oSettings, 0, "Unknown paging action: "+mAction );
-			}
-			$(oSettings.oInstance).trigger('page', oSettings);
-			
-			return iOldStart != oSettings._iDisplayStart;
-		}
-		
-		
-		
-		/**
-		 * Generate the node required for the processing node
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {node} Processing element
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFeatureHtmlProcessing ( oSettings )
-		{
-			var nProcessing = document.createElement( 'div' );
-			
-			if ( !oSettings.aanFeatures.r )
-			{
-				nProcessing.id = oSettings.sTableId+'_processing';
-			}
-			nProcessing.innerHTML = oSettings.oLanguage.sProcessing;
-			nProcessing.className = oSettings.oClasses.sProcessing;
-			oSettings.nTable.parentNode.insertBefore( nProcessing, oSettings.nTable );
-			
-			return nProcessing;
-		}
-		
-		
-		/**
-		 * Display or hide the processing indicator
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {bool} bShow Show the processing indicator (true) or not (false)
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnProcessingDisplay ( oSettings, bShow )
-		{
-			if ( oSettings.oFeatures.bProcessing )
-			{
-				var an = oSettings.aanFeatures.r;
-				for ( var i=0, iLen=an.length ; i<iLen ; i++ )
-				{
-					an[i].style.visibility = bShow ? "visible" : "hidden";
-				}
-			}
-		
-			$(oSettings.oInstance).trigger('processing', [oSettings, bShow]);
-		}
-		
-		/**
-		 * Add any control elements for the table - specifically scrolling
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {node} Node to add to the DOM
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnFeatureHtmlTable ( oSettings )
-		{
-			/* Check if scrolling is enabled or not - if not then leave the DOM unaltered */
-			if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
-			{
-				return oSettings.nTable;
-			}
-			
-			/*
-			 * The HTML structure that we want to generate in this function is:
-			 *  div - nScroller
-			 *    div - nScrollHead
-			 *      div - nScrollHeadInner
-			 *        table - nScrollHeadTable
-			 *          thead - nThead
-			 *    div - nScrollBody
-			 *      table - oSettings.nTable
-			 *        thead - nTheadSize
-			 *        tbody - nTbody
-			 *    div - nScrollFoot
-			 *      div - nScrollFootInner
-			 *        table - nScrollFootTable
-			 *          tfoot - nTfoot
-			 */
-			var
-			 	nScroller = document.createElement('div'),
-			 	nScrollHead = document.createElement('div'),
-			 	nScrollHeadInner = document.createElement('div'),
-			 	nScrollBody = document.createElement('div'),
-			 	nScrollFoot = document.createElement('div'),
-			 	nScrollFootInner = document.createElement('div'),
-			 	nScrollHeadTable = oSettings.nTable.cloneNode(false),
-			 	nScrollFootTable = oSettings.nTable.cloneNode(false),
-				nThead = oSettings.nTable.getElementsByTagName('thead')[0],
-			 	nTfoot = oSettings.nTable.getElementsByTagName('tfoot').length === 0 ? null : 
-					oSettings.nTable.getElementsByTagName('tfoot')[0],
-				oClasses = oSettings.oClasses;
-			
-			nScrollHead.appendChild( nScrollHeadInner );
-			nScrollFoot.appendChild( nScrollFootInner );
-			nScrollBody.appendChild( oSettings.nTable );
-			nScroller.appendChild( nScrollHead );
-			nScroller.appendChild( nScrollBody );
-			nScrollHeadInner.appendChild( nScrollHeadTable );
-			nScrollHeadTable.appendChild( nThead );
-			if ( nTfoot !== null )
-			{
-				nScroller.appendChild( nScrollFoot );
-				nScrollFootInner.appendChild( nScrollFootTable );
-				nScrollFootTable.appendChild( nTfoot );
-			}
-			
-			nScroller.className = oClasses.sScrollWrapper;
-			nScrollHead.className = oClasses.sScrollHead;
-			nScrollHeadInner.className = oClasses.sScrollHeadInner;
-			nScrollBody.className = oClasses.sScrollBody;
-			nScrollFoot.className = oClasses.sScrollFoot;
-			nScrollFootInner.className = oClasses.sScrollFootInner;
-			
-			if ( oSettings.oScroll.bAutoCss )
-			{
-				nScrollHead.style.overflow = "hidden";
-				nScrollHead.style.position = "relative";
-				nScrollFoot.style.overflow = "hidden";
-				nScrollBody.style.overflow = "auto";
-			}
-			
-			nScrollHead.style.border = "0";
-			nScrollHead.style.width = "100%";
-			nScrollFoot.style.border = "0";
-			nScrollHeadInner.style.width = oSettings.oScroll.sXInner !== "" ?
-				oSettings.oScroll.sXInner : "100%"; /* will be overwritten */
-			
-			/* Modify attributes to respect the clones */
-			nScrollHeadTable.removeAttribute('id');
-			nScrollHeadTable.style.marginLeft = "0";
-			oSettings.nTable.style.marginLeft = "0";
-			if ( nTfoot !== null )
-			{
-				nScrollFootTable.removeAttribute('id');
-				nScrollFootTable.style.marginLeft = "0";
-			}
-			
-			/* Move caption elements from the body to the header, footer or leave where it is
-			 * depending on the configuration. Note that the DTD says there can be only one caption */
-			var nCaption = $(oSettings.nTable).children('caption');
-			if ( nCaption.length > 0 )
-			{
-				nCaption = nCaption[0];
-				if ( nCaption._captionSide === "top" )
-				{
-					nScrollHeadTable.appendChild( nCaption );
-				}
-				else if ( nCaption._captionSide === "bottom" && nTfoot )
-				{
-					nScrollFootTable.appendChild( nCaption );
-				}
-			}
-			
-			/*
-			 * Sizing
-			 */
-			/* When x-scrolling add the width and a scroller to move the header with the body */
-			if ( oSettings.oScroll.sX !== "" )
-			{
-				nScrollHead.style.width = _fnStringToCss( oSettings.oScroll.sX );
-				nScrollBody.style.width = _fnStringToCss( oSettings.oScroll.sX );
-				
-				if ( nTfoot !== null )
-				{
-					nScrollFoot.style.width = _fnStringToCss( oSettings.oScroll.sX );	
-				}
-				
-				/* When the body is scrolled, then we also want to scroll the headers */
-				$(nScrollBody).scroll( function (e) {
-					nScrollHead.scrollLeft = this.scrollLeft;
-					
-					if ( nTfoot !== null )
-					{
-						nScrollFoot.scrollLeft = this.scrollLeft;
-					}
-				} );
-			}
-			
-			/* When yscrolling, add the height */
-			if ( oSettings.oScroll.sY !== "" )
-			{
-				nScrollBody.style.height = _fnStringToCss( oSettings.oScroll.sY );
-			}
-			
-			/* Redraw - align columns across the tables */
-			oSettings.aoDrawCallback.push( {
-				"fn": _fnScrollDraw,
-				"sName": "scrolling"
-			} );
-			
-			/* Infinite scrolling event handlers */
-			if ( oSettings.oScroll.bInfinite )
-			{
-				$(nScrollBody).scroll( function() {
-					/* Use a blocker to stop scrolling from loading more data while other data is still loading */
-					if ( !oSettings.bDrawing && $(this).scrollTop() !== 0 )
-					{
-						/* Check if we should load the next data set */
-						if ( $(this).scrollTop() + $(this).height() > 
-							$(oSettings.nTable).height() - oSettings.oScroll.iLoadGap )
-						{
-							/* Only do the redraw if we have to - we might be at the end of the data */
-							if ( oSettings.fnDisplayEnd() < oSettings.fnRecordsDisplay() )
-							{
-								_fnPageChange( oSettings, 'next' );
-								_fnCalculateEnd( oSettings );
-								_fnDraw( oSettings );
-							}
-						}
-					}
-				} );
-			}
-			
-			oSettings.nScrollHead = nScrollHead;
-			oSettings.nScrollFoot = nScrollFoot;
-			
-			return nScroller;
-		}
-		
-		
-		/**
-		 * Update the various tables for resizing. It's a bit of a pig this function, but
-		 * basically the idea to:
-		 *   1. Re-create the table inside the scrolling div
-		 *   2. Take live measurements from the DOM
-		 *   3. Apply the measurements
-		 *   4. Clean up
-		 *  @param {object} o dataTables settings object
-		 *  @returns {node} Node to add to the DOM
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnScrollDraw ( o )
-		{
-			var
-				nScrollHeadInner = o.nScrollHead.getElementsByTagName('div')[0],
-				nScrollHeadTable = nScrollHeadInner.getElementsByTagName('table')[0],
-				nScrollBody = o.nTable.parentNode,
-				i, iLen, j, jLen, anHeadToSize, anHeadSizers, anFootSizers, anFootToSize, oStyle, iVis,
-				nTheadSize, nTfootSize,
-				iWidth, aApplied=[], aAppliedFooter=[], iSanityWidth,
-				nScrollFootInner = (o.nTFoot !== null) ? o.nScrollFoot.getElementsByTagName('div')[0] : null,
-				nScrollFootTable = (o.nTFoot !== null) ? nScrollFootInner.getElementsByTagName('table')[0] : null,
-				ie67 = o.oBrowser.bScrollOversize,
-				zeroOut = function(nSizer) {
-					oStyle = nSizer.style;
-					oStyle.paddingTop = "0";
-					oStyle.paddingBottom = "0";
-					oStyle.borderTopWidth = "0";
-					oStyle.borderBottomWidth = "0";
-					oStyle.height = 0;
-				};
-			
-			/*
-			 * 1. Re-create the table inside the scrolling div
-			 */
-			
-			/* Remove the old minimised thead and tfoot elements in the inner table */
-			$(o.nTable).children('thead, tfoot').remove();
-		
-			/* Clone the current header and footer elements and then place it into the inner table */
-			nTheadSize = $(o.nTHead).clone()[0];
-			o.nTable.insertBefore( nTheadSize, o.nTable.childNodes[0] );
-			anHeadToSize = o.nTHead.getElementsByTagName('tr');
-			anHeadSizers = nTheadSize.getElementsByTagName('tr');
-			
-			if ( o.nTFoot !== null )
-			{
-				nTfootSize = $(o.nTFoot).clone()[0];
-				o.nTable.insertBefore( nTfootSize, o.nTable.childNodes[1] );
-				anFootToSize = o.nTFoot.getElementsByTagName('tr');
-				anFootSizers = nTfootSize.getElementsByTagName('tr');
-			}
-			
-			/*
-			 * 2. Take live measurements from the DOM - do not alter the DOM itself!
-			 */
-			
-			/* Remove old sizing and apply the calculated column widths
-			 * Get the unique column headers in the newly created (cloned) header. We want to apply the
-			 * calculated sizes to this header
-			 */
-			if ( o.oScroll.sX === "" )
-			{
-				nScrollBody.style.width = '100%';
-				nScrollHeadInner.parentNode.style.width = '100%';
-			}
-			
-			var nThs = _fnGetUniqueThs( o, nTheadSize );
-			for ( i=0, iLen=nThs.length ; i<iLen ; i++ )
-			{
-				iVis = _fnVisibleToColumnIndex( o, i );
-				nThs[i].style.width = o.aoColumns[iVis].sWidth;
-			}
-			
-			if ( o.nTFoot !== null )
-			{
-				_fnApplyToChildren( function(n) {
-					n.style.width = "";
-				}, anFootSizers );
-			}
-		
-			// If scroll collapse is enabled, when we put the headers back into the body for sizing, we
-			// will end up forcing the scrollbar to appear, making our measurements wrong for when we
-			// then hide it (end of this function), so add the header height to the body scroller.
-			if ( o.oScroll.bCollapse && o.oScroll.sY !== "" )
-			{
-				nScrollBody.style.height = (nScrollBody.offsetHeight + o.nTHead.offsetHeight)+"px";
-			}
-			
-			/* Size the table as a whole */
-			iSanityWidth = $(o.nTable).outerWidth();
-			if ( o.oScroll.sX === "" )
-			{
-				/* No x scrolling */
-				o.nTable.style.width = "100%";
-				
-				/* I know this is rubbish - but IE7 will make the width of the table when 100% include
-				 * the scrollbar - which is shouldn't. When there is a scrollbar we need to take this
-				 * into account.
-				 */
-				if ( ie67 && ($('tbody', nScrollBody).height() > nScrollBody.offsetHeight || 
-					$(nScrollBody).css('overflow-y') == "scroll")  )
-				{
-					o.nTable.style.width = _fnStringToCss( $(o.nTable).outerWidth() - o.oScroll.iBarWidth);
-				}
-			}
-			else
-			{
-				if ( o.oScroll.sXInner !== "" )
-				{
-					/* x scroll inner has been given - use it */
-					o.nTable.style.width = _fnStringToCss(o.oScroll.sXInner);
-				}
-				else if ( iSanityWidth == $(nScrollBody).width() &&
-				   $(nScrollBody).height() < $(o.nTable).height() )
-				{
-					/* There is y-scrolling - try to take account of the y scroll bar */
-					o.nTable.style.width = _fnStringToCss( iSanityWidth-o.oScroll.iBarWidth );
-					if ( $(o.nTable).outerWidth() > iSanityWidth-o.oScroll.iBarWidth )
-					{
-						/* Not possible to take account of it */
-						o.nTable.style.width = _fnStringToCss( iSanityWidth );
-					}
-				}
-				else
-				{
-					/* All else fails */
-					o.nTable.style.width = _fnStringToCss( iSanityWidth );
-				}
-			}
-			
-			/* Recalculate the sanity width - now that we've applied the required width, before it was
-			 * a temporary variable. This is required because the column width calculation is done
-			 * before this table DOM is created.
-			 */
-			iSanityWidth = $(o.nTable).outerWidth();
-			
-			/* We want the hidden header to have zero height, so remove padding and borders. Then
-			 * set the width based on the real headers
-			 */
-			
-			// Apply all styles in one pass. Invalidates layout only once because we don't read any 
-			// DOM properties.
-			_fnApplyToChildren( zeroOut, anHeadSizers );
-			 
-			// Read all widths in next pass. Forces layout only once because we do not change 
-			// any DOM properties.
-			_fnApplyToChildren( function(nSizer) {
-				aApplied.push( _fnStringToCss( $(nSizer).width() ) );
-			}, anHeadSizers );
-			 
-			// Apply all widths in final pass. Invalidates layout only once because we do not
-			// read any DOM properties.
-			_fnApplyToChildren( function(nToSize, i) {
-				nToSize.style.width = aApplied[i];
-			}, anHeadToSize );
-		
-			$(anHeadSizers).height(0);
-			
-			/* Same again with the footer if we have one */
-			if ( o.nTFoot !== null )
-			{
-				_fnApplyToChildren( zeroOut, anFootSizers );
-				 
-				_fnApplyToChildren( function(nSizer) {
-					aAppliedFooter.push( _fnStringToCss( $(nSizer).width() ) );
-				}, anFootSizers );
-				 
-				_fnApplyToChildren( function(nToSize, i) {
-					nToSize.style.width = aAppliedFooter[i];
-				}, anFootToSize );
-		
-				$(anFootSizers).height(0);
-			}
-			
-			/*
-			 * 3. Apply the measurements
-			 */
-			
-			/* "Hide" the header and footer that we used for the sizing. We want to also fix their width
-			 * to what they currently are
-			 */
-			_fnApplyToChildren( function(nSizer, i) {
-				nSizer.innerHTML = "";
-				nSizer.style.width = aApplied[i];
-			}, anHeadSizers );
-			
-			if ( o.nTFoot !== null )
-			{
-				_fnApplyToChildren( function(nSizer, i) {
-					nSizer.innerHTML = "";
-					nSizer.style.width = aAppliedFooter[i];
-				}, anFootSizers );
-			}
-			
-			/* Sanity check that the table is of a sensible width. If not then we are going to get
-			 * misalignment - try to prevent this by not allowing the table to shrink below its min width
-			 */
-			if ( $(o.nTable).outerWidth() < iSanityWidth )
-			{
-				/* The min width depends upon if we have a vertical scrollbar visible or not */
-				var iCorrection = ((nScrollBody.scrollHeight > nScrollBody.offsetHeight || 
-					$(nScrollBody).css('overflow-y') == "scroll")) ?
-						iSanityWidth+o.oScroll.iBarWidth : iSanityWidth;
-				
-				/* IE6/7 are a law unto themselves... */
-				if ( ie67 && (nScrollBody.scrollHeight > 
-					nScrollBody.offsetHeight || $(nScrollBody).css('overflow-y') == "scroll")  )
-				{
-					o.nTable.style.width = _fnStringToCss( iCorrection-o.oScroll.iBarWidth );
-				}
-				
-				/* Apply the calculated minimum width to the table wrappers */
-				nScrollBody.style.width = _fnStringToCss( iCorrection );
-				o.nScrollHead.style.width = _fnStringToCss( iCorrection );
-				
-				if ( o.nTFoot !== null )
-				{
-					o.nScrollFoot.style.width = _fnStringToCss( iCorrection );
-				}
-				
-				/* And give the user a warning that we've stopped the table getting too small */
-				if ( o.oScroll.sX === "" )
-				{
-					_fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
-						" misalignment. The table has been drawn at its minimum possible width." );
-				}
-				else if ( o.oScroll.sXInner !== "" )
-				{
-					_fnLog( o, 1, "The table cannot fit into the current element which will cause column"+
-						" misalignment. Increase the sScrollXInner value or remove it to allow automatic"+
-						" calculation" );
-				}
-			}
-			else
-			{
-				nScrollBody.style.width = _fnStringToCss( '100%' );
-				o.nScrollHead.style.width = _fnStringToCss( '100%' );
-				
-				if ( o.nTFoot !== null )
-				{
-					o.nScrollFoot.style.width = _fnStringToCss( '100%' );
-				}
-			}
-			
-			
-			/*
-			 * 4. Clean up
-			 */
-			if ( o.oScroll.sY === "" )
-			{
-				/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
-				 * the scrollbar height from the visible display, rather than adding it on. We need to
-				 * set the height in order to sort this. Don't want to do it in any other browsers.
-				 */
-				if ( ie67 )
-				{
-					nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+o.oScroll.iBarWidth );
-				}
-			}
-			
-			if ( o.oScroll.sY !== "" && o.oScroll.bCollapse )
-			{
-				nScrollBody.style.height = _fnStringToCss( o.oScroll.sY );
-				
-				var iExtra = (o.oScroll.sX !== "" && o.nTable.offsetWidth > nScrollBody.offsetWidth) ?
-				 	o.oScroll.iBarWidth : 0;
-				if ( o.nTable.offsetHeight < nScrollBody.offsetHeight )
-				{
-					nScrollBody.style.height = _fnStringToCss( o.nTable.offsetHeight+iExtra );
-				}
-			}
-			
-			/* Finally set the width's of the header and footer tables */
-			var iOuterWidth = $(o.nTable).outerWidth();
-			nScrollHeadTable.style.width = _fnStringToCss( iOuterWidth );
-			nScrollHeadInner.style.width = _fnStringToCss( iOuterWidth );
-		
-			// Figure out if there are scrollbar present - if so then we need a the header and footer to
-			// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
-			var bScrolling = $(o.nTable).height() > nScrollBody.clientHeight || $(nScrollBody).css('overflow-y') == "scroll";
-			nScrollHeadInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
-			
-			if ( o.nTFoot !== null )
-			{
-				nScrollFootTable.style.width = _fnStringToCss( iOuterWidth );
-				nScrollFootInner.style.width = _fnStringToCss( iOuterWidth );
-				nScrollFootInner.style.paddingRight = bScrolling ? o.oScroll.iBarWidth+"px" : "0px";
-			}
-		
-			/* Adjust the position of the header in case we loose the y-scrollbar */
-			$(nScrollBody).scroll();
-			
-			/* If sorting or filtering has occurred, jump the scrolling back to the top */
-			if ( o.bSorted || o.bFiltered )
-			{
-				nScrollBody.scrollTop = 0;
-			}
-		}
-		
-		
-		/**
-		 * Apply a given function to the display child nodes of an element array (typically
-		 * TD children of TR rows
-		 *  @param {function} fn Method to apply to the objects
-		 *  @param array {nodes} an1 List of elements to look through for display children
-		 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnApplyToChildren( fn, an1, an2 )
-		{
-			var index=0, i=0, iLen=an1.length;
-			var nNode1, nNode2;
-		
-			while ( i < iLen )
-			{
-				nNode1 = an1[i].firstChild;
-				nNode2 = an2 ? an2[i].firstChild : null;
-				while ( nNode1 )
-				{
-					if ( nNode1.nodeType === 1 )
-					{
-						if ( an2 )
-						{
-							fn( nNode1, nNode2, index );
-						}
-						else
-						{
-							fn( nNode1, index );
-						}
-						index++;
-					}
-					nNode1 = nNode1.nextSibling;
-					nNode2 = an2 ? nNode2.nextSibling : null;
-				}
-				i++;
-			}
-		}
-		
-		/**
-		 * Convert a CSS unit width to pixels (e.g. 2em)
-		 *  @param {string} sWidth width to be converted
-		 *  @param {node} nParent parent to get the with for (required for relative widths) - optional
-		 *  @returns {int} iWidth width in pixels
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnConvertToWidth ( sWidth, nParent )
-		{
-			if ( !sWidth || sWidth === null || sWidth === '' )
-			{
-				return 0;
-			}
-			
-			if ( !nParent )
-			{
-				nParent = document.body;
-			}
-			
-			var iWidth;
-			var nTmp = document.createElement( "div" );
-			nTmp.style.width = _fnStringToCss( sWidth );
-			
-			nParent.appendChild( nTmp );
-			iWidth = nTmp.offsetWidth;
-			nParent.removeChild( nTmp );
-			
-			return ( iWidth );
-		}
-		
-		
-		/**
-		 * Calculate the width of columns for the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnCalculateColumnWidths ( oSettings )
-		{
-			var iTableWidth = oSettings.nTable.offsetWidth;
-			var iUserInputs = 0;
-			var iTmpWidth;
-			var iVisibleColumns = 0;
-			var iColums = oSettings.aoColumns.length;
-			var i, iIndex, iCorrector, iWidth;
-			var oHeaders = $('th', oSettings.nTHead);
-			var widthAttr = oSettings.nTable.getAttribute('width');
-			var nWrapper = oSettings.nTable.parentNode;
-			
-			/* Convert any user input sizes into pixel sizes */
-			for ( i=0 ; i<iColums ; i++ )
-			{
-				if ( oSettings.aoColumns[i].bVisible )
-				{
-					iVisibleColumns++;
-					
-					if ( oSettings.aoColumns[i].sWidth !== null )
-					{
-						iTmpWidth = _fnConvertToWidth( oSettings.aoColumns[i].sWidthOrig, 
-							nWrapper );
-						if ( iTmpWidth !== null )
-						{
-							oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
-						}
-							
-						iUserInputs++;
-					}
-				}
-			}
-			
-			/* If the number of columns in the DOM equals the number that we have to process in 
-			 * DataTables, then we can use the offsets that are created by the web-browser. No custom 
-			 * sizes can be set in order for this to happen, nor scrolling used
-			 */
-			if ( iColums == oHeaders.length && iUserInputs === 0 && iVisibleColumns == iColums &&
-				oSettings.oScroll.sX === "" && oSettings.oScroll.sY === "" )
-			{
-				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-				{
-					iTmpWidth = $(oHeaders[i]).width();
-					if ( iTmpWidth !== null )
-					{
-						oSettings.aoColumns[i].sWidth = _fnStringToCss( iTmpWidth );
-					}
-				}
-			}
-			else
-			{
-				/* Otherwise we are going to have to do some calculations to get the width of each column.
-				 * Construct a 1 row table with the widest node in the data, and any user defined widths,
-				 * then insert it into the DOM and allow the browser to do all the hard work of
-				 * calculating table widths.
-				 */
-				var
-					nCalcTmp = oSettings.nTable.cloneNode( false ),
-					nTheadClone = oSettings.nTHead.cloneNode(true),
-					nBody = document.createElement( 'tbody' ),
-					nTr = document.createElement( 'tr' ),
-					nDivSizing;
-				
-				nCalcTmp.removeAttribute( "id" );
-				nCalcTmp.appendChild( nTheadClone );
-				if ( oSettings.nTFoot !== null )
-				{
-					nCalcTmp.appendChild( oSettings.nTFoot.cloneNode(true) );
-					_fnApplyToChildren( function(n) {
-						n.style.width = "";
-					}, nCalcTmp.getElementsByTagName('tr') );
-				}
-				
-				nCalcTmp.appendChild( nBody );
-				nBody.appendChild( nTr );
-				
-				/* Remove any sizing that was previously applied by the styles */
-				var jqColSizing = $('thead th', nCalcTmp);
-				if ( jqColSizing.length === 0 )
-				{
-					jqColSizing = $('tbody tr:eq(0)>td', nCalcTmp);
-				}
-		
-				/* Apply custom sizing to the cloned header */
-				var nThs = _fnGetUniqueThs( oSettings, nTheadClone );
-				iCorrector = 0;
-				for ( i=0 ; i<iColums ; i++ )
-				{
-					var oColumn = oSettings.aoColumns[i];
-					if ( oColumn.bVisible && oColumn.sWidthOrig !== null && oColumn.sWidthOrig !== "" )
-					{
-						nThs[i-iCorrector].style.width = _fnStringToCss( oColumn.sWidthOrig );
-					}
-					else if ( oColumn.bVisible )
-					{
-						nThs[i-iCorrector].style.width = "";
-					}
-					else
-					{
-						iCorrector++;
-					}
-				}
-		
-				/* Find the biggest td for each column and put it into the table */
-				for ( i=0 ; i<iColums ; i++ )
-				{
-					if ( oSettings.aoColumns[i].bVisible )
-					{
-						var nTd = _fnGetWidestNode( oSettings, i );
-						if ( nTd !== null )
-						{
-							nTd = nTd.cloneNode(true);
-							if ( oSettings.aoColumns[i].sContentPadding !== "" )
-							{
-								nTd.innerHTML += oSettings.aoColumns[i].sContentPadding;
-							}
-							nTr.appendChild( nTd );
-						}
-					}
-				}
-				
-				/* Build the table and 'display' it */
-				nWrapper.appendChild( nCalcTmp );
-				
-				/* When scrolling (X or Y) we want to set the width of the table as appropriate. However,
-				 * when not scrolling leave the table width as it is. This results in slightly different,
-				 * but I think correct behaviour
-				 */
-				if ( oSettings.oScroll.sX !== "" && oSettings.oScroll.sXInner !== "" )
-				{
-					nCalcTmp.style.width = _fnStringToCss(oSettings.oScroll.sXInner);
-				}
-				else if ( oSettings.oScroll.sX !== "" )
-				{
-					nCalcTmp.style.width = "";
-					if ( $(nCalcTmp).width() < nWrapper.offsetWidth )
-					{
-						nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
-					}
-				}
-				else if ( oSettings.oScroll.sY !== "" )
-				{
-					nCalcTmp.style.width = _fnStringToCss( nWrapper.offsetWidth );
-				}
-				else if ( widthAttr )
-				{
-					nCalcTmp.style.width = _fnStringToCss( widthAttr );
-				}
-				nCalcTmp.style.visibility = "hidden";
-				
-				/* Scrolling considerations */
-				_fnScrollingWidthAdjust( oSettings, nCalcTmp );
-				
-				/* Read the width's calculated by the browser and store them for use by the caller. We
-				 * first of all try to use the elements in the body, but it is possible that there are
-				 * no elements there, under which circumstances we use the header elements
-				 */
-				var oNodes = $("tbody tr:eq(0)", nCalcTmp).children();
-				if ( oNodes.length === 0 )
-				{
-					oNodes = _fnGetUniqueThs( oSettings, $('thead', nCalcTmp)[0] );
-				}
-		
-				/* Browsers need a bit of a hand when a width is assigned to any columns when 
-				 * x-scrolling as they tend to collapse the table to the min-width, even if
-				 * we sent the column widths. So we need to keep track of what the table width
-				 * should be by summing the user given values, and the automatic values
-				 */
-				if ( oSettings.oScroll.sX !== "" )
-				{
-					var iTotal = 0;
-					iCorrector = 0;
-					for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-					{
-						if ( oSettings.aoColumns[i].bVisible )
-						{
-							if ( oSettings.aoColumns[i].sWidthOrig === null )
-							{
-								iTotal += $(oNodes[iCorrector]).outerWidth();
-							}
-							else
-							{
-								iTotal += parseInt(oSettings.aoColumns[i].sWidth.replace('px',''), 10) +
-									($(oNodes[iCorrector]).outerWidth() - $(oNodes[iCorrector]).width());
-							}
-							iCorrector++;
-						}
-					}
-					
-					nCalcTmp.style.width = _fnStringToCss( iTotal );
-					oSettings.nTable.style.width = _fnStringToCss( iTotal );
-				}
-		
-				iCorrector = 0;
-				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-				{
-					if ( oSettings.aoColumns[i].bVisible )
-					{
-						iWidth = $(oNodes[iCorrector]).width();
-						if ( iWidth !== null && iWidth > 0 )
-						{
-							oSettings.aoColumns[i].sWidth = _fnStringToCss( iWidth );
-						}
-						iCorrector++;
-					}
-				}
-		
-				var cssWidth = $(nCalcTmp).css('width');
-				oSettings.nTable.style.width = (cssWidth.indexOf('%') !== -1) ?
-				    cssWidth : _fnStringToCss( $(nCalcTmp).outerWidth() );
-				nCalcTmp.parentNode.removeChild( nCalcTmp );
-			}
-		
-			if ( widthAttr )
-			{
-				oSettings.nTable.style.width = _fnStringToCss( widthAttr );
-			}
-		}
-		
-		
-		/**
-		 * Adjust a table's width to take account of scrolling
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {node} n table node
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnScrollingWidthAdjust ( oSettings, n )
-		{
-			if ( oSettings.oScroll.sX === "" && oSettings.oScroll.sY !== "" )
-			{
-				/* When y-scrolling only, we want to remove the width of the scroll bar so the table
-				 * + scroll bar will fit into the area avaialble.
-				 */
-				var iOrigWidth = $(n).width();
-				n.style.width = _fnStringToCss( $(n).outerWidth()-oSettings.oScroll.iBarWidth );
-			}
-			else if ( oSettings.oScroll.sX !== "" )
-			{
-				/* When x-scrolling both ways, fix the table at it's current size, without adjusting */
-				n.style.width = _fnStringToCss( $(n).outerWidth() );
-			}
-		}
-		
-		
-		/**
-		 * Get the widest node
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iCol column of interest
-		 *  @returns {node} widest table node
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetWidestNode( oSettings, iCol )
-		{
-			var iMaxIndex = _fnGetMaxLenString( oSettings, iCol );
-			if ( iMaxIndex < 0 )
-			{
-				return null;
-			}
-		
-			if ( oSettings.aoData[iMaxIndex].nTr === null )
-			{
-				var n = document.createElement('td');
-				n.innerHTML = _fnGetCellData( oSettings, iMaxIndex, iCol, '' );
-				return n;
-			}
-			return _fnGetTdNodes(oSettings, iMaxIndex)[iCol];
-		}
-		
-		
-		/**
-		 * Get the maximum strlen for each data column
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iCol column of interest
-		 *  @returns {string} max string length for each column
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetMaxLenString( oSettings, iCol )
-		{
-			var iMax = -1;
-			var iMaxIndex = -1;
-			
-			for ( var i=0 ; i<oSettings.aoData.length ; i++ )
-			{
-				var s = _fnGetCellData( oSettings, i, iCol, 'display' )+"";
-				s = s.replace( /<.*?>/g, "" );
-				if ( s.length > iMax )
-				{
-					iMax = s.length;
-					iMaxIndex = i;
-				}
-			}
-			
-			return iMaxIndex;
-		}
-		
-		
-		/**
-		 * Append a CSS unit (only if required) to a string
-		 *  @param {array} aArray1 first array
-		 *  @param {array} aArray2 second array
-		 *  @returns {int} 0 if match, 1 if length is different, 2 if no match
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnStringToCss( s )
-		{
-			if ( s === null )
-			{
-				return "0px";
-			}
-			
-			if ( typeof s == 'number' )
-			{
-				if ( s < 0 )
-				{
-					return "0px";
-				}
-				return s+"px";
-			}
-			
-			/* Check if the last character is not 0-9 */
-			var c = s.charCodeAt( s.length-1 );
-			if (c < 0x30 || c > 0x39)
-			{
-				return s;
-			}
-			return s+"px";
-		}
-		
-		
-		/**
-		 * Get the width of a scroll bar in this browser being used
-		 *  @returns {int} width in pixels
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnScrollBarWidth ()
-		{  
-			var inner = document.createElement('p');
-			var style = inner.style;
-			style.width = "100%";
-			style.height = "200px";
-			style.padding = "0px";
-			
-			var outer = document.createElement('div');
-			style = outer.style;
-			style.position = "absolute";
-			style.top = "0px";
-			style.left = "0px";
-			style.visibility = "hidden";
-			style.width = "200px";
-			style.height = "150px";
-			style.padding = "0px";
-			style.overflow = "hidden";
-			outer.appendChild(inner);
-			
-			document.body.appendChild(outer);
-			var w1 = inner.offsetWidth;
-			outer.style.overflow = 'scroll';
-			var w2 = inner.offsetWidth;
-			if ( w1 == w2 )
-			{
-				w2 = outer.clientWidth;
-			}
-			
-			document.body.removeChild(outer);
-			return (w1 - w2);  
-		}
-		
-		/**
-		 * Change the order of the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {bool} bApplyClasses optional - should we apply classes or not
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSort ( oSettings, bApplyClasses )
-		{
-			var
-				i, iLen, j, jLen, k, kLen,
-				sDataType, nTh,
-				aaSort = [],
-			 	aiOrig = [],
-				oSort = DataTable.ext.oSort,
-				aoData = oSettings.aoData,
-				aoColumns = oSettings.aoColumns,
-				oAria = oSettings.oLanguage.oAria;
-			
-			/* No sorting required if server-side or no sorting array */
-			if ( !oSettings.oFeatures.bServerSide && 
-				(oSettings.aaSorting.length !== 0 || oSettings.aaSortingFixed !== null) )
-			{
-				aaSort = ( oSettings.aaSortingFixed !== null ) ?
-					oSettings.aaSortingFixed.concat( oSettings.aaSorting ) :
-					oSettings.aaSorting.slice();
-				
-				/* If there is a sorting data type, and a function belonging to it, then we need to
-				 * get the data from the developer's function and apply it for this column
-				 */
-				for ( i=0 ; i<aaSort.length ; i++ )
-				{
-					var iColumn = aaSort[i][0];
-					var iVisColumn = _fnColumnIndexToVisible( oSettings, iColumn );
-					sDataType = oSettings.aoColumns[ iColumn ].sSortDataType;
-					if ( DataTable.ext.afnSortData[sDataType] )
-					{
-						var aData = DataTable.ext.afnSortData[sDataType].call( 
-							oSettings.oInstance, oSettings, iColumn, iVisColumn
-						);
-						if ( aData.length === aoData.length )
-						{
-							for ( j=0, jLen=aoData.length ; j<jLen ; j++ )
-							{
-								_fnSetCellData( oSettings, j, iColumn, aData[j] );
-							}
-						}
-						else
-						{
-							_fnLog( oSettings, 0, "Returned data sort array (col "+iColumn+") is the wrong length" );
-						}
-					}
-				}
-				
-				/* Create a value - key array of the current row positions such that we can use their
-				 * current position during the sort, if values match, in order to perform stable sorting
-				 */
-				for ( i=0, iLen=oSettings.aiDisplayMaster.length ; i<iLen ; i++ )
-				{
-					aiOrig[ oSettings.aiDisplayMaster[i] ] = i;
-				}
-		
-				/* Build an internal data array which is specific to the sort, so we can get and prep
-				 * the data to be sorted only once, rather than needing to do it every time the sorting
-				 * function runs. This make the sorting function a very simple comparison
-				 */
-				var iSortLen = aaSort.length;
-				var fnSortFormat, aDataSort;
-				for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
-				{
-					for ( j=0 ; j<iSortLen ; j++ )
-					{
-						aDataSort = aoColumns[ aaSort[j][0] ].aDataSort;
-		
-						for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
-						{
-							sDataType = aoColumns[ aDataSort[k] ].sType;
-							fnSortFormat = oSort[ (sDataType ? sDataType : 'string')+"-pre" ];
-							
-							aoData[i]._aSortData[ aDataSort[k] ] = fnSortFormat ?
-								fnSortFormat( _fnGetCellData( oSettings, i, aDataSort[k], 'sort' ) ) :
-								_fnGetCellData( oSettings, i, aDataSort[k], 'sort' );
-						}
-					}
-				}
-				
-				/* Do the sort - here we want multi-column sorting based on a given data source (column)
-				 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
-				 * follow on it's own, but this is what we want (example two column sorting):
-				 *  fnLocalSorting = function(a,b){
-				 *  	var iTest;
-				 *  	iTest = oSort['string-asc']('data11', 'data12');
-				 *  	if (iTest !== 0)
-				 *  		return iTest;
-				 *    iTest = oSort['numeric-desc']('data21', 'data22');
-				 *    if (iTest !== 0)
-				 *  		return iTest;
-				 *  	return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
-				 *  }
-				 * Basically we have a test for each sorting column, if the data in that column is equal,
-				 * test the next column. If all columns match, then we use a numeric sort on the row 
-				 * positions in the original data array to provide a stable sort.
-				 */
-				oSettings.aiDisplayMaster.sort( function ( a, b ) {
-					var k, l, lLen, iTest, aDataSort, sDataType;
-					for ( k=0 ; k<iSortLen ; k++ )
-					{
-						aDataSort = aoColumns[ aaSort[k][0] ].aDataSort;
-		
-						for ( l=0, lLen=aDataSort.length ; l<lLen ; l++ )
-						{
-							sDataType = aoColumns[ aDataSort[l] ].sType;
-							
-							iTest = oSort[ (sDataType ? sDataType : 'string')+"-"+aaSort[k][1] ](
-								aoData[a]._aSortData[ aDataSort[l] ],
-								aoData[b]._aSortData[ aDataSort[l] ]
-							);
-						
-							if ( iTest !== 0 )
-							{
-								return iTest;
-							}
-						}
-					}
-					
-					return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
-				} );
-			}
-			
-			/* Alter the sorting classes to take account of the changes */
-			if ( (bApplyClasses === undefined || bApplyClasses) && !oSettings.oFeatures.bDeferRender )
-			{
-				_fnSortingClasses( oSettings );
-			}
-		
-			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				var sTitle = aoColumns[i].sTitle.replace( /<.*?>/g, "" );
-				nTh = aoColumns[i].nTh;
-				nTh.removeAttribute('aria-sort');
-				nTh.removeAttribute('aria-label');
-				
-				/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
-				if ( aoColumns[i].bSortable )
-				{
-					if ( aaSort.length > 0 && aaSort[0][0] == i )
-					{
-						nTh.setAttribute('aria-sort', aaSort[0][1]=="asc" ? "ascending" : "descending" );
-						
-						var nextSort = (aoColumns[i].asSorting[ aaSort[0][2]+1 ]) ? 
-							aoColumns[i].asSorting[ aaSort[0][2]+1 ] : aoColumns[i].asSorting[0];
-						nTh.setAttribute('aria-label', sTitle+
-							(nextSort=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
-					}
-					else
-					{
-						nTh.setAttribute('aria-label', sTitle+
-							(aoColumns[i].asSorting[0]=="asc" ? oAria.sSortAscending : oAria.sSortDescending) );
-					}
-				}
-				else
-				{
-					nTh.setAttribute('aria-label', sTitle);
-				}
-			}
-			
-			/* Tell the draw function that we have sorted the data */
-			oSettings.bSorted = true;
-			$(oSettings.oInstance).trigger('sort', oSettings);
-			
-			/* Copy the master data into the draw array and re-draw */
-			if ( oSettings.oFeatures.bFilter )
-			{
-				/* _fnFilter() will redraw the table for us */
-				_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
-			}
-			else
-			{
-				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-				oSettings._iDisplayStart = 0; /* reset display back to page 0 */
-				_fnCalculateEnd( oSettings );
-				_fnDraw( oSettings );
-			}
-		}
-		
-		
-		/**
-		 * Attach a sort handler (click) to a node
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {node} nNode node to attach the handler to
-		 *  @param {int} iDataIndex column sorting index
-		 *  @param {function} [fnCallback] callback function
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSortAttachListener ( oSettings, nNode, iDataIndex, fnCallback )
-		{
-			_fnBindAction( nNode, {}, function (e) {
-				/* If the column is not sortable - don't to anything */
-				if ( oSettings.aoColumns[iDataIndex].bSortable === false )
-				{
-					return;
-				}
-				
-				/*
-				 * This is a little bit odd I admit... I declare a temporary function inside the scope of
-				 * _fnBuildHead and the click handler in order that the code presented here can be used 
-				 * twice - once for when bProcessing is enabled, and another time for when it is 
-				 * disabled, as we need to perform slightly different actions.
-				 *   Basically the issue here is that the Javascript engine in modern browsers don't 
-				 * appear to allow the rendering engine to update the display while it is still executing
-				 * it's thread (well - it does but only after long intervals). This means that the 
-				 * 'processing' display doesn't appear for a table sort. To break the js thread up a bit
-				 * I force an execution break by using setTimeout - but this breaks the expected 
-				 * thread continuation for the end-developer's point of view (their code would execute
-				 * too early), so we only do it when we absolutely have to.
-				 */
-				var fnInnerSorting = function () {
-					var iColumn, iNextSort;
-					
-					/* If the shift key is pressed then we are multiple column sorting */
-					if ( e.shiftKey )
-					{
-						/* Are we already doing some kind of sort on this column? */
-						var bFound = false;
-						for ( var i=0 ; i<oSettings.aaSorting.length ; i++ )
-						{
-							if ( oSettings.aaSorting[i][0] == iDataIndex )
-							{
-								bFound = true;
-								iColumn = oSettings.aaSorting[i][0];
-								iNextSort = oSettings.aaSorting[i][2]+1;
-								
-								if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )
-								{
-									/* Reached the end of the sorting options, remove from multi-col sort */
-									oSettings.aaSorting.splice( i, 1 );
-								}
-								else
-								{
-									/* Move onto next sorting direction */
-									oSettings.aaSorting[i][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
-									oSettings.aaSorting[i][2] = iNextSort;
-								}
-								break;
-							}
-						}
-						
-						/* No sort yet - add it in */
-						if ( bFound === false )
-						{
-							oSettings.aaSorting.push( [ iDataIndex, 
-								oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
-						}
-					}
-					else
-					{
-						/* If no shift key then single column sort */
-						if ( oSettings.aaSorting.length == 1 && oSettings.aaSorting[0][0] == iDataIndex )
-						{
-							iColumn = oSettings.aaSorting[0][0];
-							iNextSort = oSettings.aaSorting[0][2]+1;
-							if ( !oSettings.aoColumns[iColumn].asSorting[iNextSort] )
-							{
-								iNextSort = 0;
-							}
-							oSettings.aaSorting[0][1] = oSettings.aoColumns[iColumn].asSorting[iNextSort];
-							oSettings.aaSorting[0][2] = iNextSort;
-						}
-						else
-						{
-							oSettings.aaSorting.splice( 0, oSettings.aaSorting.length );
-							oSettings.aaSorting.push( [ iDataIndex, 
-								oSettings.aoColumns[iDataIndex].asSorting[0], 0 ] );
-						}
-					}
-					
-					/* Run the sort */
-					_fnSort( oSettings );
-				}; /* /fnInnerSorting */
-				
-				if ( !oSettings.oFeatures.bProcessing )
-				{
-					fnInnerSorting();
-				}
-				else
-				{
-					_fnProcessingDisplay( oSettings, true );
-					setTimeout( function() {
-						fnInnerSorting();
-						if ( !oSettings.oFeatures.bServerSide )
-						{
-							_fnProcessingDisplay( oSettings, false );
-						}
-					}, 0 );
-				}
-				
-				/* Call the user specified callback function - used for async user interaction */
-				if ( typeof fnCallback == 'function' )
-				{
-					fnCallback( oSettings );
-				}
-			} );
-		}
-		
-		
-		/**
-		 * Set the sorting classes on the header, Note: it is safe to call this function 
-		 * when bSort and bSortClasses are false
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSortingClasses( oSettings )
-		{
-			var i, iLen, j, jLen, iFound;
-			var aaSort, sClass;
-			var iColumns = oSettings.aoColumns.length;
-			var oClasses = oSettings.oClasses;
-			
-			for ( i=0 ; i<iColumns ; i++ )
-			{
-				if ( oSettings.aoColumns[i].bSortable )
-				{
-					$(oSettings.aoColumns[i].nTh).removeClass( oClasses.sSortAsc +" "+ oClasses.sSortDesc +
-						" "+ oSettings.aoColumns[i].sSortingClass );
-				}
-			}
-			
-			if ( oSettings.aaSortingFixed !== null )
-			{
-				aaSort = oSettings.aaSortingFixed.concat( oSettings.aaSorting );
-			}
-			else
-			{
-				aaSort = oSettings.aaSorting.slice();
-			}
-			
-			/* Apply the required classes to the header */
-			for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-			{
-				if ( oSettings.aoColumns[i].bSortable )
-				{
-					sClass = oSettings.aoColumns[i].sSortingClass;
-					iFound = -1;
-					for ( j=0 ; j<aaSort.length ; j++ )
-					{
-						if ( aaSort[j][0] == i )
-						{
-							sClass = ( aaSort[j][1] == "asc" ) ?
-								oClasses.sSortAsc : oClasses.sSortDesc;
-							iFound = j;
-							break;
-						}
-					}
-					$(oSettings.aoColumns[i].nTh).addClass( sClass );
-					
-					if ( oSettings.bJUI )
-					{
-						/* jQuery UI uses extra markup */
-						var jqSpan = $("span."+oClasses.sSortIcon,  oSettings.aoColumns[i].nTh);
-						jqSpan.removeClass(oClasses.sSortJUIAsc +" "+ oClasses.sSortJUIDesc +" "+ 
-							oClasses.sSortJUI +" "+ oClasses.sSortJUIAscAllowed +" "+ oClasses.sSortJUIDescAllowed );
-						
-						var sSpanClass;
-						if ( iFound == -1 )
-						{
-						 	sSpanClass = oSettings.aoColumns[i].sSortingClassJUI;
-						}
-						else if ( aaSort[iFound][1] == "asc" )
-						{
-							sSpanClass = oClasses.sSortJUIAsc;
-						}
-						else
-						{
-							sSpanClass = oClasses.sSortJUIDesc;
-						}
-						
-						jqSpan.addClass( sSpanClass );
-					}
-				}
-				else
-				{
-					/* No sorting on this column, so add the base class. This will have been assigned by
-					 * _fnAddColumn
-					 */
-					$(oSettings.aoColumns[i].nTh).addClass( oSettings.aoColumns[i].sSortingClass );
-				}
-			}
-			
-			/* 
-			 * Apply the required classes to the table body
-			 * Note that this is given as a feature switch since it can significantly slow down a sort
-			 * on large data sets (adding and removing of classes is always slow at the best of times..)
-			 * Further to this, note that this code is admittedly fairly ugly. It could be made a lot 
-			 * simpler using jQuery selectors and add/removeClass, but that is significantly slower
-			 * (on the order of 5 times slower) - hence the direct DOM manipulation here.
-			 * Note that for deferred drawing we do use jQuery - the reason being that taking the first
-			 * row found to see if the whole column needs processed can miss classes since the first
-			 * column might be new.
-			 */
-			sClass = oClasses.sSortColumn;
-			
-			if ( oSettings.oFeatures.bSort && oSettings.oFeatures.bSortClasses )
-			{
-				var nTds = _fnGetTdNodes( oSettings );
-				
-				/* Determine what the sorting class for each column should be */
-				var iClass, iTargetCol;
-				var asClasses = [];
-				for (i = 0; i < iColumns; i++)
-				{
-					asClasses.push("");
-				}
-				for (i = 0, iClass = 1; i < aaSort.length; i++)
-				{
-					iTargetCol = parseInt( aaSort[i][0], 10 );
-					asClasses[iTargetCol] = sClass + iClass;
-					
-					if ( iClass < 3 )
-					{
-						iClass++;
-					}
-				}
-				
-				/* Make changes to the classes for each cell as needed */
-				var reClass = new RegExp(sClass + "[123]");
-				var sTmpClass, sCurrentClass, sNewClass;
-				for ( i=0, iLen=nTds.length; i<iLen; i++ )
-				{
-					/* Determine which column we're looking at */
-					iTargetCol = i % iColumns;
-					
-					/* What is the full list of classes now */
-					sCurrentClass = nTds[i].className;
-					/* What sorting class should be applied? */
-					sNewClass = asClasses[iTargetCol];
-					/* What would the new full list be if we did a replacement? */
-					sTmpClass = sCurrentClass.replace(reClass, sNewClass);
-					
-					if ( sTmpClass != sCurrentClass )
-					{
-						/* We changed something */
-						nTds[i].className = $.trim( sTmpClass );
-					}
-					else if ( sNewClass.length > 0 && sCurrentClass.indexOf(sNewClass) == -1 )
-					{
-						/* We need to add a class */
-						nTds[i].className = sCurrentClass + " " + sNewClass;
-					}
-				}
-			}
-		}
-		
-		
-		
-		/**
-		 * Save the state of a table in a cookie such that the page can be reloaded
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSaveState ( oSettings )
-		{
-			if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
-			{
-				return;
-			}
-		
-			/* Store the interesting variables */
-			var i, iLen, bInfinite=oSettings.oScroll.bInfinite;
-			var oState = {
-				"iCreate":      new Date().getTime(),
-				"iStart":       (bInfinite ? 0 : oSettings._iDisplayStart),
-				"iEnd":         (bInfinite ? oSettings._iDisplayLength : oSettings._iDisplayEnd),
-				"iLength":      oSettings._iDisplayLength,
-				"aaSorting":    $.extend( true, [], oSettings.aaSorting ),
-				"oSearch":      $.extend( true, {}, oSettings.oPreviousSearch ),
-				"aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
-				"abVisCols":    []
-			};
-		
-			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-			{
-				oState.abVisCols.push( oSettings.aoColumns[i].bVisible );
-			}
-		
-			_fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] );
-			
-			oSettings.fnStateSave.call( oSettings.oInstance, oSettings, oState );
-		}
-		
-		
-		/**
-		 * Attempt to load a saved table state from a cookie
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {object} oInit DataTables init object so we can override settings
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnLoadState ( oSettings, oInit )
-		{
-			if ( !oSettings.oFeatures.bStateSave )
-			{
-				return;
-			}
-		
-			var oData = oSettings.fnStateLoad.call( oSettings.oInstance, oSettings );
-			if ( !oData )
-			{
-				return;
-			}
-			
-			/* Allow custom and plug-in manipulation functions to alter the saved data set and
-			 * cancelling of loading by returning false
-			 */
-			var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );
-			if ( $.inArray( false, abStateLoad ) !== -1 )
-			{
-				return;
-			}
-			
-			/* Store the saved state so it might be accessed at any time */
-			oSettings.oLoadedState = $.extend( true, {}, oData );
-			
-			/* Restore key features */
-			oSettings._iDisplayStart    = oData.iStart;
-			oSettings.iInitDisplayStart = oData.iStart;
-			oSettings._iDisplayEnd      = oData.iEnd;
-			oSettings._iDisplayLength   = oData.iLength;
-			oSettings.aaSorting         = oData.aaSorting.slice();
-			oSettings.saved_aaSorting   = oData.aaSorting.slice();
-			
-			/* Search filtering  */
-			$.extend( oSettings.oPreviousSearch, oData.oSearch );
-			$.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );
-			
-			/* Column visibility state
-			 * Pass back visibility settings to the init handler, but to do not here override
-			 * the init object that the user might have passed in
-			 */
-			oInit.saved_aoColumns = [];
-			for ( var i=0 ; i<oData.abVisCols.length ; i++ )
-			{
-				oInit.saved_aoColumns[i] = {};
-				oInit.saved_aoColumns[i].bVisible = oData.abVisCols[i];
-			}
-		
-			_fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );
-		}
-		
-		
-		/**
-		 * Create a new cookie with a value to store the state of a table
-		 *  @param {string} sName name of the cookie to create
-		 *  @param {string} sValue the value the cookie should take
-		 *  @param {int} iSecs duration of the cookie
-		 *  @param {string} sBaseName sName is made up of the base + file name - this is the base
-		 *  @param {function} fnCallback User definable function to modify the cookie
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnCreateCookie ( sName, sValue, iSecs, sBaseName, fnCallback )
-		{
-			var date = new Date();
-			date.setTime( date.getTime()+(iSecs*1000) );
-			
-			/* 
-			 * Shocking but true - it would appear IE has major issues with having the path not having
-			 * a trailing slash on it. We need the cookie to be available based on the path, so we
-			 * have to append the file name to the cookie name. Appalling. Thanks to vex for adding the
-			 * patch to use at least some of the path
-			 */
-			var aParts = window.location.pathname.split('/');
-			var sNameFile = sName + '_' + aParts.pop().replace(/[\/:]/g,"").toLowerCase();
-			var sFullCookie, oData;
-			
-			if ( fnCallback !== null )
-			{
-				oData = (typeof $.parseJSON === 'function') ? 
-					$.parseJSON( sValue ) : eval( '('+sValue+')' );
-				sFullCookie = fnCallback( sNameFile, oData, date.toGMTString(),
-					aParts.join('/')+"/" );
-			}
-			else
-			{
-				sFullCookie = sNameFile + "=" + encodeURIComponent(sValue) +
-					"; expires=" + date.toGMTString() +"; path=" + aParts.join('/')+"/";
-			}
-			
-			/* Are we going to go over the cookie limit of 4KiB? If so, try to delete a cookies
-			 * belonging to DataTables.
-			 */
-			var
-				aCookies =document.cookie.split(';'),
-				iNewCookieLen = sFullCookie.split(';')[0].length,
-				aOldCookies = [];
-			
-			if ( iNewCookieLen+document.cookie.length+10 > 4096 ) /* Magic 10 for padding */
-			{
-				for ( var i=0, iLen=aCookies.length ; i<iLen ; i++ )
-				{
-					if ( aCookies[i].indexOf( sBaseName ) != -1 )
-					{
-						/* It's a DataTables cookie, so eval it and check the time stamp */
-						var aSplitCookie = aCookies[i].split('=');
-						try {
-							oData = eval( '('+decodeURIComponent(aSplitCookie[1])+')' );
-		
-							if ( oData && oData.iCreate )
-							{
-								aOldCookies.push( {
-									"name": aSplitCookie[0],
-									"time": oData.iCreate
-								} );
-							}
-						}
-						catch( e ) {}
-					}
-				}
-		
-				// Make sure we delete the oldest ones first
-				aOldCookies.sort( function (a, b) {
-					return b.time - a.time;
-				} );
-		
-				// Eliminate as many old DataTables cookies as we need to
-				while ( iNewCookieLen + document.cookie.length + 10 > 4096 ) {
-					if ( aOldCookies.length === 0 ) {
-						// Deleted all DT cookies and still not enough space. Can't state save
-						return;
-					}
-					
-					var old = aOldCookies.pop();
-					document.cookie = old.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+
-						aParts.join('/') + "/";
-				}
-			}
-			
-			document.cookie = sFullCookie;
-		}
-		
-		
-		/**
-		 * Read an old cookie to get a cookie with an old table state
-		 *  @param {string} sName name of the cookie to read
-		 *  @returns {string} contents of the cookie - or null if no cookie with that name found
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnReadCookie ( sName )
-		{
-			var
-				aParts = window.location.pathname.split('/'),
-				sNameEQ = sName + '_' + aParts[aParts.length-1].replace(/[\/:]/g,"").toLowerCase() + '=',
-			 	sCookieContents = document.cookie.split(';');
-			
-			for( var i=0 ; i<sCookieContents.length ; i++ )
-			{
-				var c = sCookieContents[i];
-				
-				while (c.charAt(0)==' ')
-				{
-					c = c.substring(1,c.length);
-				}
-				
-				if (c.indexOf(sNameEQ) === 0)
-				{
-					return decodeURIComponent( c.substring(sNameEQ.length,c.length) );
-				}
-			}
-			return null;
-		}
-		
-		
-		/**
-		 * Return the settings object for a particular table
-		 *  @param {node} nTable table we are using as a dataTable
-		 *  @returns {object} Settings object - or null if not found
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnSettingsFromNode ( nTable )
-		{
-			for ( var i=0 ; i<DataTable.settings.length ; i++ )
-			{
-				if ( DataTable.settings[i].nTable === nTable )
-				{
-					return DataTable.settings[i];
-				}
-			}
-			
-			return null;
-		}
-		
-		
-		/**
-		 * Return an array with the TR nodes for the table
-		 *  @param {object} oSettings dataTables settings object
-		 *  @returns {array} TR array
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetTrNodes ( oSettings )
-		{
-			var aNodes = [];
-			var aoData = oSettings.aoData;
-			for ( var i=0, iLen=aoData.length ; i<iLen ; i++ )
-			{
-				if ( aoData[i].nTr !== null )
-				{
-					aNodes.push( aoData[i].nTr );
-				}
-			}
-			return aNodes;
-		}
-		
-		
-		/**
-		 * Return an flat array with all TD nodes for the table, or row
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} [iIndividualRow] aoData index to get the nodes for - optional 
-		 *    if not given then the return array will contain all nodes for the table
-		 *  @returns {array} TD array
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnGetTdNodes ( oSettings, iIndividualRow )
-		{
-			var anReturn = [];
-			var iCorrector;
-			var anTds, nTd;
-			var iRow, iRows=oSettings.aoData.length,
-				iColumn, iColumns, oData, sNodeName, iStart=0, iEnd=iRows;
-			
-			/* Allow the collection to be limited to just one row */
-			if ( iIndividualRow !== undefined )
-			{
-				iStart = iIndividualRow;
-				iEnd = iIndividualRow+1;
-			}
-		
-			for ( iRow=iStart ; iRow<iEnd ; iRow++ )
-			{
-				oData = oSettings.aoData[iRow];
-				if ( oData.nTr !== null )
-				{
-					/* get the TD child nodes - taking into account text etc nodes */
-					anTds = [];
-					nTd = oData.nTr.firstChild;
-					while ( nTd )
-					{
-						sNodeName = nTd.nodeName.toLowerCase();
-						if ( sNodeName == 'td' || sNodeName == 'th' )
-						{
-							anTds.push( nTd );
-						}
-						nTd = nTd.nextSibling;
-					}
-		
-					iCorrector = 0;
-					for ( iColumn=0, iColumns=oSettings.aoColumns.length ; iColumn<iColumns ; iColumn++ )
-					{
-						if ( oSettings.aoColumns[iColumn].bVisible )
-						{
-							anReturn.push( anTds[iColumn-iCorrector] );
-						}
-						else
-						{
-							anReturn.push( oData._anHidden[iColumn] );
-							iCorrector++;
-						}
-					}
-				}
-			}
-		
-			return anReturn;
-		}
-		
-		
-		/**
-		 * Log an error message
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {int} iLevel log error messages, or display them to the user
-		 *  @param {string} sMesg error message
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnLog( oSettings, iLevel, sMesg )
-		{
-			var sAlert = (oSettings===null) ?
-				"DataTables warning: "+sMesg :
-				"DataTables warning (table id = '"+oSettings.sTableId+"'): "+sMesg;
-			
-			if ( iLevel === 0 )
-			{
-				if ( DataTable.ext.sErrMode == 'alert' )
-				{
-					alert( sAlert );
-				}
-				else
-				{
-					throw new Error(sAlert);
-				}
-				return;
-			}
-			else if ( window.console && console.log )
-			{
-				console.log( sAlert );
-			}
-		}
-		
-		
-		/**
-		 * See if a property is defined on one object, if so assign it to the other object
-		 *  @param {object} oRet target object
-		 *  @param {object} oSrc source object
-		 *  @param {string} sName property
-		 *  @param {string} [sMappedName] name to map too - optional, sName used if not given
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnMap( oRet, oSrc, sName, sMappedName )
-		{
-			if ( sMappedName === undefined )
-			{
-				sMappedName = sName;
-			}
-			if ( oSrc[sName] !== undefined )
-			{
-				oRet[sMappedName] = oSrc[sName];
-			}
-		}
-		
-		
-		/**
-		 * Extend objects - very similar to jQuery.extend, but deep copy objects, and shallow
-		 * copy arrays. The reason we need to do this, is that we don't want to deep copy array
-		 * init values (such as aaSorting) since the dev wouldn't be able to override them, but
-		 * we do want to deep copy arrays.
-		 *  @param {object} oOut Object to extend
-		 *  @param {object} oExtender Object from which the properties will be applied to oOut
-		 *  @returns {object} oOut Reference, just for convenience - oOut === the return.
-		 *  @memberof DataTable#oApi
-		 *  @todo This doesn't take account of arrays inside the deep copied objects.
-		 */
-		function _fnExtend( oOut, oExtender )
-		{
-			var val;
-			
-			for ( var prop in oExtender )
-			{
-				if ( oExtender.hasOwnProperty(prop) )
-				{
-					val = oExtender[prop];
-		
-					if ( typeof oInit[prop] === 'object' && val !== null && $.isArray(val) === false )
-					{
-						$.extend( true, oOut[prop], val );
-					}
-					else
-					{
-						oOut[prop] = val;
-					}
-				}
-			}
-		
-			return oOut;
-		}
-		
-		
-		/**
-		 * Bind an event handers to allow a click or return key to activate the callback.
-		 * This is good for accessibility since a return on the keyboard will have the
-		 * same effect as a click, if the element has focus.
-		 *  @param {element} n Element to bind the action to
-		 *  @param {object} oData Data object to pass to the triggered function
-		 *  @param {function} fn Callback function for when the event is triggered
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnBindAction( n, oData, fn )
-		{
-			$(n)
-				.bind( 'click.DT', oData, function (e) {
-						n.blur(); // Remove focus outline for mouse users
-						fn(e);
-					} )
-				.bind( 'keypress.DT', oData, function (e){
-					if ( e.which === 13 ) {
-						fn(e);
-					} } )
-				.bind( 'selectstart.DT', function () {
-					/* Take the brutal approach to cancelling text selection */
-					return false;
-					} );
-		}
-		
-		
-		/**
-		 * Register a callback function. Easily allows a callback function to be added to
-		 * an array store of callback functions that can then all be called together.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
-		 *  @param {function} fn Function to be called back
-		 *  @param {string} sName Identifying name for the callback (i.e. a label)
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnCallbackReg( oSettings, sStore, fn, sName )
-		{
-			if ( fn )
-			{
-				oSettings[sStore].push( {
-					"fn": fn,
-					"sName": sName
-				} );
-			}
-		}
-		
-		
-		/**
-		 * Fire callback functions and trigger events. Note that the loop over the callback
-		 * array store is done backwards! Further note that you do not want to fire off triggers
-		 * in time sensitive applications (for example cell creation) as its slow.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
-		 *  @param {string} sTrigger Name of the jQuery custom event to trigger. If null no trigger
-		 *    is fired
-		 *  @param {array} aArgs Array of arguments to pass to the callback function / trigger
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnCallbackFire( oSettings, sStore, sTrigger, aArgs )
-		{
-			var aoStore = oSettings[sStore];
-			var aRet =[];
-		
-			for ( var i=aoStore.length-1 ; i>=0 ; i-- )
-			{
-				aRet.push( aoStore[i].fn.apply( oSettings.oInstance, aArgs ) );
-			}
-		
-			if ( sTrigger !== null )
-			{
-				$(oSettings.oInstance).trigger(sTrigger, aArgs);
-			}
-		
-			return aRet;
-		}
-		
-		
-		/**
-		 * JSON stringify. If JSON.stringify it provided by the browser, json2.js or any other
-		 * library, then we use that as it is fast, safe and accurate. If the function isn't 
-		 * available then we need to built it ourselves - the inspiration for this function comes
-		 * from Craig Buckler ( http://www.sitepoint.com/javascript-json-serialization/ ). It is
-		 * not perfect and absolutely should not be used as a replacement to json2.js - but it does
-		 * do what we need, without requiring a dependency for DataTables.
-		 *  @param {object} o JSON object to be converted
-		 *  @returns {string} JSON string
-		 *  @memberof DataTable#oApi
-		 */
-		var _fnJsonString = (window.JSON) ? JSON.stringify : function( o )
-		{
-			/* Not an object or array */
-			var sType = typeof o;
-			if (sType !== "object" || o === null)
-			{
-				// simple data type
-				if (sType === "string")
-				{
-					o = '"'+o+'"';
-				}
-				return o+"";
-			}
-		
-			/* If object or array, need to recurse over it */
-			var
-				sProp, mValue,
-				json = [],
-				bArr = $.isArray(o);
-			
-			for (sProp in o)
-			{
-				mValue = o[sProp];
-				sType = typeof mValue;
-		
-				if (sType === "string")
-				{
-					mValue = '"'+mValue+'"';
-				}
-				else if (sType === "object" && mValue !== null)
-				{
-					mValue = _fnJsonString(mValue);
-				}
-		
-				json.push((bArr ? "" : '"'+sProp+'":') + mValue);
-			}
-		
-			return (bArr ? "[" : "{") + json + (bArr ? "]" : "}");
-		};
-		
-		
-		/**
-		 * From some browsers (specifically IE6/7) we need special handling to work around browser
-		 * bugs - this function is used to detect when these workarounds are needed.
-		 *  @param {object} oSettings dataTables settings object
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnBrowserDetect( oSettings )
-		{
-			/* IE6/7 will oversize a width 100% element inside a scrolling element, to include the
-			 * width of the scrollbar, while other browsers ensure the inner element is contained
-			 * without forcing scrolling
-			 */
-			var n = $(
-				'<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden">'+
-					'<div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;">'+
-						'<div id="DT_BrowserTest" style="width:100%; height:10px;"></div>'+
-					'</div>'+
-				'</div>')[0];
-		
-			document.body.appendChild( n );
-			oSettings.oBrowser.bScrollOversize = $('#DT_BrowserTest', n)[0].offsetWidth === 100 ? true : false;
-			document.body.removeChild( n );
-		}
-		
-
-		/**
-		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
-		 * return the resulting jQuery object.
-		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
-		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
-		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
-		 *    criterion ("applied") or all TR elements (i.e. no filter).
-		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
-		 *    Can be either 'current', whereby the current sorting of the table is used, or
-		 *    'original' whereby the original order the data was read into the table is used.
-		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
-		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be 
-		 *    'current' and filter is 'applied', regardless of what they might be given as.
-		 *  @returns {object} jQuery object, filtered by the given selector.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *
-		 *      // Highlight every second row
-		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
-		 *    } );
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *
-		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
-		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
-		 *      oTable.fnFilter('Webkit');
-		 *      oTable.$('tr', {"filter": "applied"}).css('backgroundColor', 'blue');
-		 *      oTable.fnFilter('');
-		 *    } );
-		 */
-		this.$ = function ( sSelector, oOpts )
-		{
-			var i, iLen, a = [], tr;
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var aoData = oSettings.aoData;
-			var aiDisplay = oSettings.aiDisplay;
-			var aiDisplayMaster = oSettings.aiDisplayMaster;
-		
-			if ( !oOpts )
-			{
-				oOpts = {};
-			}
-		
-			oOpts = $.extend( {}, {
-				"filter": "none", // applied
-				"order": "current", // "original"
-				"page": "all" // current
-			}, oOpts );
-		
-			// Current page implies that order=current and fitler=applied, since it is fairly
-			// senseless otherwise
-			if ( oOpts.page == 'current' )
-			{
-				for ( i=oSettings._iDisplayStart, iLen=oSettings.fnDisplayEnd() ; i<iLen ; i++ )
-				{
-					tr = aoData[ aiDisplay[i] ].nTr;
-					if ( tr )
-					{
-						a.push( tr );
-					}
-				}
-			}
-			else if ( oOpts.order == "current" && oOpts.filter == "none" )
-			{
-				for ( i=0, iLen=aiDisplayMaster.length ; i<iLen ; i++ )
-				{
-					tr = aoData[ aiDisplayMaster[i] ].nTr;
-					if ( tr )
-					{
-						a.push( tr );
-					}
-				}
-			}
-			else if ( oOpts.order == "current" && oOpts.filter == "applied" )
-			{
-				for ( i=0, iLen=aiDisplay.length ; i<iLen ; i++ )
-				{
-					tr = aoData[ aiDisplay[i] ].nTr;
-					if ( tr )
-					{
-						a.push( tr );
-					}
-				}
-			}
-			else if ( oOpts.order == "original" && oOpts.filter == "none" )
-			{
-				for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
-				{
-					tr = aoData[ i ].nTr ;
-					if ( tr )
-					{
-						a.push( tr );
-					}
-				}
-			}
-			else if ( oOpts.order == "original" && oOpts.filter == "applied" )
-			{
-				for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
-				{
-					tr = aoData[ i ].nTr;
-					if ( $.inArray( i, aiDisplay ) !== -1 && tr )
-					{
-						a.push( tr );
-					}
-				}
-			}
-			else
-			{
-				_fnLog( oSettings, 1, "Unknown selection options" );
-			}
-		
-			/* We need to filter on the TR elements and also 'find' in their descendants
-			 * to make the selector act like it would in a full table - so we need
-			 * to build both results and then combine them together
-			 */
-			var jqA = $(a);
-			var jqTRs = jqA.filter( sSelector );
-			var jqDescendants = jqA.find( sSelector );
-		
-			return $( [].concat($.makeArray(jqTRs), $.makeArray(jqDescendants)) );
-		};
-		
-		
-		/**
-		 * Almost identical to $ in operation, but in this case returns the data for the matched
-		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
-		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
-		 * rows are found, the data returned is the original data array/object that was used to  
-		 * create the row (or a generated array if from a DOM source).
-		 *
-		 * This method is often useful in-combination with $ where both functions are given the
-		 * same parameters and the array indexes will match identically.
-		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
-		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
-		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
-		 *    criterion ("applied") or all elements (i.e. no filter).
-		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
-		 *    Can be either 'current', whereby the current sorting of the table is used, or
-		 *    'original' whereby the original order the data was read into the table is used.
-		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
-		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be 
-		 *    'current' and filter is 'applied', regardless of what they might be given as.
-		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
-		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null 
-		 *    entry in the array.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *
-		 *      // Get the data from the first row in the table
-		 *      var data = oTable._('tr:first');
-		 *
-		 *      // Do something useful with the data
-		 *      alert( "First cell is: "+data[0] );
-		 *    } );
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *
-		 *      // Filter to 'Webkit' and get all data for 
-		 *      oTable.fnFilter('Webkit');
-		 *      var data = oTable._('tr', {"filter": "applied"});
-		 *      
-		 *      // Do something with the data
-		 *      alert( data.length+" rows matched the filter" );
-		 *    } );
-		 */
-		this._ = function ( sSelector, oOpts )
-		{
-			var aOut = [];
-			var i, iLen, iIndex;
-			var aTrs = this.$( sSelector, oOpts );
-		
-			for ( i=0, iLen=aTrs.length ; i<iLen ; i++ )
-			{
-				aOut.push( this.fnGetData(aTrs[i]) );
-			}
-		
-			return aOut;
-		};
-		
-		
-		/**
-		 * Add a single new row or multiple rows of data to the table. Please note
-		 * that this is suitable for client-side processing only - if you are using 
-		 * server-side processing (i.e. "bServerSide": true), then to add data, you
-		 * must add it to the data source, i.e. the server-side, through an Ajax call.
-		 *  @param {array|object} mData The data to be added to the table. This can be:
-		 *    <ul>
-		 *      <li>1D array of data - add a single row with the data provided</li>
-		 *      <li>2D array of arrays - add multiple rows in a single call</li>
-		 *      <li>object - data object when using <i>mData</i></li>
-		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
-		 *    </ul>
-		 *  @param {bool} [bRedraw=true] redraw the table or not
-		 *  @returns {array} An array of integers, representing the list of indexes in 
-		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to 
-		 *    the table.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    // Global var for counter
-		 *    var giCount = 2;
-		 *    
-		 *    $(document).ready(function() {
-		 *      $('#example').dataTable();
-		 *    } );
-		 *    
-		 *    function fnClickAddRow() {
-		 *      $('#example').dataTable().fnAddData( [
-		 *        giCount+".1",
-		 *        giCount+".2",
-		 *        giCount+".3",
-		 *        giCount+".4" ]
-		 *      );
-		 *        
-		 *      giCount++;
-		 *    }
-		 */
-		this.fnAddData = function( mData, bRedraw )
-		{
-			if ( mData.length === 0 )
-			{
-				return [];
-			}
-			
-			var aiReturn = [];
-			var iTest;
-			
-			/* Find settings from table node */
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			
-			/* Check if we want to add multiple rows or not */
-			if ( typeof mData[0] === "object" && mData[0] !== null )
-			{
-				for ( var i=0 ; i<mData.length ; i++ )
-				{
-					iTest = _fnAddData( oSettings, mData[i] );
-					if ( iTest == -1 )
-					{
-						return aiReturn;
-					}
-					aiReturn.push( iTest );
-				}
-			}
-			else
-			{
-				iTest = _fnAddData( oSettings, mData );
-				if ( iTest == -1 )
-				{
-					return aiReturn;
-				}
-				aiReturn.push( iTest );
-			}
-			
-			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-			
-			if ( bRedraw === undefined || bRedraw )
-			{
-				_fnReDraw( oSettings );
-			}
-			return aiReturn;
-		};
-		
-		
-		/**
-		 * This function will make DataTables recalculate the column sizes, based on the data 
-		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or 
-		 * through the sWidth parameter). This can be useful when the width of the table's 
-		 * parent element changes (for example a window resize).
-		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "sScrollY": "200px",
-		 *        "bPaginate": false
-		 *      } );
-		 *      
-		 *      $(window).bind('resize', function () {
-		 *        oTable.fnAdjustColumnSizing();
-		 *      } );
-		 *    } );
-		 */
-		this.fnAdjustColumnSizing = function ( bRedraw )
-		{
-			var oSettings = _fnSettingsFromNode(this[DataTable.ext.iApiIndex]);
-			_fnAdjustColumnSizing( oSettings );
-			
-			if ( bRedraw === undefined || bRedraw )
-			{
-				this.fnDraw( false );
-			}
-			else if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
-			{
-				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
-				this.oApi._fnScrollDraw(oSettings);
-			}
-		};
-		
-		
-		/**
-		 * Quickly and simply clear a table
-		 *  @param {bool} [bRedraw=true] redraw the table or not
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
-		 *      oTable.fnClearTable();
-		 *    } );
-		 */
-		this.fnClearTable = function( bRedraw )
-		{
-			/* Find settings from table node */
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			_fnClearTable( oSettings );
-			
-			if ( bRedraw === undefined || bRedraw )
-			{
-				_fnDraw( oSettings );
-			}
-		};
-		
-		
-		/**
-		 * The exact opposite of 'opening' a row, this function will close any rows which 
-		 * are currently 'open'.
-		 *  @param {node} nTr the table row to 'close'
-		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable;
-		 *      
-		 *      // 'open' an information row when a row is clicked on
-		 *      $('#example tbody tr').click( function () {
-		 *        if ( oTable.fnIsOpen(this) ) {
-		 *          oTable.fnClose( this );
-		 *        } else {
-		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
-		 *        }
-		 *      } );
-		 *      
-		 *      oTable = $('#example').dataTable();
-		 *    } );
-		 */
-		this.fnClose = function( nTr )
-		{
-			/* Find settings from table node */
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			
-			for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
-			{
-				if ( oSettings.aoOpenRows[i].nParent == nTr )
-				{
-					var nTrParent = oSettings.aoOpenRows[i].nTr.parentNode;
-					if ( nTrParent )
-					{
-						/* Remove it if it is currently on display */
-						nTrParent.removeChild( oSettings.aoOpenRows[i].nTr );
-					}
-					oSettings.aoOpenRows.splice( i, 1 );
-					return 0;
-				}
-			}
-			return 1;
-		};
-		
-		
-		/**
-		 * Remove a row for the table
-		 *  @param {mixed} mTarget The index of the row from aoData to be deleted, or
-		 *    the TR element you want to delete
-		 *  @param {function|null} [fnCallBack] Callback function
-		 *  @param {bool} [bRedraw=true] Redraw the table or not
-		 *  @returns {array} The row that was deleted
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Immediately remove the first row
-		 *      oTable.fnDeleteRow( 0 );
-		 *    } );
-		 */
-		this.fnDeleteRow = function( mTarget, fnCallBack, bRedraw )
-		{
-			/* Find settings from table node */
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var i, iLen, iAODataIndex;
-			
-			iAODataIndex = (typeof mTarget === 'object') ? 
-				_fnNodeToDataIndex(oSettings, mTarget) : mTarget;
-			
-			/* Return the data array from this row */
-			var oData = oSettings.aoData.splice( iAODataIndex, 1 );
-		
-			/* Update the _DT_RowIndex parameter */
-			for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
-			{
-				if ( oSettings.aoData[i].nTr !== null )
-				{
-					oSettings.aoData[i].nTr._DT_RowIndex = i;
-				}
-			}
-			
-			/* Remove the target row from the search array */
-			var iDisplayIndex = $.inArray( iAODataIndex, oSettings.aiDisplay );
-			oSettings.asDataSearch.splice( iDisplayIndex, 1 );
-			
-			/* Delete from the display arrays */
-			_fnDeleteIndex( oSettings.aiDisplayMaster, iAODataIndex );
-			_fnDeleteIndex( oSettings.aiDisplay, iAODataIndex );
-			
-			/* If there is a user callback function - call it */
-			if ( typeof fnCallBack === "function" )
-			{
-				fnCallBack.call( this, oSettings, oData );
-			}
-			
-			/* Check for an 'overflow' they case for displaying the table */
-			if ( oSettings._iDisplayStart >= oSettings.fnRecordsDisplay() )
-			{
-				oSettings._iDisplayStart -= oSettings._iDisplayLength;
-				if ( oSettings._iDisplayStart < 0 )
-				{
-					oSettings._iDisplayStart = 0;
-				}
-			}
-			
-			if ( bRedraw === undefined || bRedraw )
-			{
-				_fnCalculateEnd( oSettings );
-				_fnDraw( oSettings );
-			}
-			
-			return oData;
-		};
-		
-		
-		/**
-		 * Restore the table to it's original state in the DOM by removing all of DataTables 
-		 * enhancements, alterations to the DOM structure of the table and event listeners.
-		 *  @param {boolean} [bRemove=false] Completely remove the table from the DOM
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
-		 *      var oTable = $('#example').dataTable();
-		 *      oTable.fnDestroy();
-		 *    } );
-		 */
-		this.fnDestroy = function ( bRemove )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var nOrig = oSettings.nTableWrapper.parentNode;
-			var nBody = oSettings.nTBody;
-			var i, iLen;
-		
-			bRemove = (bRemove===undefined) ? false : bRemove;
-			
-			/* Flag to note that the table is currently being destroyed - no action should be taken */
-			oSettings.bDestroying = true;
-			
-			/* Fire off the destroy callbacks for plug-ins etc */
-			_fnCallbackFire( oSettings, "aoDestroyCallback", "destroy", [oSettings] );
-		
-			/* If the table is not being removed, restore the hidden columns */
-			if ( !bRemove )
-			{
-				for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
-				{
-					if ( oSettings.aoColumns[i].bVisible === false )
-					{
-						this.fnSetColumnVis( i, true );
-					}
-				}
-			}
-			
-			/* Blitz all DT events */
-			$(oSettings.nTableWrapper).find('*').andSelf().unbind('.DT');
-			
-			/* If there is an 'empty' indicator row, remove it */
-			$('tbody>tr>td.'+oSettings.oClasses.sRowEmpty, oSettings.nTable).parent().remove();
-			
-			/* When scrolling we had to break the table up - restore it */
-			if ( oSettings.nTable != oSettings.nTHead.parentNode )
-			{
-				$(oSettings.nTable).children('thead').remove();
-				oSettings.nTable.appendChild( oSettings.nTHead );
-			}
-			
-			if ( oSettings.nTFoot && oSettings.nTable != oSettings.nTFoot.parentNode )
-			{
-				$(oSettings.nTable).children('tfoot').remove();
-				oSettings.nTable.appendChild( oSettings.nTFoot );
-			}
-			
-			/* Remove the DataTables generated nodes, events and classes */
-			oSettings.nTable.parentNode.removeChild( oSettings.nTable );
-			$(oSettings.nTableWrapper).remove();
-			
-			oSettings.aaSorting = [];
-			oSettings.aaSortingFixed = [];
-			_fnSortingClasses( oSettings );
-			
-			$(_fnGetTrNodes( oSettings )).removeClass( oSettings.asStripeClasses.join(' ') );
-			
-			$('th, td', oSettings.nTHead).removeClass( [
-				oSettings.oClasses.sSortable,
-				oSettings.oClasses.sSortableAsc,
-				oSettings.oClasses.sSortableDesc,
-				oSettings.oClasses.sSortableNone ].join(' ')
-			);
-			if ( oSettings.bJUI )
-			{
-				$('th span.'+oSettings.oClasses.sSortIcon
-					+ ', td span.'+oSettings.oClasses.sSortIcon, oSettings.nTHead).remove();
-		
-				$('th, td', oSettings.nTHead).each( function () {
-					var jqWrapper = $('div.'+oSettings.oClasses.sSortJUIWrapper, this);
-					var kids = jqWrapper.contents();
-					$(this).append( kids );
-					jqWrapper.remove();
-				} );
-			}
-			
-			/* Add the TR elements back into the table in their original order */
-			if ( !bRemove && oSettings.nTableReinsertBefore )
-			{
-				nOrig.insertBefore( oSettings.nTable, oSettings.nTableReinsertBefore );
-			}
-			else if ( !bRemove )
-			{
-				nOrig.appendChild( oSettings.nTable );
-			}
-		
-			for ( i=0, iLen=oSettings.aoData.length ; i<iLen ; i++ )
-			{
-				if ( oSettings.aoData[i].nTr !== null )
-				{
-					nBody.appendChild( oSettings.aoData[i].nTr );
-				}
-			}
-			
-			/* Restore the width of the original table */
-			if ( oSettings.oFeatures.bAutoWidth === true )
-			{
-			  oSettings.nTable.style.width = _fnStringToCss(oSettings.sDestroyWidth);
-			}
-			
-			/* If the were originally stripe classes - then we add them back here. Note
-			 * this is not fool proof (for example if not all rows had stripe classes - but
-			 * it's a good effort without getting carried away
-			 */
-			iLen = oSettings.asDestroyStripes.length;
-			if (iLen)
-			{
-				var anRows = $(nBody).children('tr');
-				for ( i=0 ; i<iLen ; i++ )
-				{
-					anRows.filter(':nth-child(' + iLen + 'n + ' + i + ')').addClass( oSettings.asDestroyStripes[i] );
-				}
-			}
-			
-			/* Remove the settings object from the settings array */
-			for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )
-			{
-				if ( DataTable.settings[i] == oSettings )
-				{
-					DataTable.settings.splice( i, 1 );
-				}
-			}
-			
-			/* End it all */
-			oSettings = null;
-			oInit = null;
-		};
-		
-		
-		/**
-		 * Redraw the table
-		 *  @param {bool} [bComplete=true] Re-filter and resort (if enabled) the table before the draw.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
-		 *      oTable.fnDraw();
-		 *    } );
-		 */
-		this.fnDraw = function( bComplete )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			if ( bComplete === false )
-			{
-				_fnCalculateEnd( oSettings );
-				_fnDraw( oSettings );
-			}
-			else
-			{
-				_fnReDraw( oSettings );
-			}
-		};
-		
-		
-		/**
-		 * Filter the input based on data
-		 *  @param {string} sInput String to filter the table on
-		 *  @param {int|null} [iColumn] Column to limit filtering to
-		 *  @param {bool} [bRegex=false] Treat as regular expression or not
-		 *  @param {bool} [bSmart=true] Perform smart filtering or not
-		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
-		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Sometime later - filter...
-		 *      oTable.fnFilter( 'test string' );
-		 *    } );
-		 */
-		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			
-			if ( !oSettings.oFeatures.bFilter )
-			{
-				return;
-			}
-			
-			if ( bRegex === undefined || bRegex === null )
-			{
-				bRegex = false;
-			}
-			
-			if ( bSmart === undefined || bSmart === null )
-			{
-				bSmart = true;
-			}
-			
-			if ( bShowGlobal === undefined || bShowGlobal === null )
-			{
-				bShowGlobal = true;
-			}
-			
-			if ( bCaseInsensitive === undefined || bCaseInsensitive === null )
-			{
-				bCaseInsensitive = true;
-			}
-			
-			if ( iColumn === undefined || iColumn === null )
-			{
-				/* Global filter */
-				_fnFilterComplete( oSettings, {
-					"sSearch":sInput+"",
-					"bRegex": bRegex,
-					"bSmart": bSmart,
-					"bCaseInsensitive": bCaseInsensitive
-				}, 1 );
-				
-				if ( bShowGlobal && oSettings.aanFeatures.f )
-				{
-					var n = oSettings.aanFeatures.f;
-					for ( var i=0, iLen=n.length ; i<iLen ; i++ )
-					{
-						// IE9 throws an 'unknown error' if document.activeElement is used
-						// inside an iframe or frame...
-						try {
-							if ( n[i]._DT_Input != document.activeElement )
-							{
-								$(n[i]._DT_Input).val( sInput );
-							}
-						}
-						catch ( e ) {
-							$(n[i]._DT_Input).val( sInput );
-						}
-					}
-				}
-			}
-			else
-			{
-				/* Single column filter */
-				$.extend( oSettings.aoPreSearchCols[ iColumn ], {
-					"sSearch": sInput+"",
-					"bRegex": bRegex,
-					"bSmart": bSmart,
-					"bCaseInsensitive": bCaseInsensitive
-				} );
-				_fnFilterComplete( oSettings, oSettings.oPreviousSearch, 1 );
-			}
-		};
-		
-		
-		/**
-		 * Get the data for the whole table, an individual row or an individual cell based on the 
-		 * provided parameters.
-		 *  @param {int|node} [mRow] A TR row node, TD/TH cell node or an integer. If given as
-		 *    a TR node then the data source for the whole row will be returned. If given as a
-		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
-		 *    cell returned. If given as an integer, then this is treated as the aoData internal
-		 *    data index for the row (see fnGetPosition) and the data for that row used.
-		 *  @param {int} [iCol] Optional column index that you want the data of.
-		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
-		 *    returned. If mRow is defined, just data for that row, and is iCol is
-		 *    defined, only data for the designated cell is returned.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    // Row data
-		 *    $(document).ready(function() {
-		 *      oTable = $('#example').dataTable();
-		 *
-		 *      oTable.$('tr').click( function () {
-		 *        var data = oTable.fnGetData( this );
-		 *        // ... do something with the array / object of data for the row
-		 *      } );
-		 *    } );
-		 *
-		 *  @example
-		 *    // Individual cell data
-		 *    $(document).ready(function() {
-		 *      oTable = $('#example').dataTable();
-		 *
-		 *      oTable.$('td').click( function () {
-		 *        var sData = oTable.fnGetData( this );
-		 *        alert( 'The cell clicked on had the value of '+sData );
-		 *      } );
-		 *    } );
-		 */
-		this.fnGetData = function( mRow, iCol )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			
-			if ( mRow !== undefined )
-			{
-				var iRow = mRow;
-				if ( typeof mRow === 'object' )
-				{
-					var sNode = mRow.nodeName.toLowerCase();
-					if (sNode === "tr" )
-					{
-						iRow = _fnNodeToDataIndex(oSettings, mRow);
-					}
-					else if ( sNode === "td" )
-					{
-						iRow = _fnNodeToDataIndex(oSettings, mRow.parentNode);
-						iCol = _fnNodeToColumnIndex( oSettings, iRow, mRow );
-					}
-				}
-		
-				if ( iCol !== undefined )
-				{
-					return _fnGetCellData( oSettings, iRow, iCol, '' );
-				}
-				return (oSettings.aoData[iRow]!==undefined) ?
-					oSettings.aoData[iRow]._aData : null;
-			}
-			return _fnGetDataMaster( oSettings );
-		};
-		
-		
-		/**
-		 * Get an array of the TR nodes that are used in the table's body. Note that you will 
-		 * typically want to use the '$' API method in preference to this as it is more 
-		 * flexible.
-		 *  @param {int} [iRow] Optional row index for the TR element you want
-		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
-		 *    in the table's body, or iRow is defined, just the TR element requested.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Get the nodes from the table
-		 *      var nNodes = oTable.fnGetNodes( );
-		 *    } );
-		 */
-		this.fnGetNodes = function( iRow )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			
-			if ( iRow !== undefined ) {
-				return (oSettings.aoData[iRow]!==undefined) ?
-					oSettings.aoData[iRow].nTr : null;
-			}
-			return _fnGetTrNodes( oSettings );
-		};
-		
-		
-		/**
-		 * Get the array indexes of a particular cell from it's DOM element
-		 * and column index including hidden columns
-		 *  @param {node} nNode this can either be a TR, TD or TH in the table's body
-		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
-		 *    if given as a cell, an array of [row index, column index (visible), 
-		 *    column index (all)] is given.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      $('#example tbody td').click( function () {
-		 *        // Get the position of the current data from the node
-		 *        var aPos = oTable.fnGetPosition( this );
-		 *        
-		 *        // Get the data array for this row
-		 *        var aData = oTable.fnGetData( aPos[0] );
-		 *        
-		 *        // Update the data array and return the value
-		 *        aData[ aPos[1] ] = 'clicked';
-		 *        this.innerHTML = 'clicked';
-		 *      } );
-		 *      
-		 *      // Init DataTables
-		 *      oTable = $('#example').dataTable();
-		 *    } );
-		 */
-		this.fnGetPosition = function( nNode )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var sNodeName = nNode.nodeName.toUpperCase();
-			
-			if ( sNodeName == "TR" )
-			{
-				return _fnNodeToDataIndex(oSettings, nNode);
-			}
-			else if ( sNodeName == "TD" || sNodeName == "TH" )
-			{
-				var iDataIndex = _fnNodeToDataIndex( oSettings, nNode.parentNode );
-				var iColumnIndex = _fnNodeToColumnIndex( oSettings, iDataIndex, nNode );
-				return [ iDataIndex, _fnColumnIndexToVisible(oSettings, iColumnIndex ), iColumnIndex ];
-			}
-			return null;
-		};
-		
-		
-		/**
-		 * Check to see if a row is 'open' or not.
-		 *  @param {node} nTr the table row to check
-		 *  @returns {boolean} true if the row is currently open, false otherwise
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable;
-		 *      
-		 *      // 'open' an information row when a row is clicked on
-		 *      $('#example tbody tr').click( function () {
-		 *        if ( oTable.fnIsOpen(this) ) {
-		 *          oTable.fnClose( this );
-		 *        } else {
-		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
-		 *        }
-		 *      } );
-		 *      
-		 *      oTable = $('#example').dataTable();
-		 *    } );
-		 */
-		this.fnIsOpen = function( nTr )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var aoOpenRows = oSettings.aoOpenRows;
-			
-			for ( var i=0 ; i<oSettings.aoOpenRows.length ; i++ )
-			{
-				if ( oSettings.aoOpenRows[i].nParent == nTr )
-				{
-					return true;
-				}
-			}
-			return false;
-		};
-		
-		
-		/**
-		 * This function will place a new row directly after a row which is currently 
-		 * on display on the page, with the HTML contents that is passed into the 
-		 * function. This can be used, for example, to ask for confirmation that a 
-		 * particular record should be deleted.
-		 *  @param {node} nTr The table row to 'open'
-		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
-		 *  @param {string} sClass Class to give the new TD cell
-		 *  @returns {node} The row opened. Note that if the table row passed in as the
-		 *    first parameter, is not found in the table, this method will silently
-		 *    return.
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable;
-		 *      
-		 *      // 'open' an information row when a row is clicked on
-		 *      $('#example tbody tr').click( function () {
-		 *        if ( oTable.fnIsOpen(this) ) {
-		 *          oTable.fnClose( this );
-		 *        } else {
-		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
-		 *        }
-		 *      } );
-		 *      
-		 *      oTable = $('#example').dataTable();
-		 *    } );
-		 */
-		this.fnOpen = function( nTr, mHtml, sClass )
-		{
-			/* Find settings from table node */
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-		
-			/* Check that the row given is in the table */
-			var nTableRows = _fnGetTrNodes( oSettings );
-			if ( $.inArray(nTr, nTableRows) === -1 )
-			{
-				return;
-			}
-			
-			/* the old open one if there is one */
-			this.fnClose( nTr );
-			
-			var nNewRow = document.createElement("tr");
-			var nNewCell = document.createElement("td");
-			nNewRow.appendChild( nNewCell );
-			nNewCell.className = sClass;
-			nNewCell.colSpan = _fnVisbleColumns( oSettings );
-		
-			if (typeof mHtml === "string")
-			{
-				nNewCell.innerHTML = mHtml;
-			}
-			else
-			{
-				$(nNewCell).html( mHtml );
-			}
-		
-			/* If the nTr isn't on the page at the moment - then we don't insert at the moment */
-			var nTrs = $('tr', oSettings.nTBody);
-			if ( $.inArray(nTr, nTrs) != -1  )
-			{
-				$(nNewRow).insertAfter(nTr);
-			}
-			
-			oSettings.aoOpenRows.push( {
-				"nTr": nNewRow,
-				"nParent": nTr
-			} );
-			
-			return nNewRow;
-		};
-		
-		
-		/**
-		 * Change the pagination - provides the internal logic for pagination in a simple API 
-		 * function. With this function you can have a DataTables table go to the next, 
-		 * previous, first or last pages.
-		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
-		 *    or page number to jump to (integer), note that page 0 is the first page.
-		 *  @param {bool} [bRedraw=true] Redraw the table or not
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      oTable.fnPageChange( 'next' );
-		 *    } );
-		 */
-		this.fnPageChange = function ( mAction, bRedraw )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			_fnPageChange( oSettings, mAction );
-			_fnCalculateEnd( oSettings );
-			
-			if ( bRedraw === undefined || bRedraw )
-			{
-				_fnDraw( oSettings );
-			}
-		};
-		
-		
-		/**
-		 * Show a particular column
-		 *  @param {int} iCol The column whose display should be changed
-		 *  @param {bool} bShow Show (true) or hide (false) the column
-		 *  @param {bool} [bRedraw=true] Redraw the table or not
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Hide the second column after initialisation
-		 *      oTable.fnSetColumnVis( 1, false );
-		 *    } );
-		 */
-		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var i, iLen;
-			var aoColumns = oSettings.aoColumns;
-			var aoData = oSettings.aoData;
-			var nTd, bAppend, iBefore;
-			
-			/* No point in doing anything if we are requesting what is already true */
-			if ( aoColumns[iCol].bVisible == bShow )
-			{
-				return;
-			}
-			
-			/* Show the column */
-			if ( bShow )
-			{
-				var iInsert = 0;
-				for ( i=0 ; i<iCol ; i++ )
-				{
-					if ( aoColumns[i].bVisible )
-					{
-						iInsert++;
-					}
-				}
-				
-				/* Need to decide if we should use appendChild or insertBefore */
-				bAppend = (iInsert >= _fnVisbleColumns( oSettings ));
-		
-				/* Which coloumn should we be inserting before? */
-				if ( !bAppend )
-				{
-					for ( i=iCol ; i<aoColumns.length ; i++ )
-					{
-						if ( aoColumns[i].bVisible )
-						{
-							iBefore = i;
-							break;
-						}
-					}
-				}
-		
-				for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
-				{
-					if ( aoData[i].nTr !== null )
-					{
-						if ( bAppend )
-						{
-							aoData[i].nTr.appendChild( 
-								aoData[i]._anHidden[iCol]
-							);
-						}
-						else
-						{
-							aoData[i].nTr.insertBefore(
-								aoData[i]._anHidden[iCol], 
-								_fnGetTdNodes( oSettings, i )[iBefore] );
-						}
-					}
-				}
-			}
-			else
-			{
-				/* Remove a column from display */
-				for ( i=0, iLen=aoData.length ; i<iLen ; i++ )
-				{
-					if ( aoData[i].nTr !== null )
-					{
-						nTd = _fnGetTdNodes( oSettings, i )[iCol];
-						aoData[i]._anHidden[iCol] = nTd;
-						nTd.parentNode.removeChild( nTd );
-					}
-				}
-			}
-		
-			/* Clear to set the visible flag */
-			aoColumns[iCol].bVisible = bShow;
-		
-			/* Redraw the header and footer based on the new column visibility */
-			_fnDrawHead( oSettings, oSettings.aoHeader );
-			if ( oSettings.nTFoot )
-			{
-				_fnDrawHead( oSettings, oSettings.aoFooter );
-			}
-			
-			/* If there are any 'open' rows, then we need to alter the colspan for this col change */
-			for ( i=0, iLen=oSettings.aoOpenRows.length ; i<iLen ; i++ )
-			{
-				oSettings.aoOpenRows[i].nTr.colSpan = _fnVisbleColumns( oSettings );
-			}
-			
-			/* Do a redraw incase anything depending on the table columns needs it 
-			 * (built-in: scrolling) 
-			 */
-			if ( bRedraw === undefined || bRedraw )
-			{
-				_fnAdjustColumnSizing( oSettings );
-				_fnDraw( oSettings );
-			}
-			
-			_fnSaveState( oSettings );
-		};
-		
-		
-		/**
-		 * Get the settings for a particular table for external manipulation
-		 *  @returns {object} DataTables settings object. See 
-		 *    {@link DataTable.models.oSettings}
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      var oSettings = oTable.fnSettings();
-		 *      
-		 *      // Show an example parameter from the settings
-		 *      alert( oSettings._iDisplayStart );
-		 *    } );
-		 */
-		this.fnSettings = function()
-		{
-			return _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-		};
-		
-		
-		/**
-		 * Sort the table by a particular column
-		 *  @param {int} iCol the data index to sort on. Note that this will not match the 
-		 *    'display index' if you have hidden data entries
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Sort immediately with columns 0 and 1
-		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
-		 *    } );
-		 */
-		this.fnSort = function( aaSort )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			oSettings.aaSorting = aaSort;
-			_fnSort( oSettings );
-		};
-		
-		
-		/**
-		 * Attach a sort listener to an element for a given column
-		 *  @param {node} nNode the element to attach the sort listener to
-		 *  @param {int} iColumn the column that a click on this node will sort on
-		 *  @param {function} [fnCallback] callback function when sort is run
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      
-		 *      // Sort on column 1, when 'sorter' is clicked on
-		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
-		 *    } );
-		 */
-		this.fnSortListener = function( nNode, iColumn, fnCallback )
-		{
-			_fnSortAttachListener( _fnSettingsFromNode( this[DataTable.ext.iApiIndex] ), nNode, iColumn,
-			 	fnCallback );
-		};
-		
-		
-		/**
-		 * Update a table cell or row - this method will accept either a single value to
-		 * update the cell with, an array of values with one element for each column or
-		 * an object in the same format as the original data source. The function is
-		 * self-referencing in order to make the multi column updates easier.
-		 *  @param {object|array|string} mData Data to update the cell/row with
-		 *  @param {node|int} mRow TR element you want to update or the aoData index
-		 *  @param {int} [iColumn] The column to update (not used of mData is an array or object)
-		 *  @param {bool} [bRedraw=true] Redraw the table or not
-		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
-		 *  @returns {int} 0 on success, 1 on error
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
-		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], 1, 0 ); // Row
-		 *    } );
-		 */
-		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
-		{
-			var oSettings = _fnSettingsFromNode( this[DataTable.ext.iApiIndex] );
-			var i, iLen, sDisplay;
-			var iRow = (typeof mRow === 'object') ? 
-				_fnNodeToDataIndex(oSettings, mRow) : mRow;
-			
-			if ( $.isArray(mData) && iColumn === undefined )
-			{
-				/* Array update - update the whole row */
-				oSettings.aoData[iRow]._aData = mData.slice();
-				
-				/* Flag to the function that we are recursing */
-				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-				{
-					this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );
-				}
-			}
-			else if ( $.isPlainObject(mData) && iColumn === undefined )
-			{
-				/* Object update - update the whole row - assume the developer gets the object right */
-				oSettings.aoData[iRow]._aData = $.extend( true, {}, mData );
-		
-				for ( i=0 ; i<oSettings.aoColumns.length ; i++ )
-				{
-					this.fnUpdate( _fnGetCellData( oSettings, iRow, i ), iRow, i, false, false );
-				}
-			}
-			else
-			{
-				/* Individual cell update */
-				_fnSetCellData( oSettings, iRow, iColumn, mData );
-				sDisplay = _fnGetCellData( oSettings, iRow, iColumn, 'display' );
-				
-				var oCol = oSettings.aoColumns[iColumn];
-				if ( oCol.fnRender !== null )
-				{
-					sDisplay = _fnRender( oSettings, iRow, iColumn );
-					if ( oCol.bUseRendered )
-					{
-						_fnSetCellData( oSettings, iRow, iColumn, sDisplay );
-					}
-				}
-				
-				if ( oSettings.aoData[iRow].nTr !== null )
-				{
-					/* Do the actual HTML update */
-					_fnGetTdNodes( oSettings, iRow )[iColumn].innerHTML = sDisplay;
-				}
-			}
-			
-			/* Modify the search index for this row (strictly this is likely not needed, since fnReDraw
-			 * will rebuild the search array - however, the redraw might be disabled by the user)
-			 */
-			var iDisplayIndex = $.inArray( iRow, oSettings.aiDisplay );
-			oSettings.asDataSearch[iDisplayIndex] = _fnBuildSearchRow(
-				oSettings, 
-				_fnGetRowData( oSettings, iRow, 'filter', _fnGetColumns( oSettings, 'bSearchable' ) )
-			);
-			
-			/* Perform pre-draw actions */
-			if ( bAction === undefined || bAction )
-			{
-				_fnAdjustColumnSizing( oSettings );
-			}
-			
-			/* Redraw the table */
-			if ( bRedraw === undefined || bRedraw )
-			{
-				_fnReDraw( oSettings );
-			}
-			return 0;
-		};
-		
-		
-		/**
-		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
-		 * to ensure compatibility.
-		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
-		 *    formats "X" and "X.Y" are also acceptable.
-		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
-		 *    version, or false if this version of DataTales is not suitable
-		 *  @method
-		 *  @dtopt API
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
-		 *    } );
-		 */
-		this.fnVersionCheck = DataTable.ext.fnVersionCheck;
-		
-		
-		/*
-		 * This is really a good bit rubbish this method of exposing the internal methods
-		 * publicly... - To be fixed in 2.0 using methods on the prototype
-		 */
-		
-		
-		/**
-		 * Create a wrapper function for exporting an internal functions to an external API.
-		 *  @param {string} sFunc API function name
-		 *  @returns {function} wrapped function
-		 *  @memberof DataTable#oApi
-		 */
-		function _fnExternApiFunc (sFunc)
-		{
-			return function() {
-				var aArgs = [_fnSettingsFromNode(this[DataTable.ext.iApiIndex])].concat( 
-					Array.prototype.slice.call(arguments) );
-				return DataTable.ext.oApi[sFunc].apply( this, aArgs );
-			};
-		}
-		
-		
-		/**
-		 * Reference to internal functions for use by plug-in developers. Note that these
-		 * methods are references to internal functions and are considered to be private.
-		 * If you use these methods, be aware that they are liable to change between versions
-		 * (check the upgrade notes).
-		 *  @namespace
-		 */
-		this.oApi = {
-			"_fnExternApiFunc": _fnExternApiFunc,
-			"_fnInitialise": _fnInitialise,
-			"_fnInitComplete": _fnInitComplete,
-			"_fnLanguageCompat": _fnLanguageCompat,
-			"_fnAddColumn": _fnAddColumn,
-			"_fnColumnOptions": _fnColumnOptions,
-			"_fnAddData": _fnAddData,
-			"_fnCreateTr": _fnCreateTr,
-			"_fnGatherData": _fnGatherData,
-			"_fnBuildHead": _fnBuildHead,
-			"_fnDrawHead": _fnDrawHead,
-			"_fnDraw": _fnDraw,
-			"_fnReDraw": _fnReDraw,
-			"_fnAjaxUpdate": _fnAjaxUpdate,
-			"_fnAjaxParameters": _fnAjaxParameters,
-			"_fnAjaxUpdateDraw": _fnAjaxUpdateDraw,
-			"_fnServerParams": _fnServerParams,
-			"_fnAddOptionsHtml": _fnAddOptionsHtml,
-			"_fnFeatureHtmlTable": _fnFeatureHtmlTable,
-			"_fnScrollDraw": _fnScrollDraw,
-			"_fnAdjustColumnSizing": _fnAdjustColumnSizing,
-			"_fnFeatureHtmlFilter": _fnFeatureHtmlFilter,
-			"_fnFilterComplete": _fnFilterComplete,
-			"_fnFilterCustom": _fnFilterCustom,
-			"_fnFilterColumn": _fnFilterColumn,
-			"_fnFilter": _fnFilter,
-			"_fnBuildSearchArray": _fnBuildSearchArray,
-			"_fnBuildSearchRow": _fnBuildSearchRow,
-			"_fnFilterCreateSearch": _fnFilterCreateSearch,
-			"_fnDataToSearch": _fnDataToSearch,
-			"_fnSort": _fnSort,
-			"_fnSortAttachListener": _fnSortAttachListener,
-			"_fnSortingClasses": _fnSortingClasses,
-			"_fnFeatureHtmlPaginate": _fnFeatureHtmlPaginate,
-			"_fnPageChange": _fnPageChange,
-			"_fnFeatureHtmlInfo": _fnFeatureHtmlInfo,
-			"_fnUpdateInfo": _fnUpdateInfo,
-			"_fnFeatureHtmlLength": _fnFeatureHtmlLength,
-			"_fnFeatureHtmlProcessing": _fnFeatureHtmlProcessing,
-			"_fnProcessingDisplay": _fnProcessingDisplay,
-			"_fnVisibleToColumnIndex": _fnVisibleToColumnIndex,
-			"_fnColumnIndexToVisible": _fnColumnIndexToVisible,
-			"_fnNodeToDataIndex": _fnNodeToDataIndex,
-			"_fnVisbleColumns": _fnVisbleColumns,
-			"_fnCalculateEnd": _fnCalculateEnd,
-			"_fnConvertToWidth": _fnConvertToWidth,
-			"_fnCalculateColumnWidths": _fnCalculateColumnWidths,
-			"_fnScrollingWidthAdjust": _fnScrollingWidthAdjust,
-			"_fnGetWidestNode": _fnGetWidestNode,
-			"_fnGetMaxLenString": _fnGetMaxLenString,
-			"_fnStringToCss": _fnStringToCss,
-			"_fnDetectType": _fnDetectType,
-			"_fnSettingsFromNode": _fnSettingsFromNode,
-			"_fnGetDataMaster": _fnGetDataMaster,
-			"_fnGetTrNodes": _fnGetTrNodes,
-			"_fnGetTdNodes": _fnGetTdNodes,
-			"_fnEscapeRegex": _fnEscapeRegex,
-			"_fnDeleteIndex": _fnDeleteIndex,
-			"_fnReOrderIndex": _fnReOrderIndex,
-			"_fnColumnOrdering": _fnColumnOrdering,
-			"_fnLog": _fnLog,
-			"_fnClearTable": _fnClearTable,
-			"_fnSaveState": _fnSaveState,
-			"_fnLoadState": _fnLoadState,
-			"_fnCreateCookie": _fnCreateCookie,
-			"_fnReadCookie": _fnReadCookie,
-			"_fnDetectHeader": _fnDetectHeader,
-			"_fnGetUniqueThs": _fnGetUniqueThs,
-			"_fnScrollBarWidth": _fnScrollBarWidth,
-			"_fnApplyToChildren": _fnApplyToChildren,
-			"_fnMap": _fnMap,
-			"_fnGetRowData": _fnGetRowData,
-			"_fnGetCellData": _fnGetCellData,
-			"_fnSetCellData": _fnSetCellData,
-			"_fnGetObjectDataFn": _fnGetObjectDataFn,
-			"_fnSetObjectDataFn": _fnSetObjectDataFn,
-			"_fnApplyColumnDefs": _fnApplyColumnDefs,
-			"_fnBindAction": _fnBindAction,
-			"_fnExtend": _fnExtend,
-			"_fnCallbackReg": _fnCallbackReg,
-			"_fnCallbackFire": _fnCallbackFire,
-			"_fnJsonString": _fnJsonString,
-			"_fnRender": _fnRender,
-			"_fnNodeToColumnIndex": _fnNodeToColumnIndex,
-			"_fnInfoMacros": _fnInfoMacros,
-			"_fnBrowserDetect": _fnBrowserDetect,
-			"_fnGetColumns": _fnGetColumns
-		};
-		
-		$.extend( DataTable.ext.oApi, this.oApi );
-		
-		for ( var sFunc in DataTable.ext.oApi )
-		{
-			if ( sFunc )
-			{
-				this[sFunc] = _fnExternApiFunc(sFunc);
-			}
-		}
-		
-		
-		var _that = this;
-		this.each(function() {
-			var i=0, iLen, j, jLen, k, kLen;
-			var sId = this.getAttribute( 'id' );
-			var bInitHandedOff = false;
-			var bUsePassedData = false;
-			
-			
-			/* Sanity check */
-			if ( this.nodeName.toLowerCase() != 'table' )
-			{
-				_fnLog( null, 0, "Attempted to initialise DataTables on a node which is not a "+
-					"table: "+this.nodeName );
-				return;
-			}
-			
-			/* Check to see if we are re-initialising a table */
-			for ( i=0, iLen=DataTable.settings.length ; i<iLen ; i++ )
-			{
-				/* Base check on table node */
-				if ( DataTable.settings[i].nTable == this )
-				{
-					if ( oInit === undefined || oInit.bRetrieve )
-					{
-						return DataTable.settings[i].oInstance;
-					}
-					else if ( oInit.bDestroy )
-					{
-						DataTable.settings[i].oInstance.fnDestroy();
-						break;
-					}
-					else
-					{
-						_fnLog( DataTable.settings[i], 0, "Cannot reinitialise DataTable.\n\n"+
-							"To retrieve the DataTables object for this table, pass no arguments or see "+
-							"the docs for bRetrieve and bDestroy" );
-						return;
-					}
-				}
-				
-				/* If the element we are initialising has the same ID as a table which was previously
-				 * initialised, but the table nodes don't match (from before) then we destroy the old
-				 * instance by simply deleting it. This is under the assumption that the table has been
-				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
-				 */
-				if ( DataTable.settings[i].sTableId == this.id )
-				{
-					DataTable.settings.splice( i, 1 );
-					break;
-				}
-			}
-			
-			/* Ensure the table has an ID - required for accessibility */
-			if ( sId === null || sId === "" )
-			{
-				sId = "DataTables_Table_"+(DataTable.ext._oExternConfig.iNextUnique++);
-				this.id = sId;
-			}
-			
-			/* Create the settings object for this table and set some of the default parameters */
-			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
-				"nTable":        this,
-				"oApi":          _that.oApi,
-				"oInit":         oInit,
-				"sDestroyWidth": $(this).width(),
-				"sInstance":     sId,
-				"sTableId":      sId
-			} );
-			DataTable.settings.push( oSettings );
-			
-			// Need to add the instance after the instance after the settings object has been added
-			// to the settings array, so we can self reference the table instance if more than one
-			oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
-			
-			/* Setting up the initialisation object */
-			if ( !oInit )
-			{
-				oInit = {};
-			}
-			
-			// Backwards compatibility, before we apply all the defaults
-			if ( oInit.oLanguage )
-			{
-				_fnLanguageCompat( oInit.oLanguage );
-			}
-			
-			oInit = _fnExtend( $.extend(true, {}, DataTable.defaults), oInit );
-			
-			// Map the initialisation options onto the settings object
-			_fnMap( oSettings.oFeatures, oInit, "bPaginate" );
-			_fnMap( oSettings.oFeatures, oInit, "bLengthChange" );
-			_fnMap( oSettings.oFeatures, oInit, "bFilter" );
-			_fnMap( oSettings.oFeatures, oInit, "bSort" );
-			_fnMap( oSettings.oFeatures, oInit, "bInfo" );
-			_fnMap( oSettings.oFeatures, oInit, "bProcessing" );
-			_fnMap( oSettings.oFeatures, oInit, "bAutoWidth" );
-			_fnMap( oSettings.oFeatures, oInit, "bSortClasses" );
-			_fnMap( oSettings.oFeatures, oInit, "bServerSide" );
-			_fnMap( oSettings.oFeatures, oInit, "bDeferRender" );
-			_fnMap( oSettings.oScroll, oInit, "sScrollX", "sX" );
-			_fnMap( oSettings.oScroll, oInit, "sScrollXInner", "sXInner" );
-			_fnMap( oSettings.oScroll, oInit, "sScrollY", "sY" );
-			_fnMap( oSettings.oScroll, oInit, "bScrollCollapse", "bCollapse" );
-			_fnMap( oSettings.oScroll, oInit, "bScrollInfinite", "bInfinite" );
-			_fnMap( oSettings.oScroll, oInit, "iScrollLoadGap", "iLoadGap" );
-			_fnMap( oSettings.oScroll, oInit, "bScrollAutoCss", "bAutoCss" );
-			_fnMap( oSettings, oInit, "asStripeClasses" );
-			_fnMap( oSettings, oInit, "asStripClasses", "asStripeClasses" ); // legacy
-			_fnMap( oSettings, oInit, "fnServerData" );
-			_fnMap( oSettings, oInit, "fnFormatNumber" );
-			_fnMap( oSettings, oInit, "sServerMethod" );
-			_fnMap( oSettings, oInit, "aaSorting" );
-			_fnMap( oSettings, oInit, "aaSortingFixed" );
-			_fnMap( oSettings, oInit, "aLengthMenu" );
-			_fnMap( oSettings, oInit, "sPaginationType" );
-			_fnMap( oSettings, oInit, "sAjaxSource" );
-			_fnMap( oSettings, oInit, "sAjaxDataProp" );
-			_fnMap( oSettings, oInit, "iCookieDuration" );
-			_fnMap( oSettings, oInit, "sCookiePrefix" );
-			_fnMap( oSettings, oInit, "sDom" );
-			_fnMap( oSettings, oInit, "bSortCellsTop" );
-			_fnMap( oSettings, oInit, "iTabIndex" );
-			_fnMap( oSettings, oInit, "oSearch", "oPreviousSearch" );
-			_fnMap( oSettings, oInit, "aoSearchCols", "aoPreSearchCols" );
-			_fnMap( oSettings, oInit, "iDisplayLength", "_iDisplayLength" );
-			_fnMap( oSettings, oInit, "bJQueryUI", "bJUI" );
-			_fnMap( oSettings, oInit, "fnCookieCallback" );
-			_fnMap( oSettings, oInit, "fnStateLoad" );
-			_fnMap( oSettings, oInit, "fnStateSave" );
-			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
-			
-			/* Callback functions which are array driven */
-			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
-			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
-			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
-			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
-			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
-			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
-			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
-			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
-			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
-			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
-			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
-			
-			if ( oSettings.oFeatures.bServerSide && oSettings.oFeatures.bSort &&
-				   oSettings.oFeatures.bSortClasses )
-			{
-				/* Enable sort classes for server-side processing. Safe to do it here, since server-side
-				 * processing must be enabled by the developer
-				 */
-				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'server_side_sort_classes' );
-			}
-			else if ( oSettings.oFeatures.bDeferRender )
-			{
-				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSortingClasses, 'defer_sort_classes' );
-			}
-			
-			if ( oInit.bJQueryUI )
-			{
-				/* Use the JUI classes object for display. You could clone the oStdClasses object if 
-				 * you want to have multiple tables with multiple independent classes 
-				 */
-				$.extend( oSettings.oClasses, DataTable.ext.oJUIClasses );
-				
-				if ( oInit.sDom === DataTable.defaults.sDom && DataTable.defaults.sDom === "lfrtip" )
-				{
-					/* Set the DOM to use a layout suitable for jQuery UI's theming */
-					oSettings.sDom = '<"H"lfr>t<"F"ip>';
-				}
-			}
-			else
-			{
-				$.extend( oSettings.oClasses, DataTable.ext.oStdClasses );
-			}
-			$(this).addClass( oSettings.oClasses.sTable );
-			
-			/* Calculate the scroll bar width and cache it for use later on */
-			if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
-			{
-				oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
-			}
-			
-			if ( oSettings.iInitDisplayStart === undefined )
-			{
-				/* Display start point, taking into account the save saving */
-				oSettings.iInitDisplayStart = oInit.iDisplayStart;
-				oSettings._iDisplayStart = oInit.iDisplayStart;
-			}
-			
-			/* Must be done after everything which can be overridden by a cookie! */
-			if ( oInit.bStateSave )
-			{
-				oSettings.oFeatures.bStateSave = true;
-				_fnLoadState( oSettings, oInit );
-				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
-			}
-			
-			if ( oInit.iDeferLoading !== null )
-			{
-				oSettings.bDeferLoading = true;
-				var tmp = $.isArray( oInit.iDeferLoading );
-				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
-				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
-			}
-			
-			if ( oInit.aaData !== null )
-			{
-				bUsePassedData = true;
-			}
-			
-			/* Language definitions */
-			if ( oInit.oLanguage.sUrl !== "" )
-			{
-				/* Get the language definitions from a file - because this Ajax call makes the language
-				 * get async to the remainder of this function we use bInitHandedOff to indicate that 
-				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
-				 */
-				oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
-				$.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
-					_fnLanguageCompat( json );
-					$.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
-					_fnInitialise( oSettings );
-				} );
-				bInitHandedOff = true;
-			}
-			else
-			{
-				$.extend( true, oSettings.oLanguage, oInit.oLanguage );
-			}
-			
-			
-			/*
-			 * Stripes
-			 */
-			if ( oInit.asStripeClasses === null )
-			{
-				oSettings.asStripeClasses =[
-					oSettings.oClasses.sStripeOdd,
-					oSettings.oClasses.sStripeEven
-				];
-			}
-			
-			/* Remove row stripe classes if they are already on the table row */
-			iLen=oSettings.asStripeClasses.length;
-			oSettings.asDestroyStripes = [];
-			if (iLen)
-			{
-				var bStripeRemove = false;
-				var anRows = $(this).children('tbody').children('tr:lt(' + iLen + ')');
-				for ( i=0 ; i<iLen ; i++ )
-				{
-					if ( anRows.hasClass( oSettings.asStripeClasses[i] ) )
-					{
-						bStripeRemove = true;
-						
-						/* Store the classes which we are about to remove so they can be re-added on destroy */
-						oSettings.asDestroyStripes.push( oSettings.asStripeClasses[i] );
-					}
-				}
-				
-				if ( bStripeRemove )
-				{
-					anRows.removeClass( oSettings.asStripeClasses.join(' ') );
-				}
-			}
-			
-			/*
-			 * Columns
-			 * See if we should load columns automatically or use defined ones
-			 */
-			var anThs = [];
-			var aoColumnsInit;
-			var nThead = this.getElementsByTagName('thead');
-			if ( nThead.length !== 0 )
-			{
-				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
-				anThs = _fnGetUniqueThs( oSettings );
-			}
-			
-			/* If not given a column array, generate one with nulls */
-			if ( oInit.aoColumns === null )
-			{
-				aoColumnsInit = [];
-				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
-				{
-					aoColumnsInit.push( null );
-				}
-			}
-			else
-			{
-				aoColumnsInit = oInit.aoColumns;
-			}
-			
-			/* Add the columns */
-			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
-			{
-				/* Short cut - use the loop to check if we have column visibility state to restore */
-				if ( oInit.saved_aoColumns !== undefined && oInit.saved_aoColumns.length == iLen )
-				{
-					if ( aoColumnsInit[i] === null )
-					{
-						aoColumnsInit[i] = {};
-					}
-					aoColumnsInit[i].bVisible = oInit.saved_aoColumns[i].bVisible;
-				}
-				
-				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
-			}
-			
-			/* Apply the column definitions */
-			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
-				_fnColumnOptions( oSettings, iCol, oDef );
-			} );
-			
-			
-			/*
-			 * Sorting
-			 * Check the aaSorting array
-			 */
-			for ( i=0, iLen=oSettings.aaSorting.length ; i<iLen ; i++ )
-			{
-				if ( oSettings.aaSorting[i][0] >= oSettings.aoColumns.length )
-				{
-					oSettings.aaSorting[i][0] = 0;
-				}
-				var oColumn = oSettings.aoColumns[ oSettings.aaSorting[i][0] ];
-				
-				/* Add a default sorting index */
-				if ( oSettings.aaSorting[i][2] === undefined )
-				{
-					oSettings.aaSorting[i][2] = 0;
-				}
-				
-				/* If aaSorting is not defined, then we use the first indicator in asSorting */
-				if ( oInit.aaSorting === undefined && oSettings.saved_aaSorting === undefined )
-				{
-					oSettings.aaSorting[i][1] = oColumn.asSorting[0];
-				}
-				
-				/* Set the current sorting index based on aoColumns.asSorting */
-				for ( j=0, jLen=oColumn.asSorting.length ; j<jLen ; j++ )
-				{
-					if ( oSettings.aaSorting[i][1] == oColumn.asSorting[j] )
-					{
-						oSettings.aaSorting[i][2] = j;
-						break;
-					}
-				}
-			}
-				
-			/* Do a first pass on the sorting classes (allows any size changes to be taken into
-			 * account, and also will apply sorting disabled classes if disabled
-			 */
-			_fnSortingClasses( oSettings );
-			
-			
-			/*
-			 * Final init
-			 * Cache the header, body and footer as required, creating them if needed
-			 */
-			
-			/* Browser support detection */
-			_fnBrowserDetect( oSettings );
-			
-			// Work around for Webkit bug 83867 - store the caption-side before removing from doc
-			var captions = $(this).children('caption').each( function () {
-				this._captionSide = $(this).css('caption-side');
-			} );
-			
-			var thead = $(this).children('thead');
-			if ( thead.length === 0 )
-			{
-				thead = [ document.createElement( 'thead' ) ];
-				this.appendChild( thead[0] );
-			}
-			oSettings.nTHead = thead[0];
-			
-			var tbody = $(this).children('tbody');
-			if ( tbody.length === 0 )
-			{
-				tbody = [ document.createElement( 'tbody' ) ];
-				this.appendChild( tbody[0] );
-			}
-			oSettings.nTBody = tbody[0];
-			oSettings.nTBody.setAttribute( "role", "alert" );
-			oSettings.nTBody.setAttribute( "aria-live", "polite" );
-			oSettings.nTBody.setAttribute( "aria-relevant", "all" );
-			
-			var tfoot = $(this).children('tfoot');
-			if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
-			{
-				// If we are a scrolling table, and no footer has been given, then we need to create
-				// a tfoot element for the caption element to be appended to
-				tfoot = [ document.createElement( 'tfoot' ) ];
-				this.appendChild( tfoot[0] );
-			}
-			
-			if ( tfoot.length > 0 )
-			{
-				oSettings.nTFoot = tfoot[0];
-				_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
-			}
-			
-			/* Check if there is data passing into the constructor */
-			if ( bUsePassedData )
-			{
-				for ( i=0 ; i<oInit.aaData.length ; i++ )
-				{
-					_fnAddData( oSettings, oInit.aaData[ i ] );
-				}
-			}
-			else
-			{
-				/* Grab the data from the page */
-				_fnGatherData( oSettings );
-			}
-			
-			/* Copy the data index array */
-			oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
-			
-			/* Initialisation complete - table can be drawn */
-			oSettings.bInitialised = true;
-			
-			/* Check if we need to initialise the table (it might not have been handed off to the
-			 * language processor)
-			 */
-			if ( bInitHandedOff === false )
-			{
-				_fnInitialise( oSettings );
-			}
-		} );
-		_that = null;
-		return this;
-	};
-
-	
-	
-	/**
-	 * Provide a common method for plug-ins to check the version of DataTables being used, in order
-	 * to ensure compatibility.
-	 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
-	 *    formats "X" and "X.Y" are also acceptable.
-	 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
-	 *    version, or false if this version of DataTales is not suitable
-	 *  @static
-	 *  @dtopt API-Static
-	 *
-	 *  @example
-	 *    alert( $.fn.dataTable.fnVersionCheck( '1.9.0' ) );
-	 */
-	DataTable.fnVersionCheck = function( sVersion )
-	{
-		/* This is cheap, but effective */
-		var fnZPad = function (Zpad, count)
-		{
-			while(Zpad.length < count) {
-				Zpad += '0';
-			}
-			return Zpad;
-		};
-		var aThis = DataTable.ext.sVersion.split('.');
-		var aThat = sVersion.split('.');
-		var sThis = '', sThat = '';
-		
-		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
-		{
-			sThis += fnZPad( aThis[i], 3 );
-			sThat += fnZPad( aThat[i], 3 );
-		}
-		
-		return parseInt(sThis, 10) >= parseInt(sThat, 10);
-	};
-	
-	
-	/**
-	 * Check if a TABLE node is a DataTable table already or not.
-	 *  @param {node} nTable The TABLE node to check if it is a DataTable or not (note that other
-	 *    node types can be passed in, but will always return false).
-	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
-	 *  @static
-	 *  @dtopt API-Static
-	 *
-	 *  @example
-	 *    var ex = document.getElementById('example');
-	 *    if ( ! $.fn.DataTable.fnIsDataTable( ex ) ) {
-	 *      $(ex).dataTable();
-	 *    }
-	 */
-	DataTable.fnIsDataTable = function ( nTable )
-	{
-		var o = DataTable.settings;
-	
-		for ( var i=0 ; i<o.length ; i++ )
-		{
-			if ( o[i].nTable === nTable || o[i].nScrollHead === nTable || o[i].nScrollFoot === nTable )
-			{
-				return true;
-			}
-		}
-	
-		return false;
-	};
-	
-	
-	/**
-	 * Get all DataTable tables that have been initialised - optionally you can select to
-	 * get only currently visible tables.
-	 *  @param {boolean} [bVisible=false] Flag to indicate if you want all (default) or 
-	 *    visible tables only.
-	 *  @returns {array} Array of TABLE nodes (not DataTable instances) which are DataTables
-	 *  @static
-	 *  @dtopt API-Static
-	 *
-	 *  @example
-	 *    var table = $.fn.dataTable.fnTables(true);
-	 *    if ( table.length > 0 ) {
-	 *      $(table).dataTable().fnAdjustColumnSizing();
-	 *    }
-	 */
-	DataTable.fnTables = function ( bVisible )
-	{
-		var out = [];
-	
-		jQuery.each( DataTable.settings, function (i, o) {
-			if ( !bVisible || (bVisible === true && $(o.nTable).is(':visible')) )
-			{
-				out.push( o.nTable );
-			}
-		} );
-	
-		return out;
-	};
-	
-
-	/**
-	 * Version string for plug-ins to check compatibility. Allowed format is
-	 * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
-	 * e are optional
-	 *  @member
-	 *  @type string
-	 *  @default Version number
-	 */
-	DataTable.version = "1.9.4";
-
-	/**
-	 * Private data store, containing all of the settings objects that are created for the
-	 * tables on a given page.
-	 * 
-	 * Note that the <i>DataTable.settings</i> object is aliased to <i>jQuery.fn.dataTableExt</i> 
-	 * through which it may be accessed and manipulated, or <i>jQuery.fn.dataTable.settings</i>.
-	 *  @member
-	 *  @type array
-	 *  @default []
-	 *  @private
-	 */
-	DataTable.settings = [];
-
-	/**
-	 * Object models container, for the various models that DataTables has available
-	 * to it. These models define the objects that are used to hold the active state 
-	 * and configuration of the table.
-	 *  @namespace
-	 */
-	DataTable.models = {};
-	
-	
-	/**
-	 * DataTables extension options and plug-ins. This namespace acts as a collection "area"
-	 * for plug-ins that can be used to extend the default DataTables behaviour - indeed many
-	 * of the build in methods use this method to provide their own capabilities (sorting methods
-	 * for example).
-	 * 
-	 * Note that this namespace is aliased to jQuery.fn.dataTableExt so it can be readily accessed
-	 * and modified by plug-ins.
-	 *  @namespace
-	 */
-	DataTable.models.ext = {
-		/**
-		 * Plug-in filtering functions - this method of filtering is complimentary to the default
-		 * type based filtering, and a lot more comprehensive as it allows you complete control
-		 * over the filtering logic. Each element in this array is a function (parameters
-		 * described below) that is called for every row in the table, and your logic decides if
-		 * it should be included in the filtered data set or not.
-		 *   <ul>
-		 *     <li>
-		 *       Function input parameters:
-		 *       <ul>
-		 *         <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
-		 *         <li>{array|object} Data for the row to be processed (same as the original format
-		 *           that was passed in as the data source, or an array from a DOM data source</li>
-		 *         <li>{int} Row index in aoData ({@link DataTable.models.oSettings.aoData}), which can
-		 *           be useful to retrieve the TR element if you need DOM interaction.</li>
-		 *       </ul>
-		 *     </li>
-		 *     <li>
-		 *       Function return:
-		 *       <ul>
-		 *         <li>{boolean} Include the row in the filtered result set (true) or not (false)</li>
-		 *       </ul>
-		 *     </il>
-		 *   </ul>
-		 *  @type array
-		 *  @default []
-		 *
-		 *  @example
-		 *    // The following example shows custom filtering being applied to the fourth column (i.e.
-		 *    // the aData[3] index) based on two input values from the end-user, matching the data in 
-		 *    // a certain range.
-		 *    $.fn.dataTableExt.afnFiltering.push(
-		 *      function( oSettings, aData, iDataIndex ) {
-		 *        var iMin = document.getElementById('min').value * 1;
-		 *        var iMax = document.getElementById('max').value * 1;
-		 *        var iVersion = aData[3] == "-" ? 0 : aData[3]*1;
-		 *        if ( iMin == "" && iMax == "" ) {
-		 *          return true;
-		 *        }
-		 *        else if ( iMin == "" && iVersion < iMax ) {
-		 *          return true;
-		 *        }
-		 *        else if ( iMin < iVersion && "" == iMax ) {
-		 *          return true;
-		 *        }
-		 *        else if ( iMin < iVersion && iVersion < iMax ) {
-		 *          return true;
-		 *        }
-		 *        return false;
-		 *      }
-		 *    );
-		 */
-		"afnFiltering": [],
-	
-	
-		/**
-		 * Plug-in sorting functions - this method of sorting is complimentary to the default type
-		 * based sorting that DataTables does automatically, allowing much greater control over the
-		 * the data that is being used to sort a column. This is useful if you want to do sorting
-		 * based on live data (for example the contents of an 'input' element) rather than just the
-		 * static string that DataTables knows of. The way these plug-ins work is that you create
-		 * an array of the values you wish to be sorted for the column in question and then return
-		 * that array. Which pre-sorting function is run here depends on the sSortDataType parameter
-		 * that is used for the column (if any). This is the corollary of <i>ofnSearch</i> for sort 
-		 * data.
-		 *   <ul>
-	     *     <li>
-	     *       Function input parameters:
-	     *       <ul>
-		 *         <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
-	     *         <li>{int} Target column index</li>
-	     *       </ul>
-	     *     </li>
-		 *     <li>
-		 *       Function return:
-		 *       <ul>
-		 *         <li>{array} Data for the column to be sorted upon</li>
-		 *       </ul>
-		 *     </il>
-		 *   </ul>
-		 *  
-		 * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
-		 * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
-		 * used as a function will give you a 'type' (sorting, filtering etc) that you can use to 
-		 * prepare the data as required for the different types. As such, this method is deprecated.
-		 *  @type array
-		 *  @default []
-		 *  @deprecated
-		 *
-		 *  @example
-		 *    // Updating the cached sorting information with user entered values in HTML input elements
-		 *    jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
-		 *    {
-		 *      var aData = [];
-		 *      $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
-		 *        aData.push( this.value );
-		 *      } );
-		 *      return aData;
-		 *    }
-		 */
-		"afnSortData": [],
-	
-	
-		/**
-		 * Feature plug-ins - This is an array of objects which describe the feature plug-ins that are
-		 * available to DataTables. These feature plug-ins are accessible through the sDom initialisation
-		 * option. As such, each feature plug-in must describe a function that is used to initialise
-		 * itself (fnInit), a character so the feature can be enabled by sDom (cFeature) and the name
-		 * of the feature (sFeature). Thus the objects attached to this method must provide:
-		 *   <ul>
-		 *     <li>{function} fnInit Initialisation of the plug-in
-		 *       <ul>
-	     *         <li>
-	     *           Function input parameters:
-	     *           <ul>
-		 *             <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
-	     *           </ul>
-	     *         </li>
-		 *         <li>
-		 *           Function return:
-		 *           <ul>
-		 *             <li>{node|null} The element which contains your feature. Note that the return
-		 *                may also be void if your plug-in does not require to inject any DOM elements 
-		 *                into DataTables control (sDom) - for example this might be useful when 
-		 *                developing a plug-in which allows table control via keyboard entry.</li>
-		 *           </ul>
-		 *         </il>
-		 *       </ul>
-		 *     </li>
-		 *     <li>{character} cFeature Character that will be matched in sDom - case sensitive</li>
-		 *     <li>{string} sFeature Feature name</li>
-		 *   </ul>
-		 *  @type array
-		 *  @default []
-		 * 
-		 *  @example
-		 *    // How TableTools initialises itself.
-		 *    $.fn.dataTableExt.aoFeatures.push( {
-		 *      "fnInit": function( oSettings ) {
-		 *        return new TableTools( { "oDTSettings": oSettings } );
-		 *      },
-		 *      "cFeature": "T",
-		 *      "sFeature": "TableTools"
-		 *    } );
-		 */
-		"aoFeatures": [],
-	
-	
-		/**
-		 * Type detection plug-in functions - DataTables utilises types to define how sorting and
-		 * filtering behave, and types can be either  be defined by the developer (sType for the
-		 * column) or they can be automatically detected by the methods in this array. The functions
-		 * defined in the array are quite simple, taking a single parameter (the data to analyse) 
-		 * and returning the type if it is a known type, or null otherwise.
-		 *   <ul>
-	     *     <li>
-	     *       Function input parameters:
-	     *       <ul>
-		 *         <li>{*} Data from the column cell to be analysed</li>
-	     *       </ul>
-	     *     </li>
-		 *     <li>
-		 *       Function return:
-		 *       <ul>
-		 *         <li>{string|null} Data type detected, or null if unknown (and thus pass it
-		 *           on to the other type detection functions.</li>
-		 *       </ul>
-		 *     </il>
-		 *   </ul>
-		 *  @type array
-		 *  @default []
-		 *  
-		 *  @example
-		 *    // Currency type detection plug-in:
-		 *    jQuery.fn.dataTableExt.aTypes.push(
-		 *      function ( sData ) {
-		 *        var sValidChars = "0123456789.-";
-		 *        var Char;
-		 *        
-		 *        // Check the numeric part
-		 *        for ( i=1 ; i<sData.length ; i++ ) {
-		 *          Char = sData.charAt(i); 
-		 *          if (sValidChars.indexOf(Char) == -1) {
-		 *            return null;
-		 *          }
-		 *        }
-		 *        
-		 *        // Check prefixed by currency
-		 *        if ( sData.charAt(0) == '$' || sData.charAt(0) == '&pound;' ) {
-		 *          return 'currency';
-		 *        }
-		 *        return null;
-		 *      }
-		 *    );
-		 */
-		"aTypes": [],
-	
-	
-		/**
-		 * Provide a common method for plug-ins to check the version of DataTables being used, 
-		 * in order to ensure compatibility.
-		 *  @type function
-		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note 
-		 *    that the formats "X" and "X.Y" are also acceptable.
-		 *  @returns {boolean} true if this version of DataTables is greater or equal to the 
-		 *    required version, or false if this version of DataTales is not suitable
-		 *
-		 *  @example
-		 *    $(document).ready(function() {
-		 *      var oTable = $('#example').dataTable();
-		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
-		 *    } );
-		 */
-		"fnVersionCheck": DataTable.fnVersionCheck,
-	
-	
-		/**
-		 * Index for what 'this' index API functions should use
-		 *  @type int
-		 *  @default 0
-		 */
-		"iApiIndex": 0,
-	
-	
-		/**
-		 * Pre-processing of filtering data plug-ins - When you assign the sType for a column
-		 * (or have it automatically detected for you by DataTables or a type detection plug-in), 
-		 * you will typically be using this for custom sorting, but it can also be used to provide 
-		 * custom filtering by allowing you to pre-processing the data and returning the data in
-		 * the format that should be filtered upon. This is done by adding functions this object 
-		 * with a parameter name which matches the sType for that target column. This is the
-		 * corollary of <i>afnSortData</i> for filtering data.
-		 *   <ul>
-	     *     <li>
-	     *       Function input parameters:
-	     *       <ul>
-		 *         <li>{*} Data from the column cell to be prepared for filtering</li>
-	     *       </ul>
-	     *     </li>
-		 *     <li>
-		 *       Function return:
-		 *       <ul>
-		 *         <li>{string|null} Formatted string that will be used for the filtering.</li>
-		 *       </ul>
-		 *     </il>
-		 *   </ul>
-		 * 
-		 * Note that as of v1.9, it is typically preferable to use <i>mData</i> to prepare data for
-		 * the different uses that DataTables can put the data to. Specifically <i>mData</i> when
-		 * used as a function will give you a 'type' (sorting, filtering etc) that you can use to 
-		 * prepare the data as required for the different types. As such, this method is deprecated.
-		 *  @type object
-		 *  @default {}
-		 *  @deprecated
-		 *
-		 *  @example
-		 *    $.fn.dataTableExt.ofnSearch['title-numeric'] = function ( sData ) {
-		 *      return sData.replace(/\n/g," ").replace( /<.*?>/g, "" );
-		 *    }
-		 */
-		"ofnSearch": {},
-	
-	
-		/**
-		 * Container for all private functions in DataTables so they can be exposed externally
-		 *  @type object
-		 *  @default {}
-		 */
-		"oApi": {},
-	
-	
-		/**
-		 * Storage for the various classes that DataTables uses
-		 *  @type object
-		 *  @default {}
-		 */
-		"oStdClasses": {},
-		
-	
-		/**
-		 * Storage for the various classes that DataTables uses - jQuery UI suitable
-		 *  @type object
-		 *  @default {}
-		 */
-		"oJUIClasses": {},
-	
-	
-		/**
-		 * Pagination plug-in methods - The style and controls of the pagination can significantly 
-		 * impact on how the end user interacts with the data in your table, and DataTables allows 
-		 * the addition of pagination controls by extending this object, which can then be enabled
-		 * through the <i>sPaginationType</i> initialisation parameter. Each pagination type that
-		 * is added is an object (the property name of which is what <i>sPaginationType</i> refers
-		 * to) that has two properties, both methods that are used by DataTables to update the
-		 * control's state.
-		 *   <ul>
-		 *     <li>
-		 *       fnInit -  Initialisation of the paging controls. Called only during initialisation 
-		 *         of the table. It is expected that this function will add the required DOM elements 
-		 *         to the page for the paging controls to work. The element pointer 
-		 *         'oSettings.aanFeatures.p' array is provided by DataTables to contain the paging 
-		 *         controls (note that this is a 2D array to allow for multiple instances of each 
-		 *         DataTables DOM element). It is suggested that you add the controls to this element 
-		 *         as children
-		 *       <ul>
-	     *         <li>
-	     *           Function input parameters:
-	     *           <ul>
-		 *             <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
-		 *             <li>{node} Container into which the pagination controls must be inserted</li>
-		 *             <li>{function} Draw callback function - whenever the controls cause a page
-		 *               change, this method must be called to redraw the table.</li>
-	     *           </ul>
-	     *         </li>
-		 *         <li>
-		 *           Function return:
-		 *           <ul>
-		 *             <li>No return required</li>
-		 *           </ul>
-		 *         </il>
-		 *       </ul>
-		 *     </il>
-		 *     <li>
-		 *       fnInit -  This function is called whenever the paging status of the table changes and is
-		 *         typically used to update classes and/or text of the paging controls to reflex the new 
-		 *         status.
-		 *       <ul>
-	     *         <li>
-	     *           Function input parameters:
-	     *           <ul>
-		 *             <li>{object} DataTables settings object: see {@link DataTable.models.oSettings}.</li>
-		 *             <li>{function} Draw callback function - in case you need to redraw the table again
-		 *               or attach new event listeners</li>
-	     *           </ul>
-	     *         </li>
-		 *         <li>
-		 *           Function return:
-		 *           <ul>
-		 *             <li>No return required</li>
-		 *           </ul>
-		 *         </il>
-		 *       </ul>
-		 *     </il>
-		 *   </ul>
-		 *  @type object
-		 *  @default {}
-		 *
-		 *  @example
-		 *    $.fn.dataTableExt.oPagination.four_button = {
-		 *      "fnInit": function ( oSettings, nPaging, fnCallbackDraw ) {
-		 *        nFirst = document.createElement( 'span' );
-		 *        nPrevious = document.createElement( 'span' );
-		 *        nNext = document.createElement( 'span' );
-		 *        nLast = document.createElement( 'span' );
-		 *        
-		 *        nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
-		 *        nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
-		 *        nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
-		 *        nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
-		 *        
-		 *        nFirst.className = "paginate_button first";
-		 *        nPrevious.className = "paginate_button previous";
-		 *        nNext.className="paginate_button next";
-		 *        nLast.className = "paginate_button last";
-		 *        
-		 *        nPaging.appendChild( nFirst );
-		 *        nPaging.appendChild( nPrevious );
-		 *        nPaging.appendChild( nNext );
-		 *        nPaging.appendChild( nLast );
-		 *        
-		 *        $(nFirst).click( function () {
-		 *          oSettings.oApi._fnPageChange( oSettings, "first" );
-		 *          fnCallbackDraw( oSettings );
-		 *        } );
-		 *        
-		 *        $(nPrevious).click( function() {
-		 *          oSettings.oApi._fnPageChange( oSettings, "previous" );
-		 *          fnCallbackDraw( oSettings );
-		 *        } );
-		 *        
-		 *        $(nNext).click( function() {
-		 *          oSettings.oApi._fnPageChange( oSettings, "next" );
-		 *          fnCallbackDraw( oSettings );
-		 *        } );
-		 *        
-		 *        $(nLast).click( function() {
-		 *          oSettings.oApi._fnPageChange( oSettings, "last" );
-		 *          fnCallbackDraw( oSettings );
-		 *        } );
-		 *        
-		 *        $(nFirst).bind( 'selectstart', function () { return false; } );
-		 *        $(nPrevious).bind( 'selectstart', function () { return false; } );
-		 *        $(nNext).bind( 'selectstart', function () { return false; } );
-		 *        $(nLast).bind( 'selectstart', function () { return false; } );
-		 *      },
-		 *      
-		 *      "fnUpdate": function ( oSettings, fnCallbackDraw ) {
-		 *        if ( !oSettings.aanFeatures.p ) {
-		 *          return;
-		 *        }
-		 *        
-		 *        // Loop over each instance of the pager
-		 *        var an = oSettings.aanFeatures.p;
-		 *        for ( var i=0, iLen=an.length ; i<iLen ; i++ ) {
-		 *          var buttons = an[i].getElementsByTagName('span');
-		 *          if ( oSettings._iDisplayStart === 0 ) {
-		 *            buttons[0].className = "paginate_disabled_previous";
-		 *            buttons[1].className = "paginate_disabled_previous";
-		 *          }
-		 *          else {
-		 *            buttons[0].className = "paginate_enabled_previous";
-		 *            buttons[1].className = "paginate_enabled_previous";
-		 *          }
-		 *          
-		 *          if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) {
-		 *            buttons[2].className = "paginate_disabled_next";
-		 *            buttons[3].className = "paginate_disabled_next";
-		 *          }
-		 *          else {
-		 *            buttons[2].className = "paginate_enabled_next";
-		 *            buttons[3].className = "paginate_enabled_next";
-		 *          }
-		 *        }
-		 *      }
-		 *    };
-		 */
-		"oPagination": {},
-	
-	
-		/**
-		 * Sorting plug-in methods - Sorting in DataTables is based on the detected type of the
-		 * data column (you can add your own type detection functions, or override automatic 
-		 * detection using sType). With this specific type given to the column, DataTables will 
-		 * apply the required sort from the functions in the object. Each sort type must provide
-		 * two mandatory methods, one each for ascending and descending sorting, and can optionally
-		 * provide a pre-formatting method that will help speed up sorting by allowing DataTables
-		 * to pre-format the sort data only once (rather than every time the actual sort functions
-		 * are run). The two sorting functions are typical Javascript sort methods:
-		 *   <ul>
-	     *     <li>
-	     *       Function input parameters:
-	     *       <ul>
-		 *         <li>{*} Data to compare to the second parameter</li>
-		 *         <li>{*} Data to compare to the first parameter</li>
-	     *       </ul>
-	     *     </li>
-		 *     <li>
-		 *       Function return:
-		 *       <ul>
-		 *         <li>{int} Sorting match: <0 if first parameter should be sorted lower than
-		 *           the second parameter, ===0 if the two parameters are equal and >0 if
-		 *           the first parameter should be sorted height than the second parameter.</li>
-		 *       </ul>
-		 *     </il>
-		 *   </ul>
-		 *  @type object
-		 *  @default {}
-		 *
-		 *  @example
-		 *    // Case-sensitive string sorting, with no pre-formatting method
-		 *    $.extend( $.fn.dataTableExt.oSort, {
-		 *      "string-case-asc": function(x,y) {
-		 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-		 *      },
-		 *      "string-case-desc": function(x,y) {
-		 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
-		 *      }
-		 *    } );
-		 *
-		 *  @example
-		 *    // Case-insensitive string sorting, with pre-formatting
-		 *    $.extend( $.fn.dataTableExt.oSort, {
-		 *      "string-pre": function(x) {
-		 *        return x.toLowerCase();
-		 *      },
-		 *      "string-asc": function(x,y) {
-		 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-		 *      },
-		 *      "string-desc": function(x,y) {
-		 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
-		 *      }
-		 *    } );
-		 */
-		"oSort": {},
-	
-	
-		/**
-		 * Version string for plug-ins to check compatibility. Allowed format is
-		 * a.b.c.d.e where: a:int, b:int, c:int, d:string(dev|beta), e:int. d and
-		 * e are optional
-		 *  @type string
-		 *  @default Version number
-		 */
-		"sVersion": DataTable.version,
-	
-	
-		/**
-		 * How should DataTables report an error. Can take the value 'alert' or 'throw'
-		 *  @type string
-		 *  @default alert
-		 */
-		"sErrMode": "alert",
-	
-	
-		/**
-		 * Store information for DataTables to access globally about other instances
-		 *  @namespace
-		 *  @private
-		 */
-		"_oExternConfig": {
-			/* int:iNextUnique - next unique number for an instance */
-			"iNextUnique": 0
-		}
-	};
-	
-	
-	
-	
-	/**
-	 * Template object for the way in which DataTables holds information about
-	 * search information for the global filter and individual column filters.
-	 *  @namespace
-	 */
-	DataTable.models.oSearch = {
-		/**
-		 * Flag to indicate if the filtering should be case insensitive or not
-		 *  @type boolean
-		 *  @default true
-		 */
-		"bCaseInsensitive": true,
-	
-		/**
-		 * Applied search term
-		 *  @type string
-		 *  @default <i>Empty string</i>
-		 */
-		"sSearch": "",
-	
-		/**
-		 * Flag to indicate if the search term should be interpreted as a
-		 * regular expression (true) or not (false) and therefore and special
-		 * regex characters escaped.
-		 *  @type boolean
-		 *  @default false
-		 */
-		"bRegex": false,
-	
-		/**
-		 * Flag to indicate if DataTables is to use its smart filtering or not.
-		 *  @type boolean
-		 *  @default true
-		 */
-		"bSmart": true
-	};
-	
-	
-	
-	
-	/**
-	 * Template object for the way in which DataTables holds information about
-	 * each individual row. This is the object format used for the settings 
-	 * aoData array.
-	 *  @namespace
-	 */
-	DataTable.models.oRow = {
-		/**
-		 * TR element for the row
-		 *  @type node
-		 *  @default null
-		 */
-		"nTr": null,
-	
-		/**
-		 * Data object from the original data source for the row. This is either
-		 * an array if using the traditional form of DataTables, or an object if
-		 * using mData options. The exact type will depend on the passed in
-		 * data from the data source, or will be an array if using DOM a data 
-		 * source.
-		 *  @type array|object
-		 *  @default []
-		 */
-		"_aData": [],
-	
-		/**
-		 * Sorting data cache - this array is ostensibly the same length as the
-		 * number of columns (although each index is generated only as it is 
-		 * needed), and holds the data that is used for sorting each column in the
-		 * row. We do this cache generation at the start of the sort in order that
-		 * the formatting of the sort data need be done only once for each cell
-		 * per sort. This array should not be read from or written to by anything
-		 * other than the master sorting methods.
-		 *  @type array
-		 *  @default []
-		 *  @private
-		 */
-		"_aSortData": [],
-	
-		/**
-		 * Array of TD elements that are cached for hidden rows, so they can be
-		 * reinserted into the table if a column is made visible again (or to act
-		 * as a store if a column is made hidden). Only hidden columns have a 
-		 * reference in the array. For non-hidden columns the value is either
-		 * undefined or null.
-		 *  @type array nodes
-		 *  @default []
-		 *  @private
-		 */
-		"_anHidden": [],
-	
-		/**
-		 * Cache of the class name that DataTables has applied to the row, so we
-		 * can quickly look at this variable rather than needing to do a DOM check
-		 * on className for the nTr property.
-		 *  @type string
-		 *  @default <i>Empty string</i>
-		 *  @private
-		 */
-		"_sRowStripe": ""
-	};
-	
-	
-	
-	/**
-	 * Template object for the column information object in DataTables. This object
-	 * is held in the settings aoColumns array and contains all the information that
-	 * DataTables needs about each individual column.
-	 * 
-	 * Note that this object is related to {@link DataTable.defaults.columns} 
-	 * but this one is the internal data store for DataTables's cache of columns.
-	 * It should NOT be manipulated outside of DataTables. Any configuration should
-	 * be done through the initialisation options.
-	 *  @namespace
-	 */
-	DataTable.models.oColumn = {
-		/**
-		 * A list of the columns that sorting should occur on when this column
-		 * is sorted. That this property is an array allows multi-column sorting
-		 * to be defined for a column (for example first name / last name columns
-		 * would benefit from this). The values are integers pointing to the
-		 * columns to be sorted on (typically it will be a single integer pointing
-		 * at itself, but that doesn't need to be the case).
-		 *  @type array
-		 */
-		"aDataSort": null,
-	
-		/**
-		 * Define the sorting directions that are applied to the column, in sequence
-		 * as the column is repeatedly sorted upon - i.e. the first value is used
-		 * as the sorting direction when the column if first sorted (clicked on).
-		 * Sort it again (click again) and it will move on to the next index.
-		 * Repeat until loop.
-		 *  @type array
-		 */
-		"asSorting": null,
-		
-		/**
-		 * Flag to indicate if the column is searchable, and thus should be included
-		 * in the filtering or not.
-		 *  @type boolean
-		 */
-		"bSearchable": null,
-		
-		/**
-		 * Flag to indicate if the column is sortable or not.
-		 *  @type boolean
-		 */
-		"bSortable": null,
-		
-		/**
-		 * <code>Deprecated</code> When using fnRender, you have two options for what 
-		 * to do with the data, and this property serves as the switch. Firstly, you 
-		 * can have the sorting and filtering use the rendered value (true - default), 
-		 * or you can have the sorting and filtering us the original value (false).
-		 *
-		 * Please note that this option has now been deprecated and will be removed
-		 * in the next version of DataTables. Please use mRender / mData rather than
-		 * fnRender.
-		 *  @type boolean
-		 *  @deprecated
-		 */
-		"bUseRendered": null,
-		
-		/**
-		 * Flag to indicate if the column is currently visible in the table or not
-		 *  @type boolean
-		 */
-		"bVisible": null,
-		
-		/**
-		 * Flag to indicate to the type detection method if the automatic type
-		 * detection should be used, or if a column type (sType) has been specified
-		 *  @type boolean
-		 *  @default true
-		 *  @private
-		 */
-		"_bAutoType": true,
-		
-		/**
-		 * Developer definable function that is called whenever a cell is created (Ajax source,
-		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
-		 * allowing you to modify the DOM element (add background colour for example) when the
-		 * element is available.
-		 *  @type function
-		 *  @param {element} nTd The TD node that has been created
-		 *  @param {*} sData The Data for the cell
-		 *  @param {array|object} oData The data for the whole row
-		 *  @param {int} iRow The row index for the aoData data store
-		 *  @default null
-		 */
-		"fnCreatedCell": null,
-		
-		/**
-		 * Function to get data from a cell in a column. You should <b>never</b>
-		 * access data directly through _aData internally in DataTables - always use
-		 * the method attached to this property. It allows mData to function as
-		 * required. This function is automatically assigned by the column 
-		 * initialisation method
-		 *  @type function
-		 *  @param {array|object} oData The data array/object for the array 
-		 *    (i.e. aoData[]._aData)
-		 *  @param {string} sSpecific The specific data type you want to get - 
-		 *    'display', 'type' 'filter' 'sort'
-		 *  @returns {*} The data for the cell from the given row's data
-		 *  @default null
-		 */
-		"fnGetData": null,
-		
-		/**
-		 * <code>Deprecated</code> Custom display function that will be called for the 
-		 * display of each cell in this column.
-		 *
-		 * Please note that this option has now been deprecated and will be removed
-		 * in the next version of DataTables. Please use mRender / mData rather than
-		 * fnRender.
-		 *  @type function
-		 *  @param {object} o Object with the following parameters:
-		 *  @param {int}    o.iDataRow The row in aoData
-		 *  @param {int}    o.iDataColumn The column in question
-		 *  @param {array}  o.aData The data for the row in question
-		 *  @param {object} o.oSettings The settings object for this DataTables instance
-		 *  @returns {string} The string you which to use in the display
-		 *  @default null
-		 *  @deprecated
-		 */
-		"fnRender": null,
-		
-		/**
-		 * Function to set data for a cell in the column. You should <b>never</b> 
-		 * set the data directly to _aData internally in DataTables - always use
-		 * this method. It allows mData to function as required. This function
-		 * is automatically assigned by the column initialisation method
-		 *  @type function
-		 *  @param {array|object} oData The data array/object for the array 
-		 *    (i.e. aoData[]._aData)
-		 *  @param {*} sValue Value to set
-		 *  @default null
-		 */
-		"fnSetData": null,
-		
-		/**
-		 * Property to read the value for the cells in the column from the data 
-		 * source array / object. If null, then the default content is used, if a
-		 * function is given then the return from the function is used.
-		 *  @type function|int|string|null
-		 *  @default null
-		 */
-		"mData": null,
-		
-		/**
-		 * Partner property to mData which is used (only when defined) to get
-		 * the data - i.e. it is basically the same as mData, but without the
-		 * 'set' option, and also the data fed to it is the result from mData.
-		 * This is the rendering method to match the data method of mData.
-		 *  @type function|int|string|null
-		 *  @default null
-		 */
-		"mRender": null,
-		
-		/**
-		 * Unique header TH/TD element for this column - this is what the sorting
-		 * listener is attached to (if sorting is enabled.)
-		 *  @type node
-		 *  @default null
-		 */
-		"nTh": null,
-		
-		/**
-		 * Unique footer TH/TD element for this column (if there is one). Not used 
-		 * in DataTables as such, but can be used for plug-ins to reference the 
-		 * footer for each column.
-		 *  @type node
-		 *  @default null
-		 */
-		"nTf": null,
-		
-		/**
-		 * The class to apply to all TD elements in the table's TBODY for the column
-		 *  @type string
-		 *  @default null
-		 */
-		"sClass": null,
-		
-		/**
-		 * When DataTables calculates the column widths to assign to each column,
-		 * it finds the longest string in each column and then constructs a
-		 * temporary table and reads the widths from that. The problem with this
-		 * is that "mmm" is much wider then "iiii", but the latter is a longer 
-		 * string - thus the calculation can go wrong (doing it properly and putting
-		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
-		 * a "work around" we provide this option. It will append its value to the
-		 * text that is found to be the longest string for the column - i.e. padding.
-		 *  @type string
-		 */
-		"sContentPadding": null,
-		
-		/**
-		 * Allows a default value to be given for a column's data, and will be used
-		 * whenever a null data source is encountered (this can be because mData
-		 * is set to null, or because the data source itself is null).
-		 *  @type string
-		 *  @default null
-		 */
-		"sDefaultContent": null,
-		
-		/**
-		 * Name for the column, allowing reference to the column by name as well as
-		 * by index (needs a lookup to work by name).
-		 *  @type string
-		 */
-		"sName": null,
-		
-		/**
-		 * Custom sorting data type - defines which of the available plug-ins in
-		 * afnSortData the custom sorting will use - if any is defined.
-		 *  @type string
-		 *  @default std
-		 */
-		"sSortDataType": 'std',
-		
-		/**
-		 * Class to be applied to the header element when sorting on this column
-		 *  @type string
-		 *  @default null
-		 */
-		"sSortingClass": null,
-		
-		/**
-		 * Class to be applied to the header element when sorting on this column -
-		 * when jQuery UI theming is used.
-		 *  @type string
-		 *  @default null
-		 */
-		"sSortingClassJUI": null,
-		
-		/**
-		 * Title of the column - what is seen in the TH element (nTh).
-		 *  @type string
-		 */
-		"sTitle": null,
-		
-		/**
-		 * Column sorting and filtering type
-		 *  @type string
-		 *  @default null
-		 */
-		"sType": null,
-		
-		/**
-		 * Width of the column
-		 *  @type string
-		 *  @default null
-		 */
-		"sWidth": null,
-		
-		/**
-		 * Width of the column when it was first "encountered"
-		 *  @type string
-		 *  @default null
-		 */
-		"sWidthOrig": null
-	};
-	
-	
-	
-	/**
-	 * Initialisation options that can be given to DataTables at initialisation 
-	 * time.
-	 *  @namespace
-	 */
-	DataTable.defaults = {
-		/**
-		 * An array of data to use for the table, passed in at initialisation which 
-		 * will be used in preference to any data which is already in the DOM. This is
-		 * particularly useful for constructing tables purely in Javascript, for
-		 * example with a custom Ajax call.
-		 *  @type array
-		 *  @default null
-		 *  @dtopt Option
-		 * 
-		 *  @example
-		 *    // Using a 2D array data source
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "aaData": [
-		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
-		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
-		 *        ],
-		 *        "aoColumns": [
-		 *          { "sTitle": "Engine" },
-		 *          { "sTitle": "Browser" },
-		 *          { "sTitle": "Platform" },
-		 *          { "sTitle": "Version" },
-		 *          { "sTitle": "Grade" }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using an array of objects as a data source (mData)
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "aaData": [
-		 *          {
-		 *            "engine":   "Trident",
-		 *            "browser":  "Internet Explorer 4.0",
-		 *            "platform": "Win 95+",
-		 *            "version":  4,
-		 *            "grade":    "X"
-		 *          },
-		 *          {
-		 *            "engine":   "Trident",
-		 *            "browser":  "Internet Explorer 5.0",
-		 *            "platform": "Win 95+",
-		 *            "version":  5,
-		 *            "grade":    "C"
-		 *          }
-		 *        ],
-		 *        "aoColumns": [
-		 *          { "sTitle": "Engine",   "mData": "engine" },
-		 *          { "sTitle": "Browser",  "mData": "browser" },
-		 *          { "sTitle": "Platform", "mData": "platform" },
-		 *          { "sTitle": "Version",  "mData": "version" },
-		 *          { "sTitle": "Grade",    "mData": "grade" }
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"aaData": null,
-	
-	
-		/**
-		 * If sorting is enabled, then DataTables will perform a first pass sort on 
-		 * initialisation. You can define which column(s) the sort is performed upon, 
-		 * and the sorting direction, with this variable. The aaSorting array should 
-		 * contain an array for each column to be sorted initially containing the 
-		 * column's index and a direction string ('asc' or 'desc').
-		 *  @type array
-		 *  @default [[0,'asc']]
-		 *  @dtopt Option
-		 * 
-		 *  @example
-		 *    // Sort by 3rd column first, and then 4th column
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aaSorting": [[2,'asc'], [3,'desc']]
-		 *      } );
-		 *    } );
-		 *    
-		 *    // No initial sorting
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aaSorting": []
-		 *      } );
-		 *    } );
-		 */
-		"aaSorting": [[0,'asc']],
-	
-	
-		/**
-		 * This parameter is basically identical to the aaSorting parameter, but 
-		 * cannot be overridden by user interaction with the table. What this means 
-		 * is that you could have a column (visible or hidden) which the sorting will 
-		 * always be forced on first - any sorting after that (from the user) will 
-		 * then be performed as required. This can be useful for grouping rows 
-		 * together.
-		 *  @type array
-		 *  @default null
-		 *  @dtopt Option
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aaSortingFixed": [[0,'asc']]
-		 *      } );
-		 *    } )
-		 */
-		"aaSortingFixed": null,
-	
-	
-		/**
-		 * This parameter allows you to readily specify the entries in the length drop
-		 * down menu that DataTables shows when pagination is enabled. It can be 
-		 * either a 1D array of options which will be used for both the displayed 
-		 * option and the value, or a 2D array which will use the array in the first 
-		 * position as the value, and the array in the second position as the 
-		 * displayed options (useful for language strings such as 'All').
-		 *  @type array
-		 *  @default [ 10, 25, 50, 100 ]
-		 *  @dtopt Option
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aLengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
-		 *      } );
-		 *    } );
-		 *  
-		 *  @example
-		 *    // Setting the default display length as well as length menu
-		 *    // This is likely to be wanted if you remove the '10' option which
-		 *    // is the iDisplayLength default.
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "iDisplayLength": 25,
-		 *        "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
-		 *      } );
-		 *    } );
-		 */
-		"aLengthMenu": [ 10, 25, 50, 100 ],
-	
-	
-		/**
-		 * The aoColumns option in the initialisation parameter allows you to define
-		 * details about the way individual columns behave. For a full list of
-		 * column options that can be set, please see 
-		 * {@link DataTable.defaults.columns}. Note that if you use aoColumns to
-		 * define your columns, you must have an entry in the array for every single
-		 * column that you have in your table (these can be null if you don't which
-		 * to specify any options).
-		 *  @member
-		 */
-		"aoColumns": null,
-	
-		/**
-		 * Very similar to aoColumns, aoColumnDefs allows you to target a specific 
-		 * column, multiple columns, or all columns, using the aTargets property of 
-		 * each object in the array. This allows great flexibility when creating 
-		 * tables, as the aoColumnDefs arrays can be of any length, targeting the 
-		 * columns you specifically want. aoColumnDefs may use any of the column 
-		 * options available: {@link DataTable.defaults.columns}, but it _must_
-		 * have aTargets defined in each object in the array. Values in the aTargets
-		 * array may be:
-		 *   <ul>
-		 *     <li>a string - class name will be matched on the TH for the column</li>
-		 *     <li>0 or a positive integer - column index counting from the left</li>
-		 *     <li>a negative integer - column index counting from the right</li>
-		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
-		 *   </ul>
-		 *  @member
-		 */
-		"aoColumnDefs": null,
-	
-	
-		/**
-		 * Basically the same as oSearch, this parameter defines the individual column
-		 * filtering state at initialisation time. The array must be of the same size 
-		 * as the number of columns, and each element be an object with the parameters
-		 * "sSearch" and "bEscapeRegex" (the latter is optional). 'null' is also
-		 * accepted and the default will be used.
-		 *  @type array
-		 *  @default []
-		 *  @dtopt Option
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoSearchCols": [
-		 *          null,
-		 *          { "sSearch": "My filter" },
-		 *          null,
-		 *          { "sSearch": "^[0-9]", "bEscapeRegex": false }
-		 *        ]
-		 *      } );
-		 *    } )
-		 */
-		"aoSearchCols": [],
-	
-	
-		/**
-		 * An array of CSS classes that should be applied to displayed rows. This 
-		 * array may be of any length, and DataTables will apply each class 
-		 * sequentially, looping when required.
-		 *  @type array
-		 *  @default null <i>Will take the values determined by the oClasses.sStripe*
-		 *    options</i>
-		 *  @dtopt Option
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "asStripeClasses": [ 'strip1', 'strip2', 'strip3' ]
-		 *      } );
-		 *    } )
-		 */
-		"asStripeClasses": null,
-	
-	
-		/**
-		 * Enable or disable automatic column width calculation. This can be disabled
-		 * as an optimisation (it takes some time to calculate the widths) if the
-		 * tables widths are passed in using aoColumns.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bAutoWidth": false
-		 *      } );
-		 *    } );
-		 */
-		"bAutoWidth": true,
-	
-	
-		/**
-		 * Deferred rendering can provide DataTables with a huge speed boost when you
-		 * are using an Ajax or JS data source for the table. This option, when set to
-		 * true, will cause DataTables to defer the creation of the table elements for
-		 * each row until they are needed for a draw - saving a significant amount of
-		 * time.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "sAjaxSource": "sources/arrays.txt",
-		 *        "bDeferRender": true
-		 *      } );
-		 *    } );
-		 */
-		"bDeferRender": false,
-	
-	
-		/**
-		 * Replace a DataTable which matches the given selector and replace it with 
-		 * one which has the properties of the new initialisation object passed. If no
-		 * table matches the selector, then the new DataTable will be constructed as
-		 * per normal.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sScrollY": "200px",
-		 *        "bPaginate": false
-		 *      } );
-		 *      
-		 *      // Some time later....
-		 *      $('#example').dataTable( {
-		 *        "bFilter": false,
-		 *        "bDestroy": true
-		 *      } );
-		 *    } );
-		 */
-		"bDestroy": false,
-	
-	
-		/**
-		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
-		 * that it allows the end user to input multiple words (space separated) and
-		 * will match a row containing those words, even if not in the order that was
-		 * specified (this allow matching across multiple columns). Note that if you
-		 * wish to use filtering in DataTables this must remain 'true' - to remove the
-		 * default filtering input box and retain filtering abilities, please use
-		 * {@link DataTable.defaults.sDom}.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bFilter": false
-		 *      } );
-		 *    } );
-		 */
-		"bFilter": true,
-	
-	
-		/**
-		 * Enable or disable the table information display. This shows information 
-		 * about the data that is currently visible on the page, including information
-		 * about filtered data if that action is being performed.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bInfo": false
-		 *      } );
-		 *    } );
-		 */
-		"bInfo": true,
-	
-	
-		/**
-		 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
-		 * slightly different and additional mark-up from what DataTables has
-		 * traditionally used).
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bJQueryUI": true
-		 *      } );
-		 *    } );
-		 */
-		"bJQueryUI": false,
-	
-	
-		/**
-		 * Allows the end user to select the size of a formatted page from a select
-		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (bPaginate).
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bLengthChange": false
-		 *      } );
-		 *    } );
-		 */
-		"bLengthChange": true,
-	
-	
-		/**
-		 * Enable or disable pagination.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bPaginate": false
-		 *      } );
-		 *    } );
-		 */
-		"bPaginate": true,
-	
-	
-		/**
-		 * Enable or disable the display of a 'processing' indicator when the table is
-		 * being processed (e.g. a sort). This is particularly useful for tables with
-		 * large amounts of data where it can take a noticeable amount of time to sort
-		 * the entries.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bProcessing": true
-		 *      } );
-		 *    } );
-		 */
-		"bProcessing": false,
-	
-	
-		/**
-		 * Retrieve the DataTables object for the given selector. Note that if the
-		 * table has already been initialised, this parameter will cause DataTables
-		 * to simply return the object that has already been set up - it will not take
-		 * account of any changes you might have made to the initialisation object
-		 * passed to DataTables (setting this parameter to true is an acknowledgement
-		 * that you understand this). bDestroy can be used to reinitialise a table if
-		 * you need.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      initTable();
-		 *      tableActions();
-		 *    } );
-		 *    
-		 *    function initTable ()
-		 *    {
-		 *      return $('#example').dataTable( {
-		 *        "sScrollY": "200px",
-		 *        "bPaginate": false,
-		 *        "bRetrieve": true
-		 *      } );
-		 *    }
-		 *    
-		 *    function tableActions ()
-		 *    {
-		 *      var oTable = initTable();
-		 *      // perform API operations with oTable 
-		 *    }
-		 */
-		"bRetrieve": false,
-	
-	
-		/**
-		 * Indicate if DataTables should be allowed to set the padding / margin
-		 * etc for the scrolling header elements or not. Typically you will want
-		 * this.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bScrollAutoCss": false,
-		 *        "sScrollY": "200px"
-		 *      } );
-		 *    } );
-		 */
-		"bScrollAutoCss": true,
-	
-	
-		/**
-		 * When vertical (y) scrolling is enabled, DataTables will force the height of
-		 * the table's viewport to the given height at all times (useful for layout).
-		 * However, this can look odd when filtering data down to a small data set,
-		 * and the footer is left "floating" further down. This parameter (when
-		 * enabled) will cause DataTables to collapse the table's viewport down when
-		 * the result set will fit within the given Y height.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sScrollY": "200",
-		 *        "bScrollCollapse": true
-		 *      } );
-		 *    } );
-		 */
-		"bScrollCollapse": false,
-	
-	
-		/**
-		 * Enable infinite scrolling for DataTables (to be used in combination with
-		 * sScrollY). Infinite scrolling means that DataTables will continually load
-		 * data as a user scrolls through a table, which is very useful for large
-		 * dataset. This cannot be used with pagination, which is automatically
-		 * disabled. Note - the Scroller extra for DataTables is recommended in
-		 * in preference to this option.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bScrollInfinite": true,
-		 *        "bScrollCollapse": true,
-		 *        "sScrollY": "200px"
-		 *      } );
-		 *    } );
-		 */
-		"bScrollInfinite": false,
-	
-	
-		/**
-		 * Configure DataTables to use server-side processing. Note that the
-		 * sAjaxSource parameter must also be given in order to give DataTables a
-		 * source to obtain the required data for each draw.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Features
-		 *  @dtopt Server-side
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bServerSide": true,
-		 *        "sAjaxSource": "xhr.php"
-		 *      } );
-		 *    } );
-		 */
-		"bServerSide": false,
-	
-	
-		/**
-		 * Enable or disable sorting of columns. Sorting of individual columns can be
-		 * disabled by the "bSortable" option for each column.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bSort": false
-		 *      } );
-		 *    } );
-		 */
-		"bSort": true,
-	
-	
-		/**
-		 * Allows control over whether DataTables should use the top (true) unique
-		 * cell that is found for a single column, or the bottom (false - default).
-		 * This is useful when using complex headers.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bSortCellsTop": true
-		 *      } );
-		 *    } );
-		 */
-		"bSortCellsTop": false,
-	
-	
-		/**
-		 * Enable or disable the addition of the classes 'sorting_1', 'sorting_2' and
-		 * 'sorting_3' to the columns which are currently being sorted on. This is
-		 * presented as a feature switch as it can increase processing time (while
-		 * classes are removed and added) so for large data sets you might want to
-		 * turn this off.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bSortClasses": false
-		 *      } );
-		 *    } );
-		 */
-		"bSortClasses": true,
-	
-	
-		/**
-		 * Enable or disable state saving. When enabled a cookie will be used to save
-		 * table display information such as pagination information, display length,
-		 * filtering and sorting. As such when the end user reloads the page the
-		 * display display will match what thy had previously set up.
-		 *  @type boolean
-		 *  @default false
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true
-		 *      } );
-		 *    } );
-		 */
-		"bStateSave": false,
-	
-	
-		/**
-		 * Customise the cookie and / or the parameters being stored when using
-		 * DataTables with state saving enabled. This function is called whenever
-		 * the cookie is modified, and it expects a fully formed cookie string to be
-		 * returned. Note that the data object passed in is a Javascript object which
-		 * must be converted to a string (JSON.stringify for example).
-		 *  @type function
-		 *  @param {string} sName Name of the cookie defined by DataTables
-		 *  @param {object} oData Data to be stored in the cookie
-		 *  @param {string} sExpires Cookie expires string
-		 *  @param {string} sPath Path of the cookie to set
-		 *  @returns {string} Cookie formatted string (which should be encoded by
-		 *    using encodeURIComponent())
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function () {
-		 *      $('#example').dataTable( {
-		 *        "fnCookieCallback": function (sName, oData, sExpires, sPath) {
-		 *          // Customise oData or sName or whatever else here
-		 *          return sName + "="+JSON.stringify(oData)+"; expires=" + sExpires +"; path=" + sPath;
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnCookieCallback": null,
-	
-	
-		/**
-		 * This function is called when a TR element is created (and all TD child
-		 * elements have been inserted), or registered if using a DOM source, allowing
-		 * manipulation of the TR element (adding classes etc).
-		 *  @type function
-		 *  @param {node} nRow "TR" element for the current row
-		 *  @param {array} aData Raw data array for this row
-		 *  @param {int} iDataIndex The index of this row in aoData
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnCreatedRow": function( nRow, aData, iDataIndex ) {
-		 *          // Bold the grade for all 'A' grade browsers
-		 *          if ( aData[4] == "A" )
-		 *          {
-		 *            $('td:eq(4)', nRow).html( '<b>A</b>' );
-		 *          }
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnCreatedRow": null,
-	
-	
-		/**
-		 * This function is called on every 'draw' event, and allows you to
-		 * dynamically modify any aspect you want about the created DOM.
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnDrawCallback": function( oSettings ) {
-		 *          alert( 'DataTables has redrawn the table' );
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnDrawCallback": null,
-	
-	
-		/**
-		 * Identical to fnHeaderCallback() but for the table footer this function
-		 * allows you to modify the table footer on every 'draw' even.
-		 *  @type function
-		 *  @param {node} nFoot "TR" element for the footer
-		 *  @param {array} aData Full table data (as derived from the original HTML)
-		 *  @param {int} iStart Index for the current display starting point in the 
-		 *    display array
-		 *  @param {int} iEnd Index for the current display ending point in the 
-		 *    display array
-		 *  @param {array int} aiDisplay Index array to translate the visual position
-		 *    to the full data array
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnFooterCallback": function( nFoot, aData, iStart, iEnd, aiDisplay ) {
-		 *          nFoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+iStart;
-		 *        }
-		 *      } );
-		 *    } )
-		 */
-		"fnFooterCallback": null,
-	
-	
-		/**
-		 * When rendering large numbers in the information element for the table
-		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
-		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
-		 * rendered as "1,000,000") to help readability for the end user. This
-		 * function will override the default method DataTables uses.
-		 *  @type function
-		 *  @member
-		 *  @param {int} iIn number to be formatted
-		 *  @returns {string} formatted string for DataTables to show the number
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnFormatNumber": function ( iIn ) {
-		 *          if ( iIn &lt; 1000 ) {
-		 *            return iIn;
-		 *          } else {
-		 *            var 
-		 *              s=(iIn+""), 
-		 *              a=s.split(""), out="", 
-		 *              iLen=s.length;
-		 *            
-		 *            for ( var i=0 ; i&lt;iLen ; i++ ) {
-		 *              if ( i%3 === 0 &amp;&amp; i !== 0 ) {
-		 *                out = "'"+out;
-		 *              }
-		 *              out = a[iLen-i-1]+out;
-		 *            }
-		 *          }
-		 *          return out;
-		 *        };
-		 *      } );
-		 *    } );
-		 */
-		"fnFormatNumber": function ( iIn ) {
-			if ( iIn < 1000 )
-			{
-				// A small optimisation for what is likely to be the majority of use cases
-				return iIn;
-			}
-	
-			var s=(iIn+""), a=s.split(""), out="", iLen=s.length;
-			
-			for ( var i=0 ; i<iLen ; i++ )
-			{
-				if ( i%3 === 0 && i !== 0 )
-				{
-					out = this.oLanguage.sInfoThousands+out;
-				}
-				out = a[iLen-i-1]+out;
-			}
-			return out;
-		},
-	
-	
-		/**
-		 * This function is called on every 'draw' event, and allows you to
-		 * dynamically modify the header row. This can be used to calculate and
-		 * display useful information about the table.
-		 *  @type function
-		 *  @param {node} nHead "TR" element for the header
-		 *  @param {array} aData Full table data (as derived from the original HTML)
-		 *  @param {int} iStart Index for the current display starting point in the
-		 *    display array
-		 *  @param {int} iEnd Index for the current display ending point in the
-		 *    display array
-		 *  @param {array int} aiDisplay Index array to translate the visual position
-		 *    to the full data array
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnHeaderCallback": function( nHead, aData, iStart, iEnd, aiDisplay ) {
-		 *          nHead.getElementsByTagName('th')[0].innerHTML = "Displaying "+(iEnd-iStart)+" records";
-		 *        }
-		 *      } );
-		 *    } )
-		 */
-		"fnHeaderCallback": null,
-	
-	
-		/**
-		 * The information element can be used to convey information about the current
-		 * state of the table. Although the internationalisation options presented by
-		 * DataTables are quite capable of dealing with most customisations, there may
-		 * be times where you wish to customise the string further. This callback
-		 * allows you to do exactly that.
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @param {int} iStart Starting position in data for the draw
-		 *  @param {int} iEnd End position in data for the draw
-		 *  @param {int} iMax Total number of rows in the table (regardless of
-		 *    filtering)
-		 *  @param {int} iTotal Total number of rows in the data set, after filtering
-		 *  @param {string} sPre The string that DataTables has formatted using it's
-		 *    own rules
-		 *  @returns {string} The string to be displayed in the information element.
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $('#example').dataTable( {
-		 *      "fnInfoCallback": function( oSettings, iStart, iEnd, iMax, iTotal, sPre ) {
-		 *        return iStart +" to "+ iEnd;
-		 *      }
-		 *    } );
-		 */
-		"fnInfoCallback": null,
-	
-	
-		/**
-		 * Called when the table has been initialised. Normally DataTables will
-		 * initialise sequentially and there will be no need for this function,
-		 * however, this does not hold true when using external language information
-		 * since that is obtained using an async XHR call.
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @param {object} json The JSON object request from the server - only
-		 *    present if client-side Ajax sourced data is used
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnInitComplete": function(oSettings, json) {
-		 *          alert( 'DataTables has finished its initialisation.' );
-		 *        }
-		 *      } );
-		 *    } )
-		 */
-		"fnInitComplete": null,
-	
-	
-		/**
-		 * Called at the very start of each table draw and can be used to cancel the
-		 * draw by returning false, any other return (including undefined) results in
-		 * the full draw occurring).
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @returns {boolean} False will cancel the draw, anything else (including no
-		 *    return) will allow it to complete.
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnPreDrawCallback": function( oSettings ) {
-		 *          if ( $('#test').val() == 1 ) {
-		 *            return false;
-		 *          }
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnPreDrawCallback": null,
-	
-	
-		/**
-		 * This function allows you to 'post process' each row after it have been
-		 * generated for each table draw, but before it is rendered on screen. This
-		 * function might be used for setting the row class name etc.
-		 *  @type function
-		 *  @param {node} nRow "TR" element for the current row
-		 *  @param {array} aData Raw data array for this row
-		 *  @param {int} iDisplayIndex The display index for the current table draw
-		 *  @param {int} iDisplayIndexFull The index of the data in the full list of
-		 *    rows (after filtering)
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
-		 *          // Bold the grade for all 'A' grade browsers
-		 *          if ( aData[4] == "A" )
-		 *          {
-		 *            $('td:eq(4)', nRow).html( '<b>A</b>' );
-		 *          }
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnRowCallback": null,
-	
-	
-		/**
-		 * This parameter allows you to override the default function which obtains
-		 * the data from the server ($.getJSON) so something more suitable for your
-		 * application. For example you could use POST data, or pull information from
-		 * a Gears or AIR database.
-		 *  @type function
-		 *  @member
-		 *  @param {string} sSource HTTP source to obtain the data from (sAjaxSource)
-		 *  @param {array} aoData A key/value pair object containing the data to send
-		 *    to the server
-		 *  @param {function} fnCallback to be called on completion of the data get
-		 *    process that will draw the data on the page.
-		 *  @param {object} oSettings DataTables settings object
-		 *  @dtopt Callbacks
-		 *  @dtopt Server-side
-		 * 
-		 *  @example
-		 *    // POST data to server
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bProcessing": true,
-		 *        "bServerSide": true,
-		 *        "sAjaxSource": "xhr.php",
-		 *        "fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
-		 *          oSettings.jqXHR = $.ajax( {
-		 *            "dataType": 'json', 
-		 *            "type": "POST", 
-		 *            "url": sSource, 
-		 *            "data": aoData, 
-		 *            "success": fnCallback
-		 *          } );
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnServerData": function ( sUrl, aoData, fnCallback, oSettings ) {
-			oSettings.jqXHR = $.ajax( {
-				"url":  sUrl,
-				"data": aoData,
-				"success": function (json) {
-					if ( json.sError ) {
-						oSettings.oApi._fnLog( oSettings, 0, json.sError );
-					}
-					
-					$(oSettings.oInstance).trigger('xhr', [oSettings, json]);
-					fnCallback( json );
-				},
-				"dataType": "json",
-				"cache": false,
-				"type": oSettings.sServerMethod,
-				"error": function (xhr, error, thrown) {
-					if ( error == "parsererror" ) {
-						oSettings.oApi._fnLog( oSettings, 0, "DataTables warning: JSON data from "+
-							"server could not be parsed. This is caused by a JSON formatting error." );
-					}
-				}
-			} );
-		},
-	
-	
-		/**
-		 * It is often useful to send extra data to the server when making an Ajax
-		 * request - for example custom filtering information, and this callback
-		 * function makes it trivial to send extra information to the server. The
-		 * passed in parameter is the data set that has been constructed by
-		 * DataTables, and you can add to this or modify it as you require.
-		 *  @type function
-		 *  @param {array} aoData Data array (array of objects which are name/value
-		 *    pairs) that has been constructed by DataTables and will be sent to the
-		 *    server. In the case of Ajax sourced data with server-side processing
-		 *    this will be an empty array, for server-side processing there will be a
-		 *    significant number of parameters!
-		 *  @returns {undefined} Ensure that you modify the aoData array passed in,
-		 *    as this is passed by reference.
-		 *  @dtopt Callbacks
-		 *  @dtopt Server-side
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bProcessing": true,
-		 *        "bServerSide": true,
-		 *        "sAjaxSource": "scripts/server_processing.php",
-		 *        "fnServerParams": function ( aoData ) {
-		 *          aoData.push( { "name": "more_data", "value": "my_value" } );
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnServerParams": null,
-	
-	
-		/**
-		 * Load the table state. With this function you can define from where, and how, the
-		 * state of a table is loaded. By default DataTables will load from its state saving
-		 * cookie, but you might wish to use local storage (HTML5) or a server-side database.
-		 *  @type function
-		 *  @member
-		 *  @param {object} oSettings DataTables settings object
-		 *  @return {object} The DataTables state object to be loaded
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true,
-		 *        "fnStateLoad": function (oSettings) {
-		 *          var o;
-		 *          
-		 *          // Send an Ajax request to the server to get the data. Note that
-		 *          // this is a synchronous request.
-		 *          $.ajax( {
-		 *            "url": "/state_load",
-		 *            "async": false,
-		 *            "dataType": "json",
-		 *            "success": function (json) {
-		 *              o = json;
-		 *            }
-		 *          } );
-		 *          
-		 *          return o;
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnStateLoad": function ( oSettings ) {
-			var sData = this.oApi._fnReadCookie( oSettings.sCookiePrefix+oSettings.sInstance );
-			var oData;
-	
-			try {
-				oData = (typeof $.parseJSON === 'function') ? 
-					$.parseJSON(sData) : eval( '('+sData+')' );
-			} catch (e) {
-				oData = null;
-			}
-	
-			return oData;
-		},
-	
-	
-		/**
-		 * Callback which allows modification of the saved state prior to loading that state.
-		 * This callback is called when the table is loading state from the stored data, but
-		 * prior to the settings object being modified by the saved state. Note that for 
-		 * plug-in authors, you should use the 'stateLoadParams' event to load parameters for 
-		 * a plug-in.
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @param {object} oData The state object that is to be loaded
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    // Remove a saved filter, so filtering is never loaded
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true,
-		 *        "fnStateLoadParams": function (oSettings, oData) {
-		 *          oData.oSearch.sSearch = "";
-		 *        }
-		 *      } );
-		 *    } );
-		 * 
-		 *  @example
-		 *    // Disallow state loading by returning false
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true,
-		 *        "fnStateLoadParams": function (oSettings, oData) {
-		 *          return false;
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnStateLoadParams": null,
-	
-	
-		/**
-		 * Callback that is called when the state has been loaded from the state saving method
-		 * and the DataTables settings object has been modified as a result of the loaded state.
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @param {object} oData The state object that was loaded
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    // Show an alert with the filtering value that was saved
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true,
-		 *        "fnStateLoaded": function (oSettings, oData) {
-		 *          alert( 'Saved filter was: '+oData.oSearch.sSearch );
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnStateLoaded": null,
-	
-	
-		/**
-		 * Save the table state. This function allows you to define where and how the state
-		 * information for the table is stored - by default it will use a cookie, but you
-		 * might want to use local storage (HTML5) or a server-side database.
-		 *  @type function
-		 *  @member
-		 *  @param {object} oSettings DataTables settings object
-		 *  @param {object} oData The state object to be saved
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true,
-		 *        "fnStateSave": function (oSettings, oData) {
-		 *          // Send an Ajax request to the server with the state object
-		 *          $.ajax( {
-		 *            "url": "/state_save",
-		 *            "data": oData,
-		 *            "dataType": "json",
-		 *            "method": "POST"
-		 *            "success": function () {}
-		 *          } );
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnStateSave": function ( oSettings, oData ) {
-			this.oApi._fnCreateCookie( 
-				oSettings.sCookiePrefix+oSettings.sInstance, 
-				this.oApi._fnJsonString(oData), 
-				oSettings.iCookieDuration, 
-				oSettings.sCookiePrefix, 
-				oSettings.fnCookieCallback
-			);
-		},
-	
-	
-		/**
-		 * Callback which allows modification of the state to be saved. Called when the table 
-		 * has changed state a new state save is required. This method allows modification of
-		 * the state saving object prior to actually doing the save, including addition or 
-		 * other state properties or modification. Note that for plug-in authors, you should 
-		 * use the 'stateSaveParams' event to save parameters for a plug-in.
-		 *  @type function
-		 *  @param {object} oSettings DataTables settings object
-		 *  @param {object} oData The state object to be saved
-		 *  @dtopt Callbacks
-		 * 
-		 *  @example
-		 *    // Remove a saved filter, so filtering is never saved
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bStateSave": true,
-		 *        "fnStateSaveParams": function (oSettings, oData) {
-		 *          oData.oSearch.sSearch = "";
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"fnStateSaveParams": null,
-	
-	
-		/**
-		 * Duration of the cookie which is used for storing session information. This
-		 * value is given in seconds.
-		 *  @type int
-		 *  @default 7200 <i>(2 hours)</i>
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "iCookieDuration": 60*60*24; // 1 day
-		 *      } );
-		 *    } )
-		 */
-		"iCookieDuration": 7200,
-	
-	
-		/**
-		 * When enabled DataTables will not make a request to the server for the first
-		 * page draw - rather it will use the data already on the page (no sorting etc
-		 * will be applied to it), thus saving on an XHR at load time. iDeferLoading
-		 * is used to indicate that deferred loading is required, but it is also used
-		 * to tell DataTables how many records there are in the full table (allowing
-		 * the information element and pagination to be displayed correctly). In the case
-		 * where a filtering is applied to the table on initial load, this can be
-		 * indicated by giving the parameter as an array, where the first element is
-		 * the number of records available after filtering and the second element is the
-		 * number of records without filtering (allowing the table information element
-		 * to be shown correctly).
-		 *  @type int | array
-		 *  @default null
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    // 57 records available in the table, no filtering applied
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bServerSide": true,
-		 *        "sAjaxSource": "scripts/server_processing.php",
-		 *        "iDeferLoading": 57
-		 *      } );
-		 *    } );
-		 * 
-		 *  @example
-		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bServerSide": true,
-		 *        "sAjaxSource": "scripts/server_processing.php",
-		 *        "iDeferLoading": [ 57, 100 ],
-		 *        "oSearch": {
-		 *          "sSearch": "my_filter"
-		 *        }
-		 *      } );
-		 *    } );
-		 */
-		"iDeferLoading": null,
-	
-	
-		/**
-		 * Number of rows to display on a single page when using pagination. If
-		 * feature enabled (bLengthChange) then the end user will be able to override
-		 * this to a custom setting using a pop-up menu.
-		 *  @type int
-		 *  @default 10
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "iDisplayLength": 50
-		 *      } );
-		 *    } )
-		 */
-		"iDisplayLength": 10,
-	
-	
-		/**
-		 * Define the starting point for data display when using DataTables with
-		 * pagination. Note that this parameter is the number of records, rather than
-		 * the page number, so if you have 10 records per page and want to start on
-		 * the third page, it should be "20".
-		 *  @type int
-		 *  @default 0
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "iDisplayStart": 20
-		 *      } );
-		 *    } )
-		 */
-		"iDisplayStart": 0,
-	
-	
-		/**
-		 * The scroll gap is the amount of scrolling that is left to go before
-		 * DataTables will load the next 'page' of data automatically. You typically
-		 * want a gap which is big enough that the scrolling will be smooth for the
-		 * user, while not so large that it will load more data than need.
-		 *  @type int
-		 *  @default 100
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bScrollInfinite": true,
-		 *        "bScrollCollapse": true,
-		 *        "sScrollY": "200px",
-		 *        "iScrollLoadGap": 50
-		 *      } );
-		 *    } );
-		 */
-		"iScrollLoadGap": 100,
-	
-	
-		/**
-		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
-		 * and filtering) by adding a tabindex attribute to the required elements. This
-		 * allows you to tab through the controls and press the enter key to activate them.
-		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
-		 * You can overrule this using this parameter if you wish. Use a value of -1 to
-		 * disable built-in keyboard navigation.
-		 *  @type int
-		 *  @default 0
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "iTabIndex": 1
-		 *      } );
-		 *    } );
-		 */
-		"iTabIndex": 0,
-	
-	
-		/**
-		 * All strings that DataTables uses in the user interface that it creates
-		 * are defined in this object, allowing you to modified them individually or
-		 * completely replace them all as required.
-		 *  @namespace
-		 */
-		"oLanguage": {
-			/**
-			 * Strings that are used for WAI-ARIA labels and controls only (these are not
-			 * actually visible on the page, but will be read by screenreaders, and thus
-			 * must be internationalised as well).
-			 *  @namespace
-			 */
-			"oAria": {
-				/**
-				 * ARIA label that is added to the table headers when the column may be
-				 * sorted ascending by activing the column (click or return when focused).
-				 * Note that the column header is prefixed to this string.
-				 *  @type string
-				 *  @default : activate to sort column ascending
-				 *  @dtopt Language
-				 * 
-				 *  @example
-				 *    $(document).ready( function() {
-				 *      $('#example').dataTable( {
-				 *        "oLanguage": {
-				 *          "oAria": {
-				 *            "sSortAscending": " - click/return to sort ascending"
-				 *          }
-				 *        }
-				 *      } );
-				 *    } );
-				 */
-				"sSortAscending": ": activate to sort column ascending",
-	
-				/**
-				 * ARIA label that is added to the table headers when the column may be
-				 * sorted descending by activing the column (click or return when focused).
-				 * Note that the column header is prefixed to this string.
-				 *  @type string
-				 *  @default : activate to sort column ascending
-				 *  @dtopt Language
-				 * 
-				 *  @example
-				 *    $(document).ready( function() {
-				 *      $('#example').dataTable( {
-				 *        "oLanguage": {
-				 *          "oAria": {
-				 *            "sSortDescending": " - click/return to sort descending"
-				 *          }
-				 *        }
-				 *      } );
-				 *    } );
-				 */
-				"sSortDescending": ": activate to sort column descending"
-			},
-	
-			/**
-			 * Pagination string used by DataTables for the two built-in pagination
-			 * control types ("two_button" and "full_numbers")
-			 *  @namespace
-			 */
-			"oPaginate": {
-				/**
-				 * Text to use when using the 'full_numbers' type of pagination for the
-				 * button to take the user to the first page.
-				 *  @type string
-				 *  @default First
-				 *  @dtopt Language
-				 * 
-				 *  @example
-				 *    $(document).ready( function() {
-				 *      $('#example').dataTable( {
-				 *        "oLanguage": {
-				 *          "oPaginate": {
-				 *            "sFirst": "First page"
-				 *          }
-				 *        }
-				 *      } );
-				 *    } );
-				 */
-				"sFirst": "First",
-			
-			
-				/**
-				 * Text to use when using the 'full_numbers' type of pagination for the
-				 * button to take the user to the last page.
-				 *  @type string
-				 *  @default Last
-				 *  @dtopt Language
-				 * 
-				 *  @example
-				 *    $(document).ready( function() {
-				 *      $('#example').dataTable( {
-				 *        "oLanguage": {
-				 *          "oPaginate": {
-				 *            "sLast": "Last page"
-				 *          }
-				 *        }
-				 *      } );
-				 *    } );
-				 */
-				"sLast": "Last",
-			
-			
-				/**
-				 * Text to use for the 'next' pagination button (to take the user to the 
-				 * next page).
-				 *  @type string
-				 *  @default Next
-				 *  @dtopt Language
-				 * 
-				 *  @example
-				 *    $(document).ready( function() {
-				 *      $('#example').dataTable( {
-				 *        "oLanguage": {
-				 *          "oPaginate": {
-				 *            "sNext": "Next page"
-				 *          }
-				 *        }
-				 *      } );
-				 *    } );
-				 */
-				"sNext": "Next",
-			
-			
-				/**
-				 * Text to use for the 'previous' pagination button (to take the user to  
-				 * the previous page).
-				 *  @type string
-				 *  @default Previous
-				 *  @dtopt Language
-				 * 
-				 *  @example
-				 *    $(document).ready( function() {
-				 *      $('#example').dataTable( {
-				 *        "oLanguage": {
-				 *          "oPaginate": {
-				 *            "sPrevious": "Previous page"
-				 *          }
-				 *        }
-				 *      } );
-				 *    } );
-				 */
-				"sPrevious": "Previous"
-			},
-		
-			/**
-			 * This string is shown in preference to sZeroRecords when the table is
-			 * empty of data (regardless of filtering). Note that this is an optional
-			 * parameter - if it is not given, the value of sZeroRecords will be used
-			 * instead (either the default or given value).
-			 *  @type string
-			 *  @default No data available in table
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sEmptyTable": "No data available in table"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sEmptyTable": "No data available in table",
-		
-		
-			/**
-			 * This string gives information to the end user about the information that 
-			 * is current on display on the page. The _START_, _END_ and _TOTAL_ 
-			 * variables are all dynamically replaced as the table display updates, and 
-			 * can be freely moved or removed as the language requirements change.
-			 *  @type string
-			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sInfo": "Got a total of _TOTAL_ entries to show (_START_ to _END_)"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
-		
-		
-			/**
-			 * Display information string for when the table is empty. Typically the 
-			 * format of this string should match sInfo.
-			 *  @type string
-			 *  @default Showing 0 to 0 of 0 entries
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sInfoEmpty": "No entries to show"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
-		
-		
-			/**
-			 * When a user filters the information in a table, this string is appended 
-			 * to the information (sInfo) to give an idea of how strong the filtering 
-			 * is. The variable _MAX_ is dynamically updated.
-			 *  @type string
-			 *  @default (filtered from _MAX_ total entries)
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sInfoFiltered": " - filtering from _MAX_ records"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sInfoFiltered": "(filtered from _MAX_ total entries)",
-		
-		
-			/**
-			 * If can be useful to append extra information to the info string at times,
-			 * and this variable does exactly that. This information will be appended to
-			 * the sInfo (sInfoEmpty and sInfoFiltered in whatever combination they are
-			 * being used) at all times.
-			 *  @type string
-			 *  @default <i>Empty string</i>
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sInfoPostFix": "All records shown are derived from real information."
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sInfoPostFix": "",
-		
-		
-			/**
-			 * DataTables has a build in number formatter (fnFormatNumber) which is used
-			 * to format large numbers that are used in the table information. By
-			 * default a comma is used, but this can be trivially changed to any
-			 * character you wish with this parameter.
-			 *  @type string
-			 *  @default ,
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sInfoThousands": "'"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sInfoThousands": ",",
-		
-		
-			/**
-			 * Detail the action that will be taken when the drop down menu for the
-			 * pagination length option is changed. The '_MENU_' variable is replaced
-			 * with a default select list of 10, 25, 50 and 100, and can be replaced
-			 * with a custom select box if required.
-			 *  @type string
-			 *  @default Show _MENU_ entries
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    // Language change only
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sLengthMenu": "Display _MENU_ records"
-			 *        }
-			 *      } );
-			 *    } );
-			 *    
-			 *  @example
-			 *    // Language and options change
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sLengthMenu": 'Display <select>'+
-			 *            '<option value="10">10</option>'+
-			 *            '<option value="20">20</option>'+
-			 *            '<option value="30">30</option>'+
-			 *            '<option value="40">40</option>'+
-			 *            '<option value="50">50</option>'+
-			 *            '<option value="-1">All</option>'+
-			 *            '</select> records'
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sLengthMenu": "Show _MENU_ entries",
-		
-		
-			/**
-			 * When using Ajax sourced data and during the first draw when DataTables is
-			 * gathering the data, this message is shown in an empty row in the table to
-			 * indicate to the end user the the data is being loaded. Note that this
-			 * parameter is not used when loading data by server-side processing, just
-			 * Ajax sourced data with client-side processing.
-			 *  @type string
-			 *  @default Loading...
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sLoadingRecords": "Please wait - loading..."
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sLoadingRecords": "Loading...",
-		
-		
-			/**
-			 * Text which is displayed when the table is processing a user action
-			 * (usually a sort command or similar).
-			 *  @type string
-			 *  @default Processing...
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sProcessing": "DataTables is currently busy"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sProcessing": "Processing...",
-		
-		
-			/**
-			 * Details the actions that will be taken when the user types into the
-			 * filtering input text box. The variable "_INPUT_", if used in the string,
-			 * is replaced with the HTML text box for the filtering input allowing
-			 * control over where it appears in the string. If "_INPUT_" is not given
-			 * then the input box is appended to the string automatically.
-			 *  @type string
-			 *  @default Search:
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    // Input text box will be appended at the end automatically
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sSearch": "Filter records:"
-			 *        }
-			 *      } );
-			 *    } );
-			 *    
-			 *  @example
-			 *    // Specify where the filter should appear
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sSearch": "Apply filter _INPUT_ to table"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sSearch": "Search:",
-		
-		
-			/**
-			 * All of the language information can be stored in a file on the
-			 * server-side, which DataTables will look up if this parameter is passed.
-			 * It must store the URL of the language file, which is in a JSON format,
-			 * and the object has the same properties as the oLanguage object in the
-			 * initialiser object (i.e. the above parameters). Please refer to one of
-			 * the example language files to see how this works in action.
-			 *  @type string
-			 *  @default <i>Empty string - i.e. disabled</i>
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sUrl": "http://www.sprymedia.co.uk/dataTables/lang.txt"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sUrl": "",
-		
-		
-			/**
-			 * Text shown inside the table records when the is no information to be
-			 * displayed after filtering. sEmptyTable is shown when there is simply no
-			 * information in the table at all (regardless of filtering).
-			 *  @type string
-			 *  @default No matching records found
-			 *  @dtopt Language
-			 * 
-			 *  @example
-			 *    $(document).ready( function() {
-			 *      $('#example').dataTable( {
-			 *        "oLanguage": {
-			 *          "sZeroRecords": "No records to display"
-			 *        }
-			 *      } );
-			 *    } );
-			 */
-			"sZeroRecords": "No matching records found"
-		},
-	
-	
-		/**
-		 * This parameter allows you to have define the global filtering state at
-		 * initialisation time. As an object the "sSearch" parameter must be
-		 * defined, but all other parameters are optional. When "bRegex" is true,
-		 * the search string will be treated as a regular expression, when false
-		 * (default) it will be treated as a straight string. When "bSmart"
-		 * DataTables will use it's smart filtering methods (to word match at
-		 * any point in the data), when false this will not be done.
-		 *  @namespace
-		 *  @extends DataTable.models.oSearch
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "oSearch": {"sSearch": "Initial search"}
-		 *      } );
-		 *    } )
-		 */
-		"oSearch": $.extend( {}, DataTable.models.oSearch ),
-	
-	
-		/**
-		 * By default DataTables will look for the property 'aaData' when obtaining
-		 * data from an Ajax source or for server-side processing - this parameter
-		 * allows that property to be changed. You can use Javascript dotted object
-		 * notation to get a data source for multiple levels of nesting.
-		 *  @type string
-		 *  @default aaData
-		 *  @dtopt Options
-		 *  @dtopt Server-side
-		 * 
-		 *  @example
-		 *    // Get data from { "data": [...] }
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "sAjaxSource": "sources/data.txt",
-		 *        "sAjaxDataProp": "data"
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Get data from { "data": { "inner": [...] } }
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "sAjaxSource": "sources/data.txt",
-		 *        "sAjaxDataProp": "data.inner"
-		 *      } );
-		 *    } );
-		 */
-		"sAjaxDataProp": "aaData",
-	
-	
-		/**
-		 * You can instruct DataTables to load data from an external source using this
-		 * parameter (use aData if you want to pass data in you already have). Simply
-		 * provide a url a JSON object can be obtained from. This object must include
-		 * the parameter 'aaData' which is the data source for the table.
-		 *  @type string
-		 *  @default null
-		 *  @dtopt Options
-		 *  @dtopt Server-side
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sAjaxSource": "http://www.sprymedia.co.uk/dataTables/json.php"
-		 *      } );
-		 *    } )
-		 */
-		"sAjaxSource": null,
-	
-	
-		/**
-		 * This parameter can be used to override the default prefix that DataTables
-		 * assigns to a cookie when state saving is enabled.
-		 *  @type string
-		 *  @default SpryMedia_DataTables_
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sCookiePrefix": "my_datatable_",
-		 *      } );
-		 *    } );
-		 */
-		"sCookiePrefix": "SpryMedia_DataTables_",
-	
-	
-		/**
-		 * This initialisation variable allows you to specify exactly where in the
-		 * DOM you want DataTables to inject the various controls it adds to the page
-		 * (for example you might want the pagination controls at the top of the
-		 * table). DIV elements (with or without a custom class) can also be added to
-		 * aid styling. The follow syntax is used:
-		 *   <ul>
-		 *     <li>The following options are allowed:	
-		 *       <ul>
-		 *         <li>'l' - Length changing</li
-		 *         <li>'f' - Filtering input</li>
-		 *         <li>'t' - The table!</li>
-		 *         <li>'i' - Information</li>
-		 *         <li>'p' - Pagination</li>
-		 *         <li>'r' - pRocessing</li>
-		 *       </ul>
-		 *     </li>
-		 *     <li>The following constants are allowed:
-		 *       <ul>
-		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
-		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
-		 *       </ul>
-		 *     </li>
-		 *     <li>The following syntax is expected:
-		 *       <ul>
-		 *         <li>'&lt;' and '&gt;' - div elements</li>
-		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
-		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
-		 *       </ul>
-		 *     </li>
-		 *     <li>Examples:
-		 *       <ul>
-		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
-		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
-		 *       </ul>
-		 *     </li>
-		 *   </ul>
-		 *  @type string
-		 *  @default lfrtip <i>(when bJQueryUI is false)</i> <b>or</b> 
-		 *    <"H"lfr>t<"F"ip> <i>(when bJQueryUI is true)</i>
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sDom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
-		 *      } );
-		 *    } );
-		 */
-		"sDom": "lfrtip",
-	
-	
-		/**
-		 * DataTables features two different built-in pagination interaction methods
-		 * ('two_button' or 'full_numbers') which present different page controls to
-		 * the end user. Further methods can be added using the API (see below).
-		 *  @type string
-		 *  @default two_button
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sPaginationType": "full_numbers"
-		 *      } );
-		 *    } )
-		 */
-		"sPaginationType": "two_button",
-	
-	
-		/**
-		 * Enable horizontal scrolling. When a table is too wide to fit into a certain
-		 * layout, or you have a large number of columns in the table, you can enable
-		 * x-scrolling to show the table in a viewport, which can be scrolled. This
-		 * property can be any CSS unit, or a number (in which case it will be treated
-		 * as a pixel measurement).
-		 *  @type string
-		 *  @default <i>blank string - i.e. disabled</i>
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sScrollX": "100%",
-		 *        "bScrollCollapse": true
-		 *      } );
-		 *    } );
-		 */
-		"sScrollX": "",
-	
-	
-		/**
-		 * This property can be used to force a DataTable to use more width than it
-		 * might otherwise do when x-scrolling is enabled. For example if you have a
-		 * table which requires to be well spaced, this parameter is useful for
-		 * "over-sizing" the table, and thus forcing scrolling. This property can by
-		 * any CSS unit, or a number (in which case it will be treated as a pixel
-		 * measurement).
-		 *  @type string
-		 *  @default <i>blank string - i.e. disabled</i>
-		 *  @dtopt Options
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sScrollX": "100%",
-		 *        "sScrollXInner": "110%"
-		 *      } );
-		 *    } );
-		 */
-		"sScrollXInner": "",
-	
-	
-		/**
-		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
-		 * to the given height, and enable scrolling for any data which overflows the
-		 * current viewport. This can be used as an alternative to paging to display
-		 * a lot of data in a small area (although paging and scrolling can both be
-		 * enabled at the same time). This property can be any CSS unit, or a number
-		 * (in which case it will be treated as a pixel measurement).
-		 *  @type string
-		 *  @default <i>blank string - i.e. disabled</i>
-		 *  @dtopt Features
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "sScrollY": "200px",
-		 *        "bPaginate": false
-		 *      } );
-		 *    } );
-		 */
-		"sScrollY": "",
-	
-	
-		/**
-		 * Set the HTTP method that is used to make the Ajax call for server-side
-		 * processing or Ajax sourced data.
-		 *  @type string
-		 *  @default GET
-		 *  @dtopt Options
-		 *  @dtopt Server-side
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "bServerSide": true,
-		 *        "sAjaxSource": "scripts/post.php",
-		 *        "sServerMethod": "POST"
-		 *      } );
-		 *    } );
-		 */
-		"sServerMethod": "GET"
-	};
-	
-	
-	
-	/**
-	 * Column options that can be given to DataTables at initialisation time.
-	 *  @namespace
-	 */
-	DataTable.defaults.columns = {
-		/**
-		 * Allows a column's sorting to take multiple columns into account when 
-		 * doing a sort. For example first name / last name columns make sense to 
-		 * do a multi-column sort over the two columns.
-		 *  @type array
-		 *  @default null <i>Takes the value of the column index automatically</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [
-		 *          { "aDataSort": [ 0, 1 ], "aTargets": [ 0 ] },
-		 *          { "aDataSort": [ 1, 0 ], "aTargets": [ 1 ] },
-		 *          { "aDataSort": [ 2, 3, 4 ], "aTargets": [ 2 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [
-		 *          { "aDataSort": [ 0, 1 ] },
-		 *          { "aDataSort": [ 1, 0 ] },
-		 *          { "aDataSort": [ 2, 3, 4 ] },
-		 *          null,
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"aDataSort": null,
-	
-	
-		/**
-		 * You can control the default sorting direction, and even alter the behaviour
-		 * of the sort handler (i.e. only allow ascending sorting etc) using this
-		 * parameter.
-		 *  @type array
-		 *  @default [ 'asc', 'desc' ]
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [
-		 *          { "asSorting": [ "asc" ], "aTargets": [ 1 ] },
-		 *          { "asSorting": [ "desc", "asc", "asc" ], "aTargets": [ 2 ] },
-		 *          { "asSorting": [ "desc" ], "aTargets": [ 3 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [
-		 *          null,
-		 *          { "asSorting": [ "asc" ] },
-		 *          { "asSorting": [ "desc", "asc", "asc" ] },
-		 *          { "asSorting": [ "desc" ] },
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"asSorting": [ 'asc', 'desc' ],
-	
-	
-		/**
-		 * Enable or disable filtering on the data in this column.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "bSearchable": false, "aTargets": [ 0 ] }
-		 *        ] } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "bSearchable": false },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ] } );
-		 *    } );
-		 */
-		"bSearchable": true,
-	
-	
-		/**
-		 * Enable or disable sorting on this column.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "bSortable": false, "aTargets": [ 0 ] }
-		 *        ] } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "bSortable": false },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ] } );
-		 *    } );
-		 */
-		"bSortable": true,
-	
-	
-		/**
-		 * <code>Deprecated</code> When using fnRender() for a column, you may wish 
-		 * to use the original data (before rendering) for sorting and filtering 
-		 * (the default is to used the rendered data that the user can see). This 
-		 * may be useful for dates etc.
-		 * 
-		 * Please note that this option has now been deprecated and will be removed
-		 * in the next version of DataTables. Please use mRender / mData rather than
-		 * fnRender.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Columns
-		 *  @deprecated
-		 */
-		"bUseRendered": true,
-	
-	
-		/**
-		 * Enable or disable the display of this column.
-		 *  @type boolean
-		 *  @default true
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "bVisible": false, "aTargets": [ 0 ] }
-		 *        ] } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "bVisible": false },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ] } );
-		 *    } );
-		 */
-		"bVisible": true,
-		
-		
-		/**
-		 * Developer definable function that is called whenever a cell is created (Ajax source,
-		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
-		 * allowing you to modify the DOM element (add background colour for example) when the
-		 * element is available.
-		 *  @type function
-		 *  @param {element} nTd The TD node that has been created
-		 *  @param {*} sData The Data for the cell
-		 *  @param {array|object} oData The data for the whole row
-		 *  @param {int} iRow The row index for the aoData data store
-		 *  @param {int} iCol The column index for aoColumns
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ {
-		 *          "aTargets": [3],
-		 *          "fnCreatedCell": function (nTd, sData, oData, iRow, iCol) {
-		 *            if ( sData == "1.7" ) {
-		 *              $(nTd).css('color', 'blue')
-		 *            }
-		 *          }
-		 *        } ]
-		 *      });
-		 *    } );
-		 */
-		"fnCreatedCell": null,
-	
-	
-		/**
-		 * <code>Deprecated</code> Custom display function that will be called for the 
-		 * display of each cell in this column.
-		 *
-		 * Please note that this option has now been deprecated and will be removed
-		 * in the next version of DataTables. Please use mRender / mData rather than
-		 * fnRender.
-		 *  @type function
-		 *  @param {object} o Object with the following parameters:
-		 *  @param {int}    o.iDataRow The row in aoData
-		 *  @param {int}    o.iDataColumn The column in question
-		 *  @param {array}  o.aData The data for the row in question
-		 *  @param {object} o.oSettings The settings object for this DataTables instance
-		 *  @param {object} o.mDataProp The data property used for this column
-		 *  @param {*}      val The current cell value
-		 *  @returns {string} The string you which to use in the display
-		 *  @dtopt Columns
-		 *  @deprecated
-		 */
-		"fnRender": null,
-	
-	
-		/**
-		 * The column index (starting from 0!) that you wish a sort to be performed
-		 * upon when this column is selected for sorting. This can be used for sorting
-		 * on hidden columns for example.
-		 *  @type int
-		 *  @default -1 <i>Use automatically calculated column index</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "iDataSort": 1, "aTargets": [ 0 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "iDataSort": 1 },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"iDataSort": -1,
-	
-	
-		/**
-		 * This parameter has been replaced by mData in DataTables to ensure naming
-		 * consistency. mDataProp can still be used, as there is backwards compatibility
-		 * in DataTables for this option, but it is strongly recommended that you use
-		 * mData in preference to mDataProp.
-		 *  @name DataTable.defaults.columns.mDataProp
-		 */
-	
-	
-		/**
-		 * This property can be used to read data from any JSON data source property,
-		 * including deeply nested objects / properties. mData can be given in a
-		 * number of different ways which effect its behaviour:
-		 *   <ul>
-		 *     <li>integer - treated as an array index for the data source. This is the
-		 *       default that DataTables uses (incrementally increased for each column).</li>
-		 *     <li>string - read an object property from the data source. Note that you can
-		 *       use Javascript dotted notation to read deep properties / arrays from the
-		 *       data source.</li>
-		 *     <li>null - the sDefaultContent option will be used for the cell (null
-		 *       by default, so you will need to specify the default content you want -
-		 *       typically an empty string). This can be useful on generated columns such 
-		 *       as edit / delete action columns.</li>
-		 *     <li>function - the function given will be executed whenever DataTables 
-		 *       needs to set or get the data for a cell in the column. The function 
-		 *       takes three parameters:
-		 *       <ul>
-		 *         <li>{array|object} The data source for the row</li>
-		 *         <li>{string} The type call data requested - this will be 'set' when
-		 *           setting data or 'filter', 'display', 'type', 'sort' or undefined when 
-		 *           gathering data. Note that when <i>undefined</i> is given for the type
-		 *           DataTables expects to get the raw data for the object back</li>
-		 *         <li>{*} Data to set when the second parameter is 'set'.</li>
-		 *       </ul>
-		 *       The return value from the function is not required when 'set' is the type
-		 *       of call, but otherwise the return is what will be used for the data
-		 *       requested.</li>
-		 *    </ul>
-		 *
-		 * Note that prior to DataTables 1.9.2 mData was called mDataProp. The name change
-		 * reflects the flexibility of this property and is consistent with the naming of
-		 * mRender. If 'mDataProp' is given, then it will still be used by DataTables, as
-		 * it automatically maps the old name to the new if required.
-		 *  @type string|int|function|null
-		 *  @default null <i>Use automatically calculated column index</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Read table data from objects
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "sAjaxSource": "sources/deep.txt",
-		 *        "aoColumns": [
-		 *          { "mData": "engine" },
-		 *          { "mData": "browser" },
-		 *          { "mData": "platform.inner" },
-		 *          { "mData": "platform.details.0" },
-		 *          { "mData": "platform.details.1" }
-		 *        ]
-		 *      } );
-		 *    } );
-		 * 
-		 *  @example
-		 *    // Using mData as a function to provide different information for
-		 *    // sorting, filtering and display. In this case, currency (price)
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "aoColumnDefs": [ {
-		 *          "aTargets": [ 0 ],
-		 *          "mData": function ( source, type, val ) {
-		 *            if (type === 'set') {
-		 *              source.price = val;
-		 *              // Store the computed dislay and filter values for efficiency
-		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
-		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
-		 *              return;
-		 *            }
-		 *            else if (type === 'display') {
-		 *              return source.price_display;
-		 *            }
-		 *            else if (type === 'filter') {
-		 *              return source.price_filter;
-		 *            }
-		 *            // 'sort', 'type' and undefined all just use the integer
-		 *            return source.price;
-		 *          }
-		 *        } ]
-		 *      } );
-		 *    } );
-		 */
-		"mData": null,
-	
-	
-		/**
-		 * This property is the rendering partner to mData and it is suggested that
-		 * when you want to manipulate data for display (including filtering, sorting etc)
-		 * but not altering the underlying data for the table, use this property. mData
-		 * can actually do everything this property can and more, but this parameter is
-		 * easier to use since there is no 'set' option. Like mData is can be given
-		 * in a number of different ways to effect its behaviour, with the addition of 
-		 * supporting array syntax for easy outputting of arrays (including arrays of
-		 * objects):
-		 *   <ul>
-		 *     <li>integer - treated as an array index for the data source. This is the
-		 *       default that DataTables uses (incrementally increased for each column).</li>
-		 *     <li>string - read an object property from the data source. Note that you can
-		 *       use Javascript dotted notation to read deep properties / arrays from the
-		 *       data source and also array brackets to indicate that the data reader should
-		 *       loop over the data source array. When characters are given between the array
-		 *       brackets, these characters are used to join the data source array together.
-		 *       For example: "accounts[, ].name" would result in a comma separated list with
-		 *       the 'name' value from the 'accounts' array of objects.</li>
-		 *     <li>function - the function given will be executed whenever DataTables 
-		 *       needs to set or get the data for a cell in the column. The function 
-		 *       takes three parameters:
-		 *       <ul>
-		 *         <li>{array|object} The data source for the row (based on mData)</li>
-		 *         <li>{string} The type call data requested - this will be 'filter', 'display', 
-		 *           'type' or 'sort'.</li>
-		 *         <li>{array|object} The full data source for the row (not based on mData)</li>
-		 *       </ul>
-		 *       The return value from the function is what will be used for the data
-		 *       requested.</li>
-		 *    </ul>
-		 *  @type string|int|function|null
-		 *  @default null <i>Use mData</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Create a comma separated list from an array of objects
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "sAjaxSource": "sources/deep.txt",
-		 *        "aoColumns": [
-		 *          { "mData": "engine" },
-		 *          { "mData": "browser" },
-		 *          {
-		 *            "mData": "platform",
-		 *            "mRender": "[, ].name"
-		 *          }
-		 *        ]
-		 *      } );
-		 *    } );
-		 * 
-		 *  @example
-		 *    // Use as a function to create a link from the data source
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "aoColumnDefs": [
-		 *        {
-		 *          "aTargets": [ 0 ],
-		 *          "mData": "download_link",
-		 *          "mRender": function ( data, type, full ) {
-		 *            return '<a href="'+data+'">Download</a>';
-		 *          }
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"mRender": null,
-	
-	
-		/**
-		 * Change the cell type created for the column - either TD cells or TH cells. This
-		 * can be useful as TH cells have semantic meaning in the table body, allowing them
-		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
-		 *  @type string
-		 *  @default td
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Make the first column use TH cells
-		 *    $(document).ready( function() {
-		 *      var oTable = $('#example').dataTable( {
-		 *        "aoColumnDefs": [ {
-		 *          "aTargets": [ 0 ],
-		 *          "sCellType": "th"
-		 *        } ]
-		 *      } );
-		 *    } );
-		 */
-		"sCellType": "td",
-	
-	
-		/**
-		 * Class to give to each cell in this column.
-		 *  @type string
-		 *  @default <i>Empty string</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "sClass": "my_class", "aTargets": [ 0 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "sClass": "my_class" },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sClass": "",
-		
-		/**
-		 * When DataTables calculates the column widths to assign to each column,
-		 * it finds the longest string in each column and then constructs a
-		 * temporary table and reads the widths from that. The problem with this
-		 * is that "mmm" is much wider then "iiii", but the latter is a longer 
-		 * string - thus the calculation can go wrong (doing it properly and putting
-		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
-		 * a "work around" we provide this option. It will append its value to the
-		 * text that is found to be the longest string for the column - i.e. padding.
-		 * Generally you shouldn't need this, and it is not documented on the 
-		 * general DataTables.net documentation
-		 *  @type string
-		 *  @default <i>Empty string<i>
-		 *  @dtopt Columns
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          {
-		 *            "sContentPadding": "mmm"
-		 *          }
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sContentPadding": "",
-	
-	
-		/**
-		 * Allows a default value to be given for a column's data, and will be used
-		 * whenever a null data source is encountered (this can be because mData
-		 * is set to null, or because the data source itself is null).
-		 *  @type string
-		 *  @default null
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          {
-		 *            "mData": null,
-		 *            "sDefaultContent": "Edit",
-		 *            "aTargets": [ -1 ]
-		 *          }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          {
-		 *            "mData": null,
-		 *            "sDefaultContent": "Edit"
-		 *          }
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sDefaultContent": null,
-	
-	
-		/**
-		 * This parameter is only used in DataTables' server-side processing. It can
-		 * be exceptionally useful to know what columns are being displayed on the
-		 * client side, and to map these to database fields. When defined, the names
-		 * also allow DataTables to reorder information from the server if it comes
-		 * back in an unexpected order (i.e. if you switch your columns around on the
-		 * client-side, your server-side code does not also need updating).
-		 *  @type string
-		 *  @default <i>Empty string</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "sName": "engine", "aTargets": [ 0 ] },
-		 *          { "sName": "browser", "aTargets": [ 1 ] },
-		 *          { "sName": "platform", "aTargets": [ 2 ] },
-		 *          { "sName": "version", "aTargets": [ 3 ] },
-		 *          { "sName": "grade", "aTargets": [ 4 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "sName": "engine" },
-		 *          { "sName": "browser" },
-		 *          { "sName": "platform" },
-		 *          { "sName": "version" },
-		 *          { "sName": "grade" }
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sName": "",
-	
-	
-		/**
-		 * Defines a data source type for the sorting which can be used to read
-		 * real-time information from the table (updating the internally cached
-		 * version) prior to sorting. This allows sorting to occur on user editable
-		 * elements such as form inputs.
-		 *  @type string
-		 *  @default std
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [
-		 *          { "sSortDataType": "dom-text", "aTargets": [ 2, 3 ] },
-		 *          { "sType": "numeric", "aTargets": [ 3 ] },
-		 *          { "sSortDataType": "dom-select", "aTargets": [ 4 ] },
-		 *          { "sSortDataType": "dom-checkbox", "aTargets": [ 5 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [
-		 *          null,
-		 *          null,
-		 *          { "sSortDataType": "dom-text" },
-		 *          { "sSortDataType": "dom-text", "sType": "numeric" },
-		 *          { "sSortDataType": "dom-select" },
-		 *          { "sSortDataType": "dom-checkbox" }
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sSortDataType": "std",
-	
-	
-		/**
-		 * The title of this column.
-		 *  @type string
-		 *  @default null <i>Derived from the 'TH' value for this column in the 
-		 *    original HTML table.</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "sTitle": "My column title", "aTargets": [ 0 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "sTitle": "My column title" },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sTitle": null,
-	
-	
-		/**
-		 * The type allows you to specify how the data for this column will be sorted.
-		 * Four types (string, numeric, date and html (which will strip HTML tags
-		 * before sorting)) are currently available. Note that only date formats
-		 * understood by Javascript's Date() object will be accepted as type date. For
-		 * example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 'numeric',
-		 * 'date' or 'html' (by default). Further types can be adding through
-		 * plug-ins.
-		 *  @type string
-		 *  @default null <i>Auto-detected from raw data</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "sType": "html", "aTargets": [ 0 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "sType": "html" },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sType": null,
-	
-	
-		/**
-		 * Defining the width of the column, this parameter may take any CSS value
-		 * (3em, 20px etc). DataTables apples 'smart' widths to columns which have not
-		 * been given a specific width through this interface ensuring that the table
-		 * remains readable.
-		 *  @type string
-		 *  @default null <i>Automatic</i>
-		 *  @dtopt Columns
-		 * 
-		 *  @example
-		 *    // Using aoColumnDefs
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumnDefs": [ 
-		 *          { "sWidth": "20%", "aTargets": [ 0 ] }
-		 *        ]
-		 *      } );
-		 *    } );
-		 *    
-		 *  @example
-		 *    // Using aoColumns
-		 *    $(document).ready( function() {
-		 *      $('#example').dataTable( {
-		 *        "aoColumns": [ 
-		 *          { "sWidth": "20%" },
-		 *          null,
-		 *          null,
-		 *          null,
-		 *          null
-		 *        ]
-		 *      } );
-		 *    } );
-		 */
-		"sWidth": null
-	};
-	
-	
-	
-	/**
-	 * DataTables settings object - this holds all the information needed for a
-	 * given table, including configuration, data and current application of the
-	 * table options. DataTables does not have a single instance for each DataTable
-	 * with the settings attached to that instance, but rather instances of the
-	 * DataTable "class" are created on-the-fly as needed (typically by a 
-	 * $().dataTable() call) and the settings object is then applied to that
-	 * instance.
-	 * 
-	 * Note that this object is related to {@link DataTable.defaults} but this 
-	 * one is the internal data store for DataTables's cache of columns. It should
-	 * NOT be manipulated outside of DataTables. Any configuration should be done
-	 * through the initialisation options.
-	 *  @namespace
-	 *  @todo Really should attach the settings object to individual instances so we
-	 *    don't need to create new instances on each $().dataTable() call (if the
-	 *    table already exists). It would also save passing oSettings around and
-	 *    into every single function. However, this is a very significant 
-	 *    architecture change for DataTables and will almost certainly break
-	 *    backwards compatibility with older installations. This is something that
-	 *    will be done in 2.0.
-	 */
-	DataTable.models.oSettings = {
-		/**
-		 * Primary features of DataTables and their enablement state.
-		 *  @namespace
-		 */
-		"oFeatures": {
-			
-			/**
-			 * Flag to say if DataTables should automatically try to calculate the
-			 * optimum table and columns widths (true) or not (false).
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bAutoWidth": null,
-	
-			/**
-			 * Delay the creation of TR and TD elements until they are actually
-			 * needed by a driven page draw. This can give a significant speed
-			 * increase for Ajax source and Javascript source data, but makes no
-			 * difference at all fro DOM and server-side processing tables.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bDeferRender": null,
-			
-			/**
-			 * Enable filtering on the table or not. Note that if this is disabled
-			 * then there is no filtering at all on the table, including fnFilter.
-			 * To just remove the filtering input use sDom and remove the 'f' option.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bFilter": null,
-			
-			/**
-			 * Table information element (the 'Showing x of y records' div) enable
-			 * flag.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bInfo": null,
-			
-			/**
-			 * Present a user control allowing the end user to change the page size
-			 * when pagination is enabled.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bLengthChange": null,
-	
-			/**
-			 * Pagination enabled or not. Note that if this is disabled then length
-			 * changing must also be disabled.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bPaginate": null,
-			
-			/**
-			 * Processing indicator enable flag whenever DataTables is enacting a
-			 * user request - typically an Ajax request for server-side processing.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bProcessing": null,
-			
-			/**
-			 * Server-side processing enabled flag - when enabled DataTables will
-			 * get all data from the server for every draw - there is no filtering,
-			 * sorting or paging done on the client-side.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bServerSide": null,
-			
-			/**
-			 * Sorting enablement flag.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bSort": null,
-			
-			/**
-			 * Apply a class to the columns which are being sorted to provide a
-			 * visual highlight or not. This can slow things down when enabled since
-			 * there is a lot of DOM interaction.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bSortClasses": null,
-			
-			/**
-			 * State saving enablement flag.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bStateSave": null
-		},
-		
-	
-		/**
-		 * Scrolling settings for a table.
-		 *  @namespace
-		 */
-		"oScroll": {
-			/**
-			 * Indicate if DataTables should be allowed to set the padding / margin
-			 * etc for the scrolling header elements or not. Typically you will want
-			 * this.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bAutoCss": null,
-			
-			/**
-			 * When the table is shorter in height than sScrollY, collapse the
-			 * table container down to the height of the table (when true).
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bCollapse": null,
-			
-			/**
-			 * Infinite scrolling enablement flag. Now deprecated in favour of
-			 * using the Scroller plug-in.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type boolean
-			 */
-			"bInfinite": null,
-			
-			/**
-			 * Width of the scrollbar for the web-browser's platform. Calculated
-			 * during table initialisation.
-			 *  @type int
-			 *  @default 0
-			 */
-			"iBarWidth": 0,
-			
-			/**
-			 * Space (in pixels) between the bottom of the scrolling container and 
-			 * the bottom of the scrolling viewport before the next page is loaded
-			 * when using infinite scrolling.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type int
-			 */
-			"iLoadGap": null,
-			
-			/**
-			 * Viewport width for horizontal scrolling. Horizontal scrolling is 
-			 * disabled if an empty string.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type string
-			 */
-			"sX": null,
-			
-			/**
-			 * Width to expand the table to when using x-scrolling. Typically you
-			 * should not need to use this.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type string
-			 *  @deprecated
-			 */
-			"sXInner": null,
-			
-			/**
-			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
-			 * if an empty string.
-			 * Note that this parameter will be set by the initialisation routine. To
-			 * set a default use {@link DataTable.defaults}.
-			 *  @type string
-			 */
-			"sY": null
-		},
-		
-		/**
-		 * Language information for the table.
-		 *  @namespace
-		 *  @extends DataTable.defaults.oLanguage
-		 */
-		"oLanguage": {
-			/**
-			 * Information callback function. See 
-			 * {@link DataTable.defaults.fnInfoCallback}
-			 *  @type function
-			 *  @default null
-			 */
-			"fnInfoCallback": null
-		},
-		
-		/**
-		 * Browser support parameters
-		 *  @namespace
-		 */
-		"oBrowser": {
-			/**
-			 * Indicate if the browser incorrectly calculates width:100% inside a
-			 * scrolling element (IE6/7)
-			 *  @type boolean
-			 *  @default false
-			 */
-			"bScrollOversize": false
-		},
-		
-		/**
-		 * Array referencing the nodes which are used for the features. The 
-		 * parameters of this object match what is allowed by sDom - i.e.
-		 *   <ul>
-		 *     <li>'l' - Length changing</li>
-		 *     <li>'f' - Filtering input</li>
-		 *     <li>'t' - The table!</li>
-		 *     <li>'i' - Information</li>
-		 *     <li>'p' - Pagination</li>
-		 *     <li>'r' - pRocessing</li>
-		 *   </ul>
-		 *  @type array
-		 *  @default []
-		 */
-		"aanFeatures": [],
-		
-		/**
-		 * Store data information - see {@link DataTable.models.oRow} for detailed
-		 * information.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoData": [],
-		
-		/**
-		 * Array of indexes which are in the current display (after filtering etc)
-		 *  @type array
-		 *  @default []
-		 */
-		"aiDisplay": [],
-		
-		/**
-		 * Array of indexes for display - no filtering
-		 *  @type array
-		 *  @default []
-		 */
-		"aiDisplayMaster": [],
-		
-		/**
-		 * Store information about each column that is in use
-		 *  @type array
-		 *  @default []
-		 */
-		"aoColumns": [],
-		
-		/**
-		 * Store information about the table's header
-		 *  @type array
-		 *  @default []
-		 */
-		"aoHeader": [],
-		
-		/**
-		 * Store information about the table's footer
-		 *  @type array
-		 *  @default []
-		 */
-		"aoFooter": [],
-		
-		/**
-		 * Search data array for regular expression searching
-		 *  @type array
-		 *  @default []
-		 */
-		"asDataSearch": [],
-		
-		/**
-		 * Store the applied global search information in case we want to force a 
-		 * research or compare the old search to a new one.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @namespace
-		 *  @extends DataTable.models.oSearch
-		 */
-		"oPreviousSearch": {},
-		
-		/**
-		 * Store the applied search for each column - see 
-		 * {@link DataTable.models.oSearch} for the format that is used for the
-		 * filtering information for each column.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoPreSearchCols": [],
-		
-		/**
-		 * Sorting that is applied to the table. Note that the inner arrays are
-		 * used in the following manner:
-		 * <ul>
-		 *   <li>Index 0 - column number</li>
-		 *   <li>Index 1 - current sorting direction</li>
-		 *   <li>Index 2 - index of asSorting for this column</li>
-		 * </ul>
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type array
-		 *  @todo These inner arrays should really be objects
-		 */
-		"aaSorting": null,
-		
-		/**
-		 * Sorting that is always applied to the table (i.e. prefixed in front of
-		 * aaSorting).
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type array|null
-		 *  @default null
-		 */
-		"aaSortingFixed": null,
-		
-		/**
-		 * Classes to use for the striping of a table.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type array
-		 *  @default []
-		 */
-		"asStripeClasses": null,
-		
-		/**
-		 * If restoring a table - we should restore its striping classes as well
-		 *  @type array
-		 *  @default []
-		 */
-		"asDestroyStripes": [],
-		
-		/**
-		 * If restoring a table - we should restore its width 
-		 *  @type int
-		 *  @default 0
-		 */
-		"sDestroyWidth": 0,
-		
-		/**
-		 * Callback functions array for every time a row is inserted (i.e. on a draw).
-		 *  @type array
-		 *  @default []
-		 */
-		"aoRowCallback": [],
-		
-		/**
-		 * Callback functions for the header on each draw.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoHeaderCallback": [],
-		
-		/**
-		 * Callback function for the footer on each draw.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoFooterCallback": [],
-		
-		/**
-		 * Array of callback functions for draw callback functions
-		 *  @type array
-		 *  @default []
-		 */
-		"aoDrawCallback": [],
-		
-		/**
-		 * Array of callback functions for row created function
-		 *  @type array
-		 *  @default []
-		 */
-		"aoRowCreatedCallback": [],
-		
-		/**
-		 * Callback functions for just before the table is redrawn. A return of 
-		 * false will be used to cancel the draw.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoPreDrawCallback": [],
-		
-		/**
-		 * Callback functions for when the table has been initialised.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoInitComplete": [],
-	
-		
-		/**
-		 * Callbacks for modifying the settings to be stored for state saving, prior to
-		 * saving state.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoStateSaveParams": [],
-		
-		/**
-		 * Callbacks for modifying the settings that have been stored for state saving
-		 * prior to using the stored values to restore the state.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoStateLoadParams": [],
-		
-		/**
-		 * Callbacks for operating on the settings object once the saved state has been
-		 * loaded
-		 *  @type array
-		 *  @default []
-		 */
-		"aoStateLoaded": [],
-		
-		/**
-		 * Cache the table ID for quick access
-		 *  @type string
-		 *  @default <i>Empty string</i>
-		 */
-		"sTableId": "",
-		
-		/**
-		 * The TABLE node for the main table
-		 *  @type node
-		 *  @default null
-		 */
-		"nTable": null,
-		
-		/**
-		 * Permanent ref to the thead element
-		 *  @type node
-		 *  @default null
-		 */
-		"nTHead": null,
-		
-		/**
-		 * Permanent ref to the tfoot element - if it exists
-		 *  @type node
-		 *  @default null
-		 */
-		"nTFoot": null,
-		
-		/**
-		 * Permanent ref to the tbody element
-		 *  @type node
-		 *  @default null
-		 */
-		"nTBody": null,
-		
-		/**
-		 * Cache the wrapper node (contains all DataTables controlled elements)
-		 *  @type node
-		 *  @default null
-		 */
-		"nTableWrapper": null,
-		
-		/**
-		 * Indicate if when using server-side processing the loading of data 
-		 * should be deferred until the second draw.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type boolean
-		 *  @default false
-		 */
-		"bDeferLoading": false,
-		
-		/**
-		 * Indicate if all required information has been read in
-		 *  @type boolean
-		 *  @default false
-		 */
-		"bInitialised": false,
-		
-		/**
-		 * Information about open rows. Each object in the array has the parameters
-		 * 'nTr' and 'nParent'
-		 *  @type array
-		 *  @default []
-		 */
-		"aoOpenRows": [],
-		
-		/**
-		 * Dictate the positioning of DataTables' control elements - see
-		 * {@link DataTable.model.oInit.sDom}.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type string
-		 *  @default null
-		 */
-		"sDom": null,
-		
-		/**
-		 * Which type of pagination should be used.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type string 
-		 *  @default two_button
-		 */
-		"sPaginationType": "two_button",
-		
-		/**
-		 * The cookie duration (for bStateSave) in seconds.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type int
-		 *  @default 0
-		 */
-		"iCookieDuration": 0,
-		
-		/**
-		 * The cookie name prefix.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type string
-		 *  @default <i>Empty string</i>
-		 */
-		"sCookiePrefix": "",
-		
-		/**
-		 * Callback function for cookie creation.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type function
-		 *  @default null
-		 */
-		"fnCookieCallback": null,
-		
-		/**
-		 * Array of callback functions for state saving. Each array element is an 
-		 * object with the following parameters:
-		 *   <ul>
-		 *     <li>function:fn - function to call. Takes two parameters, oSettings
-		 *       and the JSON string to save that has been thus far created. Returns
-		 *       a JSON string to be inserted into a json object 
-		 *       (i.e. '"param": [ 0, 1, 2]')</li>
-		 *     <li>string:sName - name of callback</li>
-		 *   </ul>
-		 *  @type array
-		 *  @default []
-		 */
-		"aoStateSave": [],
-		
-		/**
-		 * Array of callback functions for state loading. Each array element is an 
-		 * object with the following parameters:
-		 *   <ul>
-		 *     <li>function:fn - function to call. Takes two parameters, oSettings 
-		 *       and the object stored. May return false to cancel state loading</li>
-		 *     <li>string:sName - name of callback</li>
-		 *   </ul>
-		 *  @type array
-		 *  @default []
-		 */
-		"aoStateLoad": [],
-		
-		/**
-		 * State that was loaded from the cookie. Useful for back reference
-		 *  @type object
-		 *  @default null
-		 */
-		"oLoadedState": null,
-		
-		/**
-		 * Source url for AJAX data for the table.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type string
-		 *  @default null
-		 */
-		"sAjaxSource": null,
-		
-		/**
-		 * Property from a given object from which to read the table data from. This
-		 * can be an empty string (when not server-side processing), in which case 
-		 * it is  assumed an an array is given directly.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type string
-		 */
-		"sAjaxDataProp": null,
-		
-		/**
-		 * Note if draw should be blocked while getting data
-		 *  @type boolean
-		 *  @default true
-		 */
-		"bAjaxDataGet": true,
-		
-		/**
-		 * The last jQuery XHR object that was used for server-side data gathering. 
-		 * This can be used for working with the XHR information in one of the 
-		 * callbacks
-		 *  @type object
-		 *  @default null
-		 */
-		"jqXHR": null,
-		
-		/**
-		 * Function to get the server-side data.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type function
-		 */
-		"fnServerData": null,
-		
-		/**
-		 * Functions which are called prior to sending an Ajax request so extra 
-		 * parameters can easily be sent to the server
-		 *  @type array
-		 *  @default []
-		 */
-		"aoServerParams": [],
-		
-		/**
-		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if 
-		 * required).
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type string
-		 */
-		"sServerMethod": null,
-		
-		/**
-		 * Format numbers for display.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type function
-		 */
-		"fnFormatNumber": null,
-		
-		/**
-		 * List of options that can be used for the user selectable length menu.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type array
-		 *  @default []
-		 */
-		"aLengthMenu": null,
-		
-		/**
-		 * Counter for the draws that the table does. Also used as a tracker for
-		 * server-side processing
-		 *  @type int
-		 *  @default 0
-		 */
-		"iDraw": 0,
-		
-		/**
-		 * Indicate if a redraw is being done - useful for Ajax
-		 *  @type boolean
-		 *  @default false
-		 */
-		"bDrawing": false,
-		
-		/**
-		 * Draw index (iDraw) of the last error when parsing the returned data
-		 *  @type int
-		 *  @default -1
-		 */
-		"iDrawError": -1,
-		
-		/**
-		 * Paging display length
-		 *  @type int
-		 *  @default 10
-		 */
-		"_iDisplayLength": 10,
-	
-		/**
-		 * Paging start point - aiDisplay index
-		 *  @type int
-		 *  @default 0
-		 */
-		"_iDisplayStart": 0,
-	
-		/**
-		 * Paging end point - aiDisplay index. Use fnDisplayEnd rather than
-		 * this property to get the end point
-		 *  @type int
-		 *  @default 10
-		 *  @private
-		 */
-		"_iDisplayEnd": 10,
-		
-		/**
-		 * Server-side processing - number of records in the result set
-		 * (i.e. before filtering), Use fnRecordsTotal rather than
-		 * this property to get the value of the number of records, regardless of
-		 * the server-side processing setting.
-		 *  @type int
-		 *  @default 0
-		 *  @private
-		 */
-		"_iRecordsTotal": 0,
-	
-		/**
-		 * Server-side processing - number of records in the current display set
-		 * (i.e. after filtering). Use fnRecordsDisplay rather than
-		 * this property to get the value of the number of records, regardless of
-		 * the server-side processing setting.
-		 *  @type boolean
-		 *  @default 0
-		 *  @private
-		 */
-		"_iRecordsDisplay": 0,
-		
-		/**
-		 * Flag to indicate if jQuery UI marking and classes should be used.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type boolean
-		 */
-		"bJUI": null,
-		
-		/**
-		 * The classes to use for the table
-		 *  @type object
-		 *  @default {}
-		 */
-		"oClasses": {},
-		
-		/**
-		 * Flag attached to the settings object so you can check in the draw 
-		 * callback if filtering has been done in the draw. Deprecated in favour of
-		 * events.
-		 *  @type boolean
-		 *  @default false
-		 *  @deprecated
-		 */
-		"bFiltered": false,
-		
-		/**
-		 * Flag attached to the settings object so you can check in the draw 
-		 * callback if sorting has been done in the draw. Deprecated in favour of
-		 * events.
-		 *  @type boolean
-		 *  @default false
-		 *  @deprecated
-		 */
-		"bSorted": false,
-		
-		/**
-		 * Indicate that if multiple rows are in the header and there is more than 
-		 * one unique cell per column, if the top one (true) or bottom one (false) 
-		 * should be used for sorting / title by DataTables.
-		 * Note that this parameter will be set by the initialisation routine. To
-		 * set a default use {@link DataTable.defaults}.
-		 *  @type boolean
-		 */
-		"bSortCellsTop": null,
-		
-		/**
-		 * Initialisation object that is used for the table
-		 *  @type object
-		 *  @default null
-		 */
-		"oInit": null,
-		
-		/**
-		 * Destroy callback functions - for plug-ins to attach themselves to the
-		 * destroy so they can clean up markup and events.
-		 *  @type array
-		 *  @default []
-		 */
-		"aoDestroyCallback": [],
-	
-		
-		/**
-		 * Get the number of records in the current record set, before filtering
-		 *  @type function
-		 */
-		"fnRecordsTotal": function ()
-		{
-			if ( this.oFeatures.bServerSide ) {
-				return parseInt(this._iRecordsTotal, 10);
-			} else {
-				return this.aiDisplayMaster.length;
-			}
-		},
-		
-		/**
-		 * Get the number of records in the current record set, after filtering
-		 *  @type function
-		 */
-		"fnRecordsDisplay": function ()
-		{
-			if ( this.oFeatures.bServerSide ) {
-				return parseInt(this._iRecordsDisplay, 10);
-			} else {
-				return this.aiDisplay.length;
-			}
-		},
-		
-		/**
-		 * Set the display end point - aiDisplay index
-		 *  @type function
-		 *  @todo Should do away with _iDisplayEnd and calculate it on-the-fly here
-		 */
-		"fnDisplayEnd": function ()
-		{
-			if ( this.oFeatures.bServerSide ) {
-				if ( this.oFeatures.bPaginate === false || this._iDisplayLength == -1 ) {
-					return this._iDisplayStart+this.aiDisplay.length;
-				} else {
-					return Math.min( this._iDisplayStart+this._iDisplayLength, 
-						this._iRecordsDisplay );
-				}
-			} else {
-				return this._iDisplayEnd;
-			}
-		},
-		
-		/**
-		 * The DataTables object for this table
-		 *  @type object
-		 *  @default null
-		 */
-		"oInstance": null,
-		
-		/**
-		 * Unique identifier for each instance of the DataTables object. If there
-		 * is an ID on the table node, then it takes that value, otherwise an
-		 * incrementing internal counter is used.
-		 *  @type string
-		 *  @default null
-		 */
-		"sInstance": null,
-	
-		/**
-		 * tabindex attribute value that is added to DataTables control elements, allowing
-		 * keyboard navigation of the table and its controls.
-		 */
-		"iTabIndex": 0,
-	
-		/**
-		 * DIV container for the footer scrolling table if scrolling
-		 */
-		"nScrollHead": null,
-	
-		/**
-		 * DIV container for the footer scrolling table if scrolling
-		 */
-		"nScrollFoot": null
-	};
-
-	/**
-	 * Extension object for DataTables that is used to provide all extension options.
-	 * 
-	 * Note that the <i>DataTable.ext</i> object is available through
-	 * <i>jQuery.fn.dataTable.ext</i> where it may be accessed and manipulated. It is
-	 * also aliased to <i>jQuery.fn.dataTableExt</i> for historic reasons.
-	 *  @namespace
-	 *  @extends DataTable.models.ext
-	 */
-	DataTable.ext = $.extend( true, {}, DataTable.models.ext );
-	
-	$.extend( DataTable.ext.oStdClasses, {
-		"sTable": "dataTable",
-	
-		/* Two buttons buttons */
-		"sPagePrevEnabled": "paginate_enabled_previous",
-		"sPagePrevDisabled": "paginate_disabled_previous",
-		"sPageNextEnabled": "paginate_enabled_next",
-		"sPageNextDisabled": "paginate_disabled_next",
-		"sPageJUINext": "",
-		"sPageJUIPrev": "",
-		
-		/* Full numbers paging buttons */
-		"sPageButton": "paginate_button",
-		"sPageButtonActive": "paginate_active",
-		"sPageButtonStaticDisabled": "paginate_button paginate_button_disabled",
-		"sPageFirst": "first",
-		"sPagePrevious": "previous",
-		"sPageNext": "next",
-		"sPageLast": "last",
-		
-		/* Striping classes */
-		"sStripeOdd": "odd",
-		"sStripeEven": "even",
-		
-		/* Empty row */
-		"sRowEmpty": "dataTables_empty",
-		
-		/* Features */
-		"sWrapper": "dataTables_wrapper",
-		"sFilter": "dataTables_filter",
-		"sInfo": "dataTables_info",
-		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
-		"sLength": "dataTables_length",
-		"sProcessing": "dataTables_processing",
-		
-		/* Sorting */
-		"sSortAsc": "sorting_asc",
-		"sSortDesc": "sorting_desc",
-		"sSortable": "sorting", /* Sortable in both directions */
-		"sSortableAsc": "sorting_asc_disabled",
-		"sSortableDesc": "sorting_desc_disabled",
-		"sSortableNone": "sorting_disabled",
-		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
-		"sSortJUIAsc": "",
-		"sSortJUIDesc": "",
-		"sSortJUI": "",
-		"sSortJUIAscAllowed": "",
-		"sSortJUIDescAllowed": "",
-		"sSortJUIWrapper": "",
-		"sSortIcon": "",
-		
-		/* Scrolling */
-		"sScrollWrapper": "dataTables_scroll",
-		"sScrollHead": "dataTables_scrollHead",
-		"sScrollHeadInner": "dataTables_scrollHeadInner",
-		"sScrollBody": "dataTables_scrollBody",
-		"sScrollFoot": "dataTables_scrollFoot",
-		"sScrollFootInner": "dataTables_scrollFootInner",
-		
-		/* Misc */
-		"sFooterTH": "",
-		"sJUIHeader": "",
-		"sJUIFooter": ""
-	} );
-	
-	
-	$.extend( DataTable.ext.oJUIClasses, DataTable.ext.oStdClasses, {
-		/* Two buttons buttons */
-		"sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
-		"sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
-		"sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
-		"sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
-		"sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
-		"sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
-		
-		/* Full numbers paging buttons */
-		"sPageButton": "fg-button ui-button ui-state-default",
-		"sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
-		"sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
-		"sPageFirst": "first ui-corner-tl ui-corner-bl",
-		"sPageLast": "last ui-corner-tr ui-corner-br",
-		
-		/* Features */
-		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
-			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
-		
-		/* Sorting */
-		"sSortAsc": "ui-state-default",
-		"sSortDesc": "ui-state-default",
-		"sSortable": "ui-state-default",
-		"sSortableAsc": "ui-state-default",
-		"sSortableDesc": "ui-state-default",
-		"sSortableNone": "ui-state-default",
-		"sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
-		"sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
-		"sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
-		"sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
-		"sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
-		"sSortJUIWrapper": "DataTables_sort_wrapper",
-		"sSortIcon": "DataTables_sort_icon",
-		
-		/* Scrolling */
-		"sScrollHead": "dataTables_scrollHead ui-state-default",
-		"sScrollFoot": "dataTables_scrollFoot ui-state-default",
-		
-		/* Misc */
-		"sFooterTH": "ui-state-default",
-		"sJUIHeader": "fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",
-		"sJUIFooter": "fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"
-	} );
-	
-	/*
-	 * Variable: oPagination
-	 * Purpose:  
-	 * Scope:    jQuery.fn.dataTableExt
-	 */
-	$.extend( DataTable.ext.oPagination, {
-		/*
-		 * Variable: two_button
-		 * Purpose:  Standard two button (forward/back) pagination
-		 * Scope:    jQuery.fn.dataTableExt.oPagination
-		 */
-		"two_button": {
-			/*
-			 * Function: oPagination.two_button.fnInit
-			 * Purpose:  Initialise dom elements required for pagination with forward/back buttons only
-			 * Returns:  -
-			 * Inputs:   object:oSettings - dataTables settings object
-			 *           node:nPaging - the DIV which contains this pagination control
-			 *           function:fnCallbackDraw - draw function which must be called on update
-			 */
-			"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
-			{
-				var oLang = oSettings.oLanguage.oPaginate;
-				var oClasses = oSettings.oClasses;
-				var fnClickHandler = function ( e ) {
-					if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
-					{
-						fnCallbackDraw( oSettings );
-					}
-				};
-	
-				var sAppend = (!oSettings.bJUI) ?
-					'<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+
-					'<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>'
-					:
-					'<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+
-					'<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>';
-				$(nPaging).append( sAppend );
-				
-				var els = $('a', nPaging);
-				var nPrevious = els[0],
-					nNext = els[1];
-				
-				oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, fnClickHandler );
-				oSettings.oApi._fnBindAction( nNext,     {action: "next"},     fnClickHandler );
-				
-				/* ID the first elements only */
-				if ( !oSettings.aanFeatures.p )
-				{
-					nPaging.id = oSettings.sTableId+'_paginate';
-					nPrevious.id = oSettings.sTableId+'_previous';
-					nNext.id = oSettings.sTableId+'_next';
-	
-					nPrevious.setAttribute('aria-controls', oSettings.sTableId);
-					nNext.setAttribute('aria-controls', oSettings.sTableId);
-				}
-			},
-			
-			/*
-			 * Function: oPagination.two_button.fnUpdate
-			 * Purpose:  Update the two button pagination at the end of the draw
-			 * Returns:  -
-			 * Inputs:   object:oSettings - dataTables settings object
-			 *           function:fnCallbackDraw - draw function to call on page change
-			 */
-			"fnUpdate": function ( oSettings, fnCallbackDraw )
-			{
-				if ( !oSettings.aanFeatures.p )
-				{
-					return;
-				}
-				
-				var oClasses = oSettings.oClasses;
-				var an = oSettings.aanFeatures.p;
-				var nNode;
-	
-				/* Loop over each instance of the pager */
-				for ( var i=0, iLen=an.length ; i<iLen ; i++ )
-				{
-					nNode = an[i].firstChild;
-					if ( nNode )
-					{
-						/* Previous page */
-						nNode.className = ( oSettings._iDisplayStart === 0 ) ?
-						    oClasses.sPagePrevDisabled : oClasses.sPagePrevEnabled;
-						    
-						/* Next page */
-						nNode = nNode.nextSibling;
-						nNode.className = ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ?
-						    oClasses.sPageNextDisabled : oClasses.sPageNextEnabled;
-					}
-				}
-			}
-		},
-		
-		
-		/*
-		 * Variable: iFullNumbersShowPages
-		 * Purpose:  Change the number of pages which can be seen
-		 * Scope:    jQuery.fn.dataTableExt.oPagination
-		 */
-		"iFullNumbersShowPages": 5,
-		
-		/*
-		 * Variable: full_numbers
-		 * Purpose:  Full numbers pagination
-		 * Scope:    jQuery.fn.dataTableExt.oPagination
-		 */
-		"full_numbers": {
-			/*
-			 * Function: oPagination.full_numbers.fnInit
-			 * Purpose:  Initialise dom elements required for pagination with a list of the pages
-			 * Returns:  -
-			 * Inputs:   object:oSettings - dataTables settings object
-			 *           node:nPaging - the DIV which contains this pagination control
-			 *           function:fnCallbackDraw - draw function which must be called on update
-			 */
-			"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
-			{
-				var oLang = oSettings.oLanguage.oPaginate;
-				var oClasses = oSettings.oClasses;
-				var fnClickHandler = function ( e ) {
-					if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
-					{
-						fnCallbackDraw( oSettings );
-					}
-				};
-	
-				$(nPaging).append(
-					'<a  tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageFirst+'">'+oLang.sFirst+'</a>'+
-					'<a  tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPagePrevious+'">'+oLang.sPrevious+'</a>'+
-					'<span></span>'+
-					'<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageNext+'">'+oLang.sNext+'</a>'+
-					'<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+" "+oClasses.sPageLast+'">'+oLang.sLast+'</a>'
-				);
-				var els = $('a', nPaging);
-				var nFirst = els[0],
-					nPrev = els[1],
-					nNext = els[2],
-					nLast = els[3];
-				
-				oSettings.oApi._fnBindAction( nFirst, {action: "first"},    fnClickHandler );
-				oSettings.oApi._fnBindAction( nPrev,  {action: "previous"}, fnClickHandler );
-				oSettings.oApi._fnBindAction( nNext,  {action: "next"},     fnClickHandler );
-				oSettings.oApi._fnBindAction( nLast,  {action: "last"},     fnClickHandler );
-				
-				/* ID the first elements only */
-				if ( !oSettings.aanFeatures.p )
-				{
-					nPaging.id = oSettings.sTableId+'_paginate';
-					nFirst.id =oSettings.sTableId+'_first';
-					nPrev.id =oSettings.sTableId+'_previous';
-					nNext.id =oSettings.sTableId+'_next';
-					nLast.id =oSettings.sTableId+'_last';
-				}
-			},
-			
-			/*
-			 * Function: oPagination.full_numbers.fnUpdate
-			 * Purpose:  Update the list of page buttons shows
-			 * Returns:  -
-			 * Inputs:   object:oSettings - dataTables settings object
-			 *           function:fnCallbackDraw - draw function to call on page change
-			 */
-			"fnUpdate": function ( oSettings, fnCallbackDraw )
-			{
-				if ( !oSettings.aanFeatures.p )
-				{
-					return;
-				}
-				
-				var iPageCount = DataTable.ext.oPagination.iFullNumbersShowPages;
-				var iPageCountHalf = Math.floor(iPageCount / 2);
-				var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
-				var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
-				var sList = "";
-				var iStartButton, iEndButton, i, iLen;
-				var oClasses = oSettings.oClasses;
-				var anButtons, anStatic, nPaginateList, nNode;
-				var an = oSettings.aanFeatures.p;
-				var fnBind = function (j) {
-					oSettings.oApi._fnBindAction( this, {"page": j+iStartButton-1}, function(e) {
-						/* Use the information in the element to jump to the required page */
-						oSettings.oApi._fnPageChange( oSettings, e.data.page );
-						fnCallbackDraw( oSettings );
-						e.preventDefault();
-					} );
-				};
-				
-				/* Pages calculation */
-				if ( oSettings._iDisplayLength === -1 )
-				{
-					iStartButton = 1;
-					iEndButton = 1;
-					iCurrentPage = 1;
-				}
-				else if (iPages < iPageCount)
-				{
-					iStartButton = 1;
-					iEndButton = iPages;
-				}
-				else if (iCurrentPage <= iPageCountHalf)
-				{
-					iStartButton = 1;
-					iEndButton = iPageCount;
-				}
-				else if (iCurrentPage >= (iPages - iPageCountHalf))
-				{
-					iStartButton = iPages - iPageCount + 1;
-					iEndButton = iPages;
-				}
-				else
-				{
-					iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
-					iEndButton = iStartButton + iPageCount - 1;
-				}
-	
-				
-				/* Build the dynamic list */
-				for ( i=iStartButton ; i<=iEndButton ; i++ )
-				{
-					sList += (iCurrentPage !== i) ?
-						'<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButton+'">'+oSettings.fnFormatNumber(i)+'</a>' :
-						'<a tabindex="'+oSettings.iTabIndex+'" class="'+oClasses.sPageButtonActive+'">'+oSettings.fnFormatNumber(i)+'</a>';
-				}
-				
-				/* Loop over each instance of the pager */
-				for ( i=0, iLen=an.length ; i<iLen ; i++ )
-				{
-					nNode = an[i];
-					if ( !nNode.hasChildNodes() )
-					{
-						continue;
-					}
-					
-					/* Build up the dynamic list first - html and listeners */
-					$('span:eq(0)', nNode)
-						.html( sList )
-						.children('a').each( fnBind );
-					
-					/* Update the permanent button's classes */
-					anButtons = nNode.getElementsByTagName('a');
-					anStatic = [
-						anButtons[0], anButtons[1], 
-						anButtons[anButtons.length-2], anButtons[anButtons.length-1]
-					];
-	
-					$(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled );
-					$([anStatic[0], anStatic[1]]).addClass( 
-						(iCurrentPage==1) ?
-							oClasses.sPageButtonStaticDisabled :
-							oClasses.sPageButton
-					);
-					$([anStatic[2], anStatic[3]]).addClass(
-						(iPages===0 || iCurrentPage===iPages || oSettings._iDisplayLength===-1) ?
-							oClasses.sPageButtonStaticDisabled :
-							oClasses.sPageButton
-					);
-				}
-			}
-		}
-	} );
-	
-	$.extend( DataTable.ext.oSort, {
-		/*
-		 * text sorting
-		 */
-		"string-pre": function ( a )
-		{
-			if ( typeof a != 'string' ) {
-				a = (a !== null && a.toString) ? a.toString() : '';
-			}
-			return a.toLowerCase();
-		},
-	
-		"string-asc": function ( x, y )
-		{
-			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-		},
-		
-		"string-desc": function ( x, y )
-		{
-			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
-		},
-		
-		
-		/*
-		 * html sorting (ignore html tags)
-		 */
-		"html-pre": function ( a )
-		{
-			return a.replace( /<.*?>/g, "" ).toLowerCase();
-		},
-		
-		"html-asc": function ( x, y )
-		{
-			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
-		},
-		
-		"html-desc": function ( x, y )
-		{
-			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
-		},
-		
-		
-		/*
-		 * date sorting
-		 */
-		"date-pre": function ( a )
-		{
-			var x = Date.parse( a );
-			
-			if ( isNaN(x) || x==="" )
-			{
-				x = Date.parse( "01/01/1970 00:00:00" );
-			}
-			return x;
-		},
-	
-		"date-asc": function ( x, y )
-		{
-			return x - y;
-		},
-		
-		"date-desc": function ( x, y )
-		{
-			return y - x;
-		},
-		
-		
-		/*
-		 * numerical sorting
-		 */
-		"numeric-pre": function ( a )
-		{
-			return (a=="-" || a==="") ? 0 : a*1;
-		},
-	
-		"numeric-asc": function ( x, y )
-		{
-			return x - y;
-		},
-		
-		"numeric-desc": function ( x, y )
-		{
-			return y - x;
-		}
-	} );
-	
-	
-	$.extend( DataTable.ext.aTypes, [
-		/*
-		 * Function: -
-		 * Purpose:  Check to see if a string is numeric
-		 * Returns:  string:'numeric' or null
-		 * Inputs:   mixed:sText - string to check
-		 */
-		function ( sData )
-		{
-			/* Allow zero length strings as a number */
-			if ( typeof sData === 'number' )
-			{
-				return 'numeric';
-			}
-			else if ( typeof sData !== 'string' )
-			{
-				return null;
-			}
-			
-			var sValidFirstChars = "0123456789-";
-			var sValidChars = "0123456789.";
-			var Char;
-			var bDecimal = false;
-			
-			/* Check for a valid first char (no period and allow negatives) */
-			Char = sData.charAt(0); 
-			if (sValidFirstChars.indexOf(Char) == -1) 
-			{
-				return null;
-			}
-			
-			/* Check all the other characters are valid */
-			for ( var i=1 ; i<sData.length ; i++ ) 
-			{
-				Char = sData.charAt(i); 
-				if (sValidChars.indexOf(Char) == -1) 
-				{
-					return null;
-				}
-				
-				/* Only allowed one decimal place... */
-				if ( Char == "." )
-				{
-					if ( bDecimal )
-					{
-						return null;
-					}
-					bDecimal = true;
-				}
-			}
-			
-			return 'numeric';
-		},
-		
-		/*
-		 * Function: -
-		 * Purpose:  Check to see if a string is actually a formatted date
-		 * Returns:  string:'date' or null
-		 * Inputs:   string:sText - string to check
-		 */
-		function ( sData )
-		{
-			var iParse = Date.parse(sData);
-			if ( (iParse !== null && !isNaN(iParse)) || (typeof sData === 'string' && sData.length === 0) )
-			{
-				return 'date';
-			}
-			return null;
-		},
-		
-		/*
-		 * Function: -
-		 * Purpose:  Check to see if a string should be treated as an HTML string
-		 * Returns:  string:'html' or null
-		 * Inputs:   string:sText - string to check
-		 */
-		function ( sData )
-		{
-			if ( typeof sData === 'string' && sData.indexOf('<') != -1 && sData.indexOf('>') != -1 )
-			{
-				return 'html';
-			}
-			return null;
-		}
-	] );
-	
-
-	// jQuery aliases
-	$.fn.DataTable = DataTable;
-	$.fn.dataTable = DataTable;
-	$.fn.dataTableSettings = DataTable.settings;
-	$.fn.dataTableExt = DataTable.ext;
-
-
-	// Information about events fired by DataTables - for documentation.
-	/**
-	 * Draw event, fired whenever the table is redrawn on the page, at the same point as
-	 * fnDrawCallback. This may be useful for binding events or performing calculations when
-	 * the table is altered at all.
-	 *  @name DataTable#draw
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
-	 */
-
-	/**
-	 * Filter event, fired when the filtering applied to the table (using the build in global
-	 * global filter, or column filters) is altered.
-	 *  @name DataTable#filter
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
-	 */
-
-	/**
-	 * Page change event, fired when the paging of the table is altered.
-	 *  @name DataTable#page
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
-	 */
-
-	/**
-	 * Sort event, fired when the sorting applied to the table is altered.
-	 *  @name DataTable#sort
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
-	 */
-
-	/**
-	 * DataTables initialisation complete event, fired when the table is fully drawn,
-	 * including Ajax data loaded, if Ajax data is required.
-	 *  @name DataTable#init
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} oSettings DataTables settings object
-	 *  @param {object} json The JSON object request from the server - only
-	 *    present if client-side Ajax sourced data is used</li></ol>
-	 */
-
-	/**
-	 * State save event, fired when the table has changed state a new state save is required.
-	 * This method allows modification of the state saving object prior to actually doing the
-	 * save, including addition or other state properties (for plug-ins) or modification
-	 * of a DataTables core property.
-	 *  @name DataTable#stateSaveParams
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} oSettings DataTables settings object
-	 *  @param {object} json The state information to be saved
-	 */
-
-	/**
-	 * State load event, fired when the table is loading state from the stored data, but
-	 * prior to the settings object being modified by the saved state - allowing modification
-	 * of the saved state is required or loading of state for a plug-in.
-	 *  @name DataTable#stateLoadParams
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} oSettings DataTables settings object
-	 *  @param {object} json The saved state information
-	 */
-
-	/**
-	 * State loaded event, fired when state has been loaded from stored data and the settings
-	 * object has been modified by the loaded data.
-	 *  @name DataTable#stateLoaded
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} oSettings DataTables settings object
-	 *  @param {object} json The saved state information
-	 */
-
-	/**
-	 * Processing event, fired when DataTables is doing some kind of processing (be it,
-	 * sort, filter or anything else). Can be used to indicate to the end user that
-	 * there is something happening, or that something has finished.
-	 *  @name DataTable#processing
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} oSettings DataTables settings object
-	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
-	 */
-
-	/**
-	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a request to 
-	 * made to the server for new data (note that this trigger is called in fnServerData,
-	 * if you override fnServerData and which to use this event, you need to trigger it in
-	 * you success function).
-	 *  @name DataTable#xhr
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
-	 *  @param {object} json JSON returned from the server
-	 */
-
-	/**
-	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy or passing
-	 * the bDestroy:true parameter in the initialisation object. This can be used to remove
-	 * bound events, added DOM nodes, etc.
-	 *  @name DataTable#destroy
-	 *  @event
-	 *  @param {event} e jQuery event object
-	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
-	 */
-}));
-
-}(window, document));
-
diff --git a/src/main/webapp/static/js/jquery/datatables/jquery.dataTables.min.js b/src/main/webapp/static/js/jquery/datatables/jquery.dataTables.min.js
deleted file mode 100644
index 02694a4a56eb247baa2398d971927dfbd1ac3e60..0000000000000000000000000000000000000000
--- a/src/main/webapp/static/js/jquery/datatables/jquery.dataTables.min.js
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * File:        jquery.dataTables.min.js
- * Version:     1.9.4
- * Author:      Allan Jardine (www.sprymedia.co.uk)
- * Info:        www.datatables.net
- * 
- * Copyright 2008-2012 Allan Jardine, all rights reserved.
- *
- * This source file is free software, under either the GPL v2 license or a
- * BSD style license, available at:
- *   http://datatables.net/license_gpl2
- *   http://datatables.net/license_bsd
- * 
- * This source file is distributed in the hope that it will be useful, but 
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
- * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
- */
-(function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d],
-c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData=
-L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1==
-h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;b<c;b++)a.aoColumns[b].nTh.style.width=a.aoColumns[b].sWidth}function G(a,b){var c=r(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function R(a,b){var c=r(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function t(a){return r(a,"bVisible").length}
-function r(a,b){var c=[];h.map(a.aoColumns,function(a,i){a[b]&&c.push(i)});return c}function B(a){for(var b=j.ext.aTypes,c=b.length,d=0;d<c;d++){var i=b[d](a);if(null!==i)return i}return"string"}function u(a,b){for(var c=b.split(","),d=[],i=0,f=a.aoColumns.length;i<f;i++)for(var g=0;g<f;g++)if(a.aoColumns[i].sName==c[g]){d.push(g);break}return d}function M(a){for(var b="",c=0,d=a.aoColumns.length;c<d;c++)b+=a.aoColumns[c].sName+",";return b.length==d?"":b.slice(0,-1)}function ta(a,b,c,d){var i,f,
-g,e,w;if(b)for(i=b.length-1;0<=i;i--){var j=b[i].aTargets;h.isArray(j)||D(a,1,"aTargets must be an array of targets, not a "+typeof j);f=0;for(g=j.length;f<g;f++)if("number"===typeof j[f]&&0<=j[f]){for(;a.aoColumns.length<=j[f];)o(a);d(j[f],b[i])}else if("number"===typeof j[f]&&0>j[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;e<w;e++)("_all"==j[f]||h(a.aoColumns[e].nTh).hasClass(j[f]))&&d(e,b[i])}}if(c){i=0;for(a=c.length;i<a;i++)d(i,c[i])}}function H(a,
-b){var c;c=h.isArray(b)?b.slice():h.extend(!0,{},b);var d=a.aoData.length,i=h.extend(!0,{},j.models.oRow);i._aData=c;a.aoData.push(i);for(var f,i=0,g=a.aoColumns.length;i<g;i++)c=a.aoColumns[i],"function"===typeof c.fnRender&&c.bUseRendered&&null!==c.mData?F(a,d,i,S(a,d,i)):F(a,d,i,v(a,d,i)),c._bAutoType&&"string"!=c.sType&&(f=v(a,d,i,"type"),null!==f&&""!==f&&(f=B(f),null===c.sType?c.sType=f:c.sType!=f&&"html"!=c.sType&&(c.sType="string")));a.aiDisplayMaster.push(d);a.oFeatures.bDeferRender||ea(a,
-d);return d}function ua(a){var b,c,d,i,f,g,e;if(a.bDeferLoading||null===a.sAjaxSource)for(b=a.nTBody.firstChild;b;){if("TR"==b.nodeName.toUpperCase()){c=a.aoData.length;b._DT_RowIndex=c;a.aoData.push(h.extend(!0,{},j.models.oRow,{nTr:b}));a.aiDisplayMaster.push(c);f=b.firstChild;for(d=0;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)F(a,c,d,h.trim(f.innerHTML)),d++;f=f.nextSibling}}b=b.nextSibling}i=T(a);d=[];b=0;for(c=i.length;b<c;b++)for(f=i[b].firstChild;f;)g=f.nodeName.toUpperCase(),("TD"==
-g||"TH"==g)&&d.push(f),f=f.nextSibling;c=0;for(i=a.aoColumns.length;c<i;c++){e=a.aoColumns[c];null===e.sTitle&&(e.sTitle=e.nTh.innerHTML);var w=e._bAutoType,o="function"===typeof e.fnRender,k=null!==e.sClass,n=e.bVisible,m,p;if(w||o||k||!n){g=0;for(b=a.aoData.length;g<b;g++)f=a.aoData[g],m=d[g*i+c],w&&"string"!=e.sType&&(p=v(a,g,c,"type"),""!==p&&(p=B(p),null===e.sType?e.sType=p:e.sType!=p&&"html"!=e.sType&&(e.sType="string"))),e.mRender?m.innerHTML=v(a,g,c,"display"):e.mData!==c&&(m.innerHTML=v(a,
-g,c,"display")),o&&(p=S(a,g,c),m.innerHTML=p,e.bUseRendered&&F(a,g,c,p)),k&&(m.className+=" "+e.sClass),n?f._anHidden[c]=null:(f._anHidden[c]=m,m.parentNode.removeChild(m)),e.fnCreatedCell&&e.fnCreatedCell.call(a.oInstance,m,v(a,g,c,"display"),f._aData,g,c)}}if(0!==a.aoRowCreatedCallback.length){b=0;for(c=a.aoData.length;b<c;b++)f=a.aoData[b],A(a,"aoRowCreatedCallback",null,[f.nTr,f._aData,b])}}function I(a,b){return b._DT_RowIndex!==n?b._DT_RowIndex:null}function fa(a,b,c){for(var b=J(a,b),d=0,a=
-a.aoColumns.length;d<a;d++)if(b[d]===c)return d;return-1}function Y(a,b,c,d){for(var i=[],f=0,g=d.length;f<g;f++)i.push(v(a,b,d[f],c));return i}function v(a,b,c,d){var i=a.aoColumns[c];if((c=i.fnGetData(a.aoData[b]._aData,d))===n)return a.iDrawError!=a.iDraw&&null===i.sDefaultContent&&(D(a,0,"Requested unknown parameter "+("function"==typeof i.mData?"{mData function}":"'"+i.mData+"'")+" from the data source for row "+b),a.iDrawError=a.iDraw),i.sDefaultContent;if(null===c&&null!==i.sDefaultContent)c=
-i.sDefaultContent;else if("function"===typeof c)return c();return"display"==d&&null===c?"":c}function F(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d)}function Q(a){if(null===a)return function(){return null};if("function"===typeof a)return function(b,d,i){return a(b,d,i)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var f=i.split("."),g;if(""!==i){var e=0;for(g=f.length;e<g;e++){if(i=f[e].match(U)){f[e]=f[e].replace(U,"");""!==f[e]&&(a=a[f[e]]);
-g=[];f.splice(0,e+1);for(var f=f.join("."),e=0,h=a.length;e<h;e++)g.push(b(a[e],d,f));a=i[0].substring(1,i[0].length-1);a=""===a?g:g.join(a);break}if(null===a||a[f[e]]===n)return n;a=a[f[e]]}}return a};return function(c,d){return b(c,d,a)}}return function(b){return b[a]}}function L(a){if(null===a)return function(){};if("function"===typeof a)return function(b,d){a(b,"set",d)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("["))){var b=function(a,d,i){var i=i.split("."),f,g,e=0;for(g=
-i.length-1;e<g;e++){if(f=i[e].match(U)){i[e]=i[e].replace(U,"");a[i[e]]=[];f=i.slice();f.splice(0,e+1);g=f.join(".");for(var h=0,j=d.length;h<j;h++)f={},b(f,d[h],g),a[i[e]].push(f);return}if(null===a[i[e]]||a[i[e]]===n)a[i[e]]={};a=a[i[e]]}a[i[i.length-1].replace(U,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Z(a){for(var b=[],c=a.aoData.length,d=0;d<c;d++)b.push(a.aoData[d]._aData);return b}function ga(a){a.aoData.splice(0,a.aoData.length);a.aiDisplayMaster.splice(0,
-a.aiDisplayMaster.length);a.aiDisplay.splice(0,a.aiDisplay.length);y(a)}function ha(a,b){for(var c=-1,d=0,i=a.length;d<i;d++)a[d]==b?c=d:a[d]>b&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&&
-(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i<f;i++){var g=a.aoColumns[i];d=l.createElement(g.sCellType);d.innerHTML="function"===typeof g.fnRender&&(!g.bUseRendered||null===g.mData)?S(a,b,i):v(a,b,i,"display");null!==g.sClass&&(d.className=g.sClass);g.bVisible?(c.nTr.appendChild(d),c._anHidden[i]=null):c._anHidden[i]=d;g.fnCreatedCell&&g.fnCreatedCell.call(a.oInstance,d,v(a,b,i,"display"),c._aData,b,i)}A(a,"aoRowCreatedCallback",null,[c.nTr,c._aData,b])}}function va(a){var b,
-c,d;if(0!==h("th, td",a.nTHead).length){b=0;for(d=a.aoColumns.length;b<d;b++)if(c=a.aoColumns[b].nTh,c.setAttribute("role","columnheader"),a.aoColumns[b].bSortable&&(c.setAttribute("tabindex",a.iTabIndex),c.setAttribute("aria-controls",a.sTableId)),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),a.aoColumns[b].sTitle!=c.innerHTML)c.innerHTML=a.aoColumns[b].sTitle}else{var i=l.createElement("tr");b=0;for(d=a.aoColumns.length;b<d;b++)c=a.aoColumns[b].nTh,c.innerHTML=a.aoColumns[b].sTitle,
-c.setAttribute("tabindex","0"),null!==a.aoColumns[b].sClass&&h(c).addClass(a.aoColumns[b].sClass),i.appendChild(c);h(a.nTHead).html("")[0].appendChild(i);V(a.aoHeader,a.nTHead)}h(a.nTHead).children("tr").attr("role","row");if(a.bJUI){b=0;for(d=a.aoColumns.length;b<d;b++){c=a.aoColumns[b].nTh;i=l.createElement("div");i.className=a.oClasses.sSortJUIWrapper;h(c).contents().appendTo(i);var f=l.createElement("span");f.className=a.oClasses.sSortIcon;i.appendChild(f);c.appendChild(i)}}if(a.oFeatures.bSort)for(b=
-0;b<a.aoColumns.length;b++)!1!==a.aoColumns[b].bSortable?ia(a,a.aoColumns[b].nTh,b):h(a.aoColumns[b].nTh).addClass(a.oClasses.sSortableNone);""!==a.oClasses.sFooterTH&&h(a.nTFoot).children("tr").children("th").addClass(a.oClasses.sFooterTH);if(null!==a.nTFoot){c=N(a,null,a.aoFooter);b=0;for(d=a.aoColumns.length;b<d;b++)c[b]&&(a.aoColumns[b].nTf=c[b],a.aoColumns[b].sClass&&h(c[b]).addClass(a.aoColumns[b].sClass))}}function W(a,b,c){var d,i,f,g=[],e=[],h=a.aoColumns.length,j;c===n&&(c=!1);d=0;for(i=
-b.length;d<i;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=h-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);e.push([])}d=0;for(i=g.length;d<i;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(j=h=1,e[d][f]===n){a.appendChild(g[d][f].cell);for(e[d][f]=1;g[d+h]!==n&&g[d][f].cell==g[d+h][f].cell;)e[d+h][f]=1,h++;for(;g[d][f+j]!==n&&g[d][f].cell==g[d][f+j].cell;){for(c=0;c<h;c++)e[d+c][f+j]=1;j++}g[d][f].cell.rowSpan=h;g[d][f].cell.colSpan=j}}}function x(a){var b=
-A(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))E(a,!1);else{var c,d,b=[],i=0,f=a.asStripeClasses.length;c=a.aoOpenRows.length;a.bDrawing=!0;a.iInitDisplayStart!==n&&-1!=a.iInitDisplayStart&&(a._iDisplayStart=a.oFeatures.bServerSide?a.iInitDisplayStart:a.iInitDisplayStart>=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g=
-a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g<d;g++){var e=a.aoData[a.aiDisplay[g]];null===e.nTr&&ea(a,a.aiDisplay[g]);var j=e.nTr;if(0!==f){var o=a.asStripeClasses[i%f];e._sRowStripe!=o&&(h(j).removeClass(e._sRowStripe).addClass(o),e._sRowStripe=o)}A(a,"aoRowCallback",null,[j,a.aoData[a.aiDisplay[g]]._aData,i,g]);b.push(j);i++;if(0!==c)for(e=0;e<c;e++)if(j==a.aoOpenRows[e].nParent){b.push(a.aoOpenRows[e].nTr);break}}}else b[0]=l.createElement("tr"),a.asStripeClasses[0]&&
-(b[0].className=a.asStripeClasses[0]),c=a.oLanguage,f=c.sZeroRecords,1==a.iDraw&&null!==a.sAjaxSource&&!a.oFeatures.bServerSide?f=c.sLoadingRecords:c.sEmptyTable&&0===a.fnRecordsTotal()&&(f=c.sEmptyTable),c=l.createElement("td"),c.setAttribute("valign","top"),c.colSpan=t(a),c.className=a.oClasses.sRowEmpty,c.innerHTML=ja(a,f),b[i].appendChild(c);A(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);A(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],
-Z(a),a._iDisplayStart,a.fnDisplayEnd(),a.aiDisplay]);i=l.createDocumentFragment();c=l.createDocumentFragment();if(a.nTBody){f=a.nTBody.parentNode;c.appendChild(a.nTBody);if(!a.oScroll.bInfinite||!a._bInitComplete||a.bSorted||a.bFiltered)for(;c=a.nTBody.firstChild;)a.nTBody.removeChild(c);c=0;for(d=b.length;c<d;c++)i.appendChild(b[c]);a.nTBody.appendChild(i);null!==f&&f.appendChild(a.nTBody)}A(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1;a.oFeatures.bServerSide&&(E(a,!1),
-a._bInitComplete||$(a))}}function aa(a){a.oFeatures.bSort?O(a,a.oPreviousSearch):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(y(a),x(a))}function xa(a){var b=h("<div></div>")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('<div id="'+a.sTableId+'_wrapper" class="'+a.oClasses.sWrapper+'" role="grid"></div>')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m<d.length;m++){f=0;g=d[m];if("<"==g){e=h("<div></div>")[0];w=d[m+
-1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f=
-1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k<w;k++)if(g==e[k].cFeature){(i=e[k].fnInit(a))&&(f=1);break}}1==f&&null!==i&&("object"!==typeof a.aanFeatures[g]&&(a.aanFeatures[g]=[]),a.aanFeatures[g].push(i),c.appendChild(i))}b.parentNode.replaceChild(a.nTableWrapper,b)}function V(a,b){var c=h(b).children("tr"),d,i,f,g,e,j,o,k,m,p;a.splice(0,a.length);
-f=0;for(j=c.length;f<j;f++)a.push([]);f=0;for(j=c.length;f<j;f++){d=c[f];for(i=d.firstChild;i;){if("TD"==i.nodeName.toUpperCase()||"TH"==i.nodeName.toUpperCase()){k=1*i.getAttribute("colspan");m=1*i.getAttribute("rowspan");k=!k||0===k||1===k?1:k;m=!m||0===m||1===m?1:m;g=0;for(e=a[f];e[g];)g++;o=g;p=1===k?!0:!1;for(e=0;e<k;e++)for(g=0;g<m;g++)a[f+g][o+e]={cell:i,unique:p},a[f+g].nTr=d}i=i.nextSibling}}}function N(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],V(c,b)));for(var b=0,i=c.length;b<i;b++)for(var f=
-0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function wa(a){if(a.bAjaxDataGet){a.iDraw++;E(a,!0);var b=Ea(a);ka(a,b);a.fnServerData.call(a.oInstance,a.sAjaxSource,b,function(b){Fa(a,b)},a);return!1}return!0}function Ea(a){var b=a.aoColumns.length,c=[],d,i,f,g;c.push({name:"sEcho",value:a.iDraw});c.push({name:"iColumns",value:b});c.push({name:"sColumns",value:M(a)});c.push({name:"iDisplayStart",value:a._iDisplayStart});c.push({name:"iDisplayLength",
-value:!1!==a.oFeatures.bPaginate?a._iDisplayLength:-1});for(f=0;f<b;f++)d=a.aoColumns[f].mData,c.push({name:"mDataProp_"+f,value:"function"===typeof d?"function":d});if(!1!==a.oFeatures.bFilter){c.push({name:"sSearch",value:a.oPreviousSearch.sSearch});c.push({name:"bRegex",value:a.oPreviousSearch.bRegex});for(f=0;f<b;f++)c.push({name:"sSearch_"+f,value:a.aoPreSearchCols[f].sSearch}),c.push({name:"bRegex_"+f,value:a.aoPreSearchCols[f].bRegex}),c.push({name:"bSearchable_"+f,value:a.aoColumns[f].bSearchable})}if(!1!==
-a.oFeatures.bSort){var e=0;d=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(f=0;f<d.length;f++){i=a.aoColumns[d[f][0]].aDataSort;for(g=0;g<i.length;g++)c.push({name:"iSortCol_"+e,value:i[g]}),c.push({name:"sSortDir_"+e,value:d[f][1]}),e++}c.push({name:"iSortingCols",value:e});for(f=0;f<b;f++)c.push({name:"bSortable_"+f,value:a.aoColumns[f].bSortable})}return c}function ka(a,b){A(a,"aoServerParams","serverParams",[b])}function Fa(a,b){if(b.sEcho!==n){if(1*b.sEcho<
-a.iDraw)return;a.iDraw=1*b.sEcho}(!a.oScroll.bInfinite||a.oScroll.bInfinite&&(a.bSorted||a.bFiltered))&&ga(a);a._iRecordsTotal=parseInt(b.iTotalRecords,10);a._iRecordsDisplay=parseInt(b.iTotalDisplayRecords,10);var c=M(a),c=b.sColumns!==n&&""!==c&&b.sColumns!=c,d;c&&(d=u(a,b.sColumns));for(var i=Q(a.sAjaxDataProp)(b),f=0,g=i.length;f<g;f++)if(c){for(var e=[],h=0,j=a.aoColumns.length;h<j;h++)e.push(i[f][d[h]]);H(a,e)}else H(a,i[f]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;x(a);a.bAjaxDataGet=
-!0;E(a,!1)}function za(a){var b=a.oPreviousSearch,c=a.oLanguage.sSearch,c=-1!==c.indexOf("_INPUT_")?c.replace("_INPUT_",'<input type="text" />'):""===c?'<input type="text" />':c+' <input type="text" />',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="<label>"+c+"</label>";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"&quot;"));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value,
-g=0,e=c.length;g<e;g++)c[g]!=h(this).parents("div.dataTables_filter")[0]&&h(c[g]._DT_Input).val(d);d!=b.sSearch&&K(a,{sSearch:d,bRegex:b.bRegex,bSmart:b.bSmart,bCaseInsensitive:b.bCaseInsensitive})});c.attr("aria-controls",a.sTableId).bind("keypress.DT",function(a){if(a.keyCode==13)return false});return d}function K(a,b,c){var d=a.oPreviousSearch,i=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};if(a.oFeatures.bServerSide)f(b);
-else{Ga(a,b.sSearch,c,b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<a.aoPreSearchCols.length;b++)Ha(a,i[b].sSearch,b,i[b].bRegex,i[b].bSmart,i[b].bCaseInsensitive);Ia(a)}a.bFiltered=!0;h(a.oInstance).trigger("filter",a);a._iDisplayStart=0;y(a);x(a);la(a,0)}function Ia(a){for(var b=j.ext.afnFiltering,c=r(a,"bSearchable"),d=0,i=b.length;d<i;d++)for(var f=0,g=0,e=a.aiDisplay.length;g<e;g++){var h=a.aiDisplay[g-f];b[d](a,Y(a,h,"filter",c),h)||(a.aiDisplay.splice(g-f,1),f++)}}function Ha(a,b,c,
-d,i,f){if(""!==b)for(var g=0,b=ma(b,d,i,f),d=a.aiDisplay.length-1;0<=d;d--)i=Ja(v(a,a.aiDisplay[d],c,"filter"),a.aoColumns[c].sType),b.test(i)||(a.aiDisplay.splice(d,1),g++)}function Ga(a,b,c,d,i,f){d=ma(b,d,i,f);i=a.oPreviousSearch;c||(c=0);0!==j.ext.afnFiltering.length&&(c=1);if(0>=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0,
-a.aiDisplay.length);la(a,1);for(b=0;b<a.aiDisplayMaster.length;b++)d.test(a.asDataSearch[b])&&a.aiDisplay.push(a.aiDisplayMaster[b])}else for(b=c=0;b<a.asDataSearch.length;b++)d.test(a.asDataSearch[b])||(a.aiDisplay.splice(b-c,1),c++)}function la(a,b){if(!a.oFeatures.bServerSide){a.asDataSearch=[];for(var c=r(a,"bSearchable"),d=1===b?a.aiDisplayMaster:a.aiDisplay,i=0,f=d.length;i<f;i++)a.asDataSearch[i]=na(a,Y(a,d[i],"filter",c))}}function na(a,b){var c=b.join("  ");-1!==c.indexOf("&")&&(c=h("<div>").html(c).text());
-return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),
-"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g);
-null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b<c;b++)h(a[b]).html(g)}}function ja(a,b){var c=a.fnFormatNumber(a._iDisplayStart+1),d=a.fnDisplayEnd(),d=a.fnFormatNumber(d),i=a.fnRecordsDisplay(),i=a.fnFormatNumber(i),f=a.fnRecordsTotal(),f=a.fnFormatNumber(f);a.oScroll.bInfinite&&(c=a.fnFormatNumber(1));return b.replace(/_START_/g,c).replace(/_END_/g,d).replace(/_TOTAL_/g,i).replace(/_MAX_/g,f)}function ba(a){var b,c,d=a.iInitDisplayStart;
-if(!1===a.bInitialised)setTimeout(function(){ba(a)},200);else{xa(a);va(a);W(a,a.aoHeader);a.nTFoot&&W(a,a.aoFooter);E(a,!0);a.oFeatures.bAutoWidth&&da(a);b=0;for(c=a.aoColumns.length;b<c;b++)null!==a.aoColumns[b].sWidth&&(a.aoColumns[b].nTh.style.width=q(a.aoColumns[b].sWidth));a.oFeatures.bSort?O(a):a.oFeatures.bFilter?K(a,a.oPreviousSearch):(a.aiDisplay=a.aiDisplayMaster.slice(),y(a),x(a));null!==a.sAjaxSource&&!a.oFeatures.bServerSide?(c=[],ka(a,c),a.fnServerData.call(a.oInstance,a.sAjaxSource,
-c,function(c){var f=a.sAjaxDataProp!==""?Q(a.sAjaxDataProp)(c):c;for(b=0;b<f.length;b++)H(a,f[b]);a.iInitDisplayStart=d;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();y(a);x(a)}E(a,false);$(a,c)},a)):a.oFeatures.bServerSide||(E(a,!1),$(a))}}function $(a,b){a._bInitComplete=!0;A(a,"aoInitComplete","init",[a,b])}function pa(a){var b=j.defaults.oLanguage;!a.sEmptyTable&&(a.sZeroRecords&&"No data available in table"===b.sEmptyTable)&&p(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&
-(a.sZeroRecords&&"Loading..."===b.sLoadingRecords)&&p(a,a,"sZeroRecords","sLoadingRecords")}function ya(a){if(a.oScroll.bInfinite)return null;var b='<select size="1" '+('name="'+a.sTableId+'_length"')+">",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c<d;c++)b+='<option value="'+i[0][c]+'">'+i[1][c]+"</option>"}else{c=0;for(d=i.length;c<d;c++)b+='<option value="'+i[c]+'">'+i[c]+"</option>"}b+="</select>";i=l.createElement("div");a.aanFeatures.l||
-(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="<label>"+a.oLanguage.sLengthMenu.replace("_MENU_",b)+"</label>";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;c<d;c++)i[c]!=this.parentNode&&h("select",i[c]).val(b);a._iDisplayLength=parseInt(b,10);y(a);if(a.fnDisplayEnd()==a.fnRecordsDisplay()){a._iDisplayStart=a.fnDisplayEnd()-a._iDisplayLength;if(a._iDisplayStart<
-0)a._iDisplayStart=0}if(a._iDisplayLength==-1)a._iDisplayStart=0;x(a)});h("select",i).attr("aria-controls",a.sTableId);return i}function y(a){a._iDisplayEnd=!1===a.oFeatures.bPaginate?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength>a.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a,
-b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart=
-0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLength<a.fnRecordsDisplay()&&(a._iDisplayStart+=a._iDisplayLength):a._iDisplayStart=0;else if("last"==b)if(0<=a._iDisplayLength){var d=parseInt((a.fnRecordsDisplay()-1)/a._iDisplayLength,10)+1;a._iDisplayStart=(d-1)*a._iDisplayLength}else a._iDisplayStart=0;else D(a,0,"Unknown paging action: "+b);h(a.oInstance).trigger("page",a);return c!=a._iDisplayStart}function Aa(a){var b=l.createElement("div");a.aanFeatures.r||(b.id=a.sTableId+
-"_processing");b.innerHTML=a.oLanguage.sProcessing;b.className=a.oClasses.sProcessing;a.nTable.parentNode.insertBefore(b,a.nTable);return b}function E(a,b){if(a.oFeatures.bProcessing)for(var c=a.aanFeatures.r,d=0,i=c.length;d<i;d++)c[d].style.visibility=b?"visible":"hidden";h(a.oInstance).trigger("processing",[a,b])}function Ba(a){if(""===a.oScroll.sX&&""===a.oScroll.sY)return a.nTable;var b=l.createElement("div"),c=l.createElement("div"),d=l.createElement("div"),i=l.createElement("div"),f=l.createElement("div"),
-g=l.createElement("div"),e=a.nTable.cloneNode(!1),j=a.nTable.cloneNode(!1),o=a.nTable.getElementsByTagName("thead")[0],k=0===a.nTable.getElementsByTagName("tfoot").length?null:a.nTable.getElementsByTagName("tfoot")[0],m=a.oClasses;c.appendChild(d);f.appendChild(g);i.appendChild(a.nTable);b.appendChild(c);b.appendChild(i);d.appendChild(e);e.appendChild(o);null!==k&&(b.appendChild(f),g.appendChild(j),j.appendChild(k));b.className=m.sScrollWrapper;c.className=m.sScrollHead;d.className=m.sScrollHeadInner;
-i.className=m.sScrollBody;f.className=m.sScrollFoot;g.className=m.sScrollFootInner;a.oScroll.bAutoCss&&(c.style.overflow="hidden",c.style.position="relative",f.style.overflow="hidden",i.style.overflow="auto");c.style.border="0";c.style.width="100%";f.style.border="0";d.style.width=""!==a.oScroll.sXInner?a.oScroll.sXInner:"100%";e.removeAttribute("id");e.style.marginLeft="0";a.nTable.style.marginLeft="0";null!==k&&(j.removeAttribute("id"),j.style.marginLeft="0");d=h(a.nTable).children("caption");0<
-d.length&&(d=d[0],"top"===d._captionSide?e.appendChild(d):"bottom"===d._captionSide&&k&&j.appendChild(d));""!==a.oScroll.sX&&(c.style.width=q(a.oScroll.sX),i.style.width=q(a.oScroll.sX),null!==k&&(f.style.width=q(a.oScroll.sX)),h(i).scroll(function(){c.scrollLeft=this.scrollLeft;if(k!==null)f.scrollLeft=this.scrollLeft}));""!==a.oScroll.sY&&(i.style.height=q(a.oScroll.sY));a.aoDrawCallback.push({fn:La,sName:"scrolling"});a.oScroll.bInfinite&&h(i).scroll(function(){if(!a.bDrawing&&h(this).scrollTop()!==
-0&&h(this).scrollTop()+h(this).height()>h(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()<a.fnRecordsDisplay()){qa(a,"next");y(a);x(a)}});a.nScrollHead=c;a.nScrollFoot=f;return b}function La(a){var b=a.nScrollHead.getElementsByTagName("div")[0],c=b.getElementsByTagName("table")[0],d=a.nTable.parentNode,i,f,g,e,j,o,k,m,p=[],n=[],l=null!==a.nTFoot?a.nScrollFoot.getElementsByTagName("div")[0]:null,R=null!==a.nTFoot?l.getElementsByTagName("table")[0]:null,r=a.oBrowser.bScrollOversize,s=function(a){k=
-a.style;k.paddingTop="0";k.paddingBottom="0";k.borderTopWidth="0";k.borderBottomWidth="0";k.height=0};h(a.nTable).children("thead, tfoot").remove();i=h(a.nTHead).clone()[0];a.nTable.insertBefore(i,a.nTable.childNodes[0]);g=a.nTHead.getElementsByTagName("tr");e=i.getElementsByTagName("tr");null!==a.nTFoot&&(j=h(a.nTFoot).clone()[0],a.nTable.insertBefore(j,a.nTable.childNodes[1]),o=a.nTFoot.getElementsByTagName("tr"),j=j.getElementsByTagName("tr"));""===a.oScroll.sX&&(d.style.width="100%",b.parentNode.style.width=
-"100%");var t=N(a,i);i=0;for(f=t.length;i<f;i++)m=G(a,i),t[i].style.width=a.aoColumns[m].sWidth;null!==a.nTFoot&&C(function(a){a.style.width=""},j);a.oScroll.bCollapse&&""!==a.oScroll.sY&&(d.style.height=d.offsetHeight+a.nTHead.offsetHeight+"px");i=h(a.nTable).outerWidth();if(""===a.oScroll.sX){if(a.nTable.style.width="100%",r&&(h("tbody",d).height()>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width=
-q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()<h(a.nTable).height()?(a.nTable.style.width=q(i-a.oScroll.iBarWidth),h(a.nTable).outerWidth()>i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML=
-"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()<i){g=d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."):
-""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth>
-d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeight<d.offsetHeight&&(d.style.height=q(a.nTable.offsetHeight+r)));r=h(a.nTable).outerWidth();c.style.width=q(r);b.style.width=q(r);c=h(a.nTable).height()>d.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d=
-0,i=0,f=b.length,g,e;i<f;){g=b[i].firstChild;for(e=c?c[i].firstChild:null;g;)1===g.nodeType&&(c?a(g,e,d):a(g,d),d++),g=g.nextSibling,e=c?e.nextSibling:null;i++}}function Ma(a,b){if(!a||null===a||""===a)return 0;b||(b=l.body);var c,d=l.createElement("div");d.style.width=q(a);b.appendChild(d);c=d.offsetWidth;b.removeChild(d);return c}function da(a){var b=0,c,d=0,i=a.aoColumns.length,f,e,j=h("th",a.nTHead),o=a.nTable.getAttribute("width");e=a.nTable.parentNode;for(f=0;f<i;f++)a.aoColumns[f].bVisible&&
-(d++,null!==a.aoColumns[f].sWidth&&(c=Ma(a.aoColumns[f].sWidthOrig,e),null!==c&&(a.aoColumns[f].sWidth=q(c)),b++));if(i==j.length&&0===b&&d==i&&""===a.oScroll.sX&&""===a.oScroll.sY)for(f=0;f<a.aoColumns.length;f++)c=h(j[f]).width(),null!==c&&(a.aoColumns[f].sWidth=q(c));else{b=a.nTable.cloneNode(!1);f=a.nTHead.cloneNode(!0);d=l.createElement("tbody");c=l.createElement("tr");b.removeAttribute("id");b.appendChild(f);null!==a.nTFoot&&(b.appendChild(a.nTFoot.cloneNode(!0)),C(function(a){a.style.width=
-""},b.getElementsByTagName("tr")));b.appendChild(d);d.appendChild(c);d=h("thead th",b);0===d.length&&(d=h("tbody tr:eq(0)>td",b));j=N(a,f);for(f=d=0;f<i;f++){var k=a.aoColumns[f];k.bVisible&&null!==k.sWidthOrig&&""!==k.sWidthOrig?j[f-d].style.width=q(k.sWidthOrig):k.bVisible?j[f-d].style.width="":d++}for(f=0;f<i;f++)a.aoColumns[f].bVisible&&(d=Na(a,f),null!==d&&(d=d.cloneNode(!0),""!==a.aoColumns[f].sContentPadding&&(d.innerHTML+=a.aoColumns[f].sContentPadding),c.appendChild(d)));e.appendChild(b);
-""!==a.oScroll.sX&&""!==a.oScroll.sXInner?b.style.width=q(a.oScroll.sXInner):""!==a.oScroll.sX?(b.style.width="",h(b).width()<e.offsetWidth&&(b.style.width=q(e.offsetWidth))):""!==a.oScroll.sY?b.style.width=q(e.offsetWidth):o&&(b.style.width=q(o));b.style.visibility="hidden";Oa(a,b);i=h("tbody tr:eq(0)",b).children();0===i.length&&(i=N(a,h("thead",b)[0]));if(""!==a.oScroll.sX){for(f=d=e=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=null===a.aoColumns[f].sWidthOrig?e+h(i[d]).outerWidth():
-e+(parseInt(a.aoColumns[f].sWidth.replace("px",""),10)+(h(i[d]).outerWidth()-h(i[d]).width())),d++);b.style.width=q(e);a.nTable.style.width=q(e)}for(f=d=0;f<a.aoColumns.length;f++)a.aoColumns[f].bVisible&&(e=h(i[d]).width(),null!==e&&0<e&&(a.aoColumns[f].sWidth=q(e)),d++);i=h(b).css("width");a.nTable.style.width=-1!==i.indexOf("%")?i:q(h(b).outerWidth());b.parentNode.removeChild(b)}o&&(a.nTable.style.width=q(o))}function Oa(a,b){""===a.oScroll.sX&&""!==a.oScroll.sY?(h(b).width(),b.style.width=q(h(b).outerWidth()-
-a.oScroll.iBarWidth)):""!==a.oScroll.sX&&(b.style.width=q(h(b).outerWidth()))}function Na(a,b){var c=Pa(a,b);if(0>c)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i<a.aoData.length;i++){var e=v(a,i,b,"display")+"",e=e.replace(/<.*?>/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1);
-return 48>b||57<b?a:a+"px"}function Qa(){var a=l.createElement("p"),b=a.style;b.width="100%";b.height="200px";b.padding="0px";var c=l.createElement("div"),b=c.style;b.position="absolute";b.top="0px";b.left="0px";b.visibility="hidden";b.width="200px";b.height="150px";b.padding="0px";b.overflow="hidden";c.appendChild(a);l.body.appendChild(c);b=a.offsetWidth;c.style.overflow="scroll";a=a.offsetWidth;b==a&&(a=c.clientWidth);l.body.removeChild(c);return b-a}function O(a,b){var c,d,i,e,g,k,o=[],m=[],p=
-j.ext.oSort,l=a.aoData,q=a.aoColumns,G=a.oLanguage.oAria;if(!a.oFeatures.bServerSide&&(0!==a.aaSorting.length||null!==a.aaSortingFixed)){o=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(c=0;c<o.length;c++)if(d=o[c][0],i=R(a,d),e=a.aoColumns[d].sSortDataType,j.ext.afnSortData[e])if(g=j.ext.afnSortData[e].call(a.oInstance,a,d,i),g.length===l.length){i=0;for(e=l.length;i<e;i++)F(a,i,d,g[i])}else D(a,0,"Returned data sort array (col "+d+") is the wrong length");c=
-0;for(d=a.aiDisplayMaster.length;c<d;c++)m[a.aiDisplayMaster[c]]=c;var r=o.length,s;c=0;for(d=l.length;c<d;c++)for(i=0;i<r;i++){s=q[o[i][0]].aDataSort;g=0;for(k=s.length;g<k;g++)e=q[s[g]].sType,e=p[(e?e:"string")+"-pre"],l[c]._aSortData[s[g]]=e?e(v(a,c,s[g],"sort")):v(a,c,s[g],"sort")}a.aiDisplayMaster.sort(function(a,b){var c,d,e,i,f;for(c=0;c<r;c++){f=q[o[c][0]].aDataSort;d=0;for(e=f.length;d<e;d++)if(i=q[f[d]].sType,i=p[(i?i:"string")+"-"+o[c][1]](l[a]._aSortData[f[d]],l[b]._aSortData[f[d]]),0!==
-i)return i}return p["numeric-asc"](m[a],m[b])})}(b===n||b)&&!a.oFeatures.bDeferRender&&P(a);c=0;for(d=a.aoColumns.length;c<d;c++)e=q[c].sTitle.replace(/<.*?>/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0<o.length&&o[0][0]==c?(i.setAttribute("aria-sort","asc"==o[0][1]?"ascending":"descending"),i.setAttribute("aria-label",e+("asc"==(q[c].asSorting[o[0][2]+1]?q[c].asSorting[o[0][2]+1]:q[c].asSorting[0])?G.sSortAscending:G.sSortDescending))):i.setAttribute("aria-label",
-e+("asc"==q[c].asSorting[0]?G.sSortAscending:G.sSortDescending)):i.setAttribute("aria-label",e);a.bSorted=!0;h(a.oInstance).trigger("sort",a);a.oFeatures.bFilter?K(a,a.oPreviousSearch,1):(a.aiDisplay=a.aiDisplayMaster.slice(),a._iDisplayStart=0,y(a),x(a))}function ia(a,b,c,d){Ra(b,{},function(b){if(!1!==a.aoColumns[c].bSortable){var e=function(){var d,e;if(b.shiftKey){for(var f=!1,h=0;h<a.aaSorting.length;h++)if(a.aaSorting[h][0]==c){f=!0;d=a.aaSorting[h][0];e=a.aaSorting[h][2]+1;a.aoColumns[d].asSorting[e]?
-(a.aaSorting[h][1]=a.aoColumns[d].asSorting[e],a.aaSorting[h][2]=e):a.aaSorting.splice(h,1);break}!1===f&&a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0])}else 1==a.aaSorting.length&&a.aaSorting[0][0]==c?(d=a.aaSorting[0][0],e=a.aaSorting[0][2]+1,a.aoColumns[d].asSorting[e]||(e=0),a.aaSorting[0][1]=a.aoColumns[d].asSorting[e],a.aaSorting[0][2]=e):(a.aaSorting.splice(0,a.aaSorting.length),a.aaSorting.push([c,a.aoColumns[c].asSorting[0],0]));O(a)};a.oFeatures.bProcessing?(E(a,!0),setTimeout(function(){e();
-a.oFeatures.bServerSide||E(a,!1)},0)):e();"function"==typeof d&&d(a)}})}function P(a){var b,c,d,e,f,g=a.aoColumns.length,j=a.oClasses;for(b=0;b<g;b++)a.aoColumns[b].bSortable&&h(a.aoColumns[b].nTh).removeClass(j.sSortAsc+" "+j.sSortDesc+" "+a.aoColumns[b].sSortingClass);c=null!==a.aaSortingFixed?a.aaSortingFixed.concat(a.aaSorting):a.aaSorting.slice();for(b=0;b<a.aoColumns.length;b++)if(a.aoColumns[b].bSortable){f=a.aoColumns[b].sSortingClass;e=-1;for(d=0;d<c.length;d++)if(c[d][0]==b){f="asc"==c[d][1]?
-j.sSortAsc:j.sSortDesc;e=d;break}h(a.aoColumns[b].nTh).addClass(f);a.bJUI&&(f=h("span."+j.sSortIcon,a.aoColumns[b].nTh),f.removeClass(j.sSortJUIAsc+" "+j.sSortJUIDesc+" "+j.sSortJUI+" "+j.sSortJUIAscAllowed+" "+j.sSortJUIDescAllowed),f.addClass(-1==e?a.aoColumns[b].sSortingClassJUI:"asc"==c[e][1]?j.sSortJUIAsc:j.sSortJUIDesc))}else h(a.aoColumns[b].nTh).addClass(a.aoColumns[b].sSortingClass);f=j.sSortColumn;if(a.oFeatures.bSort&&a.oFeatures.bSortClasses){a=J(a);e=[];for(b=0;b<g;b++)e.push("");b=0;
-for(d=1;b<c.length;b++)j=parseInt(c[b][0],10),e[j]=f+d,3>d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b<c;b++)j=b%g,d=a[b].className,o=e[j],j=d.replace(f,o),j!=d?a[b].className=h.trim(j):0<o.length&&-1==d.indexOf(o)&&(a[b].className=d+" "+o)}}function ra(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b,c;b=a.oScroll.bInfinite;var d={iCreate:(new Date).getTime(),iStart:b?0:a._iDisplayStart,iEnd:b?a._iDisplayLength:a._iDisplayEnd,iLength:a._iDisplayLength,aaSorting:h.extend(!0,[],a.aaSorting),
-oSearch:h.extend(!0,{},a.oPreviousSearch),aoSearchCols:h.extend(!0,[],a.aoPreSearchCols),abVisCols:[]};b=0;for(c=a.aoColumns.length;b<c;b++)d.abVisCols.push(a.aoColumns[b].bVisible);A(a,"aoStateSaveParams","stateSaveParams",[a,d]);a.fnStateSave.call(a.oInstance,a,d)}}function Sa(a,b){if(a.oFeatures.bStateSave){var c=a.fnStateLoad.call(a.oInstance,a);if(c){var d=A(a,"aoStateLoadParams","stateLoadParams",[a,c]);if(-1===h.inArray(!1,d)){a.oLoadedState=h.extend(!0,{},c);a._iDisplayStart=c.iStart;a.iInitDisplayStart=
-c.iStart;a._iDisplayEnd=c.iEnd;a._iDisplayLength=c.iLength;a.aaSorting=c.aaSorting.slice();a.saved_aaSorting=c.aaSorting.slice();h.extend(a.oPreviousSearch,c.oSearch);h.extend(!0,a.aoPreSearchCols,c.aoSearchCols);b.saved_aoColumns=[];for(d=0;d<c.abVisCols.length;d++)b.saved_aoColumns[d]={},b.saved_aoColumns[d].bVisible=c.abVisCols[d];A(a,"aoStateLoaded","stateLoaded",[a,c])}}}}function s(a){for(var b=0;b<j.settings.length;b++)if(j.settings[b].nTable===a)return j.settings[b];return null}function T(a){for(var b=
-[],a=a.aoData,c=0,d=a.length;c<d;c++)null!==a[c].nTr&&b.push(a[c].nTr);return b}function J(a,b){var c=[],d,e,f,g,h,j;e=0;var o=a.aoData.length;b!==n&&(e=b,o=b+1);for(f=e;f<o;f++)if(j=a.aoData[f],null!==j.nTr){e=[];for(d=j.nTr.firstChild;d;)g=d.nodeName.toLowerCase(),("td"==g||"th"==g)&&e.push(d),d=d.nextSibling;g=d=0;for(h=a.aoColumns.length;g<h;g++)a.aoColumns[g].bVisible?c.push(e[g-d]):(c.push(j._anHidden[g]),d++)}return c}function D(a,b,c){a=null===a?"DataTables warning: "+c:"DataTables warning (table id = '"+
-a.sTableId+"'): "+c;if(0===b)if("alert"==j.ext.sErrMode)alert(a);else throw Error(a);else X.console&&console.log&&console.log(a)}function p(a,b,c,d){d===n&&(d=c);b[c]!==n&&(a[d]=b[c])}function Ta(a,b){var c,d;for(d in b)b.hasOwnProperty(d)&&(c=b[d],"object"===typeof e[d]&&null!==c&&!1===h.isArray(c)?h.extend(!0,a[d],c):a[d]=c);return a}function Ra(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&c(a)}).bind("selectstart.DT",function(){return!1})}
-function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function A(a,b,c,d){for(var b=a[b],e=[],f=b.length-1;0<=f;f--)e.push(b[f].fn.apply(a.oInstance,d));null!==c&&h(a.oInstance).trigger(c,d);return e}function Ua(a){var b=h('<div style="position:absolute; top:0; left:0; height:1px; width:1px; overflow:hidden"><div style="position:absolute; top:1px; left:1px; width:100px; overflow:scroll;"><div id="DT_BrowserTest" style="width:100%; height:10px;"></div></div></div>')[0];l.body.appendChild(b);a.oBrowser.bScrollOversize=
-100===h("#DT_BrowserTest",b)[0].offsetWidth?!0:!1;l.body.removeChild(b)}function Va(a){return function(){var b=[s(this[j.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return j.ext.oApi[a].apply(this,b)}}var U=/\[.*?\]$/,Wa=X.JSON?JSON.stringify:function(a){var b=typeof a;if("object"!==b||null===a)return"string"===b&&(a='"'+a+'"'),a+"";var c,d,e=[],f=h.isArray(a);for(c in a)d=a[c],b=typeof d,"string"===b?d='"'+d+'"':"object"===b&&null!==d&&(d=Wa(d)),e.push((f?"":'"'+c+'":')+d);return(f?
-"[":"{")+e+(f?"]":"}")};this.$=function(a,b){var c,d,e=[],f;d=s(this[j.ext.iApiIndex]);var g=d.aoData,o=d.aiDisplay,k=d.aiDisplayMaster;b||(b={});b=h.extend({},{filter:"none",order:"current",page:"all"},b);if("current"==b.page){c=d._iDisplayStart;for(d=d.fnDisplayEnd();c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("current"==b.order&&"none"==b.filter){c=0;for(d=k.length;c<d;c++)(f=g[k[c]].nTr)&&e.push(f)}else if("current"==b.order&&"applied"==b.filter){c=0;for(d=o.length;c<d;c++)(f=g[o[c]].nTr)&&e.push(f)}else if("original"==
-b.order&&"none"==b.filter){c=0;for(d=g.length;c<d;c++)(f=g[c].nTr)&&e.push(f)}else if("original"==b.order&&"applied"==b.filter){c=0;for(d=g.length;c<d;c++)f=g[c].nTr,-1!==h.inArray(c,o)&&f&&e.push(f)}else D(d,1,"Unknown selection options");e=h(e);c=e.filter(a);e=e.find(a);return h([].concat(h.makeArray(c),h.makeArray(e)))};this._=function(a,b){var c=[],d,e,f=this.$(a,b);d=0;for(e=f.length;d<e;d++)c.push(this.fnGetData(f[d]));return c};this.fnAddData=function(a,b){if(0===a.length)return[];var c=[],
-d,e=s(this[j.ext.iApiIndex]);if("object"===typeof a[0]&&null!==a[0])for(var f=0;f<a.length;f++){d=H(e,a[f]);if(-1==d)return c;c.push(d)}else{d=H(e,a);if(-1==d)return c;c.push(d)}e.aiDisplay=e.aiDisplayMaster.slice();(b===n||b)&&aa(e);return c};this.fnAdjustColumnSizing=function(a){var b=s(this[j.ext.iApiIndex]);k(b);a===n||a?this.fnDraw(!1):(""!==b.oScroll.sX||""!==b.oScroll.sY)&&this.oApi._fnScrollDraw(b)};this.fnClearTable=function(a){var b=s(this[j.ext.iApiIndex]);ga(b);(a===n||a)&&x(b)};this.fnClose=
-function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return(a=b.aoOpenRows[c].nTr.parentNode)&&a.removeChild(b.aoOpenRows[c].nTr),b.aoOpenRows.splice(c,1),0;return 1};this.fnDeleteRow=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,a="object"===typeof a?I(d,a):a,g=d.aoData.splice(a,1);e=0;for(f=d.aoData.length;e<f;e++)null!==d.aoData[e].nTr&&(d.aoData[e].nTr._DT_RowIndex=e);e=h.inArray(a,d.aiDisplay);d.asDataSearch.splice(e,1);ha(d.aiDisplayMaster,
-a);ha(d.aiDisplay,a);"function"===typeof b&&b.call(this,d,g);d._iDisplayStart>=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)y(d),x(d);return g};this.fnDestroy=function(a){var b=s(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,i,f,a=a===n?!1:a;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);if(!a){i=0;for(f=b.aoColumns.length;i<f;i++)!1===b.aoColumns[i].bVisible&&this.fnSetColumnVis(i,!0)}h(b.nTableWrapper).find("*").andSelf().unbind(".DT");
-h("tbody>tr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(h(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(h(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);h(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];P(b);h(T(b)).removeClass(b.asStripeClasses.join(" "));h("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc,
-b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(h("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),h("th, td",b.nTHead).each(function(){var a=h("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();h(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);i=0;for(f=b.aoData.length;i<f;i++)null!==b.aoData[i].nTr&&d.appendChild(b.aoData[i].nTr);!0===b.oFeatures.bAutoWidth&&
-(b.nTable.style.width=q(b.sDestroyWidth));if(f=b.asDestroyStripes.length){a=h(d).children("tr");for(i=0;i<f;i++)a.filter(":nth-child("+f+"n + "+i+")").addClass(b.asDestroyStripes[i])}i=0;for(f=j.settings.length;i<f;i++)j.settings[i]==b&&j.settings.splice(i,1);e=b=null};this.fnDraw=function(a){var b=s(this[j.ext.iApiIndex]);!1===a?(y(b),x(b)):aa(b)};this.fnFilter=function(a,b,c,d,e,f){var g=s(this[j.ext.iApiIndex]);if(g.oFeatures.bFilter){if(c===n||null===c)c=!1;if(d===n||null===d)d=!0;if(e===n||null===
-e)e=!0;if(f===n||null===f)f=!0;if(b===n||null===b){if(K(g,{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f},1),e&&g.aanFeatures.f){b=g.aanFeatures.f;c=0;for(d=b.length;c<d;c++)try{b[c]._DT_Input!=l.activeElement&&h(b[c]._DT_Input).val(a)}catch(o){h(b[c]._DT_Input).val(a)}}}else h.extend(g.aoPreSearchCols[b],{sSearch:a+"",bRegex:c,bSmart:d,bCaseInsensitive:f}),K(g,g.oPreviousSearch,1)}};this.fnGetData=function(a,b){var c=s(this[j.ext.iApiIndex]);if(a!==n){var d=a;if("object"===typeof a){var e=a.nodeName.toLowerCase();
-"tr"===e?d=I(c,a):"td"===e&&(d=I(c,a.parentNode),b=fa(c,d,a))}return b!==n?v(c,d,b,""):c.aoData[d]!==n?c.aoData[d]._aData:null}return Z(c)};this.fnGetNodes=function(a){var b=s(this[j.ext.iApiIndex]);return a!==n?b.aoData[a]!==n?b.aoData[a].nTr:null:T(b)};this.fnGetPosition=function(a){var b=s(this[j.ext.iApiIndex]),c=a.nodeName.toUpperCase();return"TR"==c?I(b,a):"TD"==c||"TH"==c?(c=I(b,a.parentNode),a=fa(b,c,a),[c,R(b,a),a]):null};this.fnIsOpen=function(a){for(var b=s(this[j.ext.iApiIndex]),c=0;c<
-b.aoOpenRows.length;c++)if(b.aoOpenRows[c].nParent==a)return!0;return!1};this.fnOpen=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e=T(d);if(-1!==h.inArray(a,e)){this.fnClose(a);var e=l.createElement("tr"),f=l.createElement("td");e.appendChild(f);f.className=c;f.colSpan=t(d);"string"===typeof b?f.innerHTML=b:h(f).html(b);b=h("tr",d.nTBody);-1!=h.inArray(a,b)&&h(e).insertAfter(a);d.aoOpenRows.push({nTr:e,nParent:a});return e}};this.fnPageChange=function(a,b){var c=s(this[j.ext.iApiIndex]);qa(c,a);
-y(c);(b===n||b)&&x(c)};this.fnSetColumnVis=function(a,b,c){var d=s(this[j.ext.iApiIndex]),e,f,g=d.aoColumns,h=d.aoData,o,m;if(g[a].bVisible!=b){if(b){for(e=f=0;e<a;e++)g[e].bVisible&&f++;m=f>=t(d);if(!m)for(e=a;e<g.length;e++)if(g[e].bVisible){o=e;break}e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(m?h[e].nTr.appendChild(h[e]._anHidden[a]):h[e].nTr.insertBefore(h[e]._anHidden[a],J(d,e)[o]))}else{e=0;for(f=h.length;e<f;e++)null!==h[e].nTr&&(o=J(d,e)[a],h[e]._anHidden[a]=o,o.parentNode.removeChild(o))}g[a].bVisible=
-b;W(d,d.aoHeader);d.nTFoot&&W(d,d.aoFooter);e=0;for(f=d.aoOpenRows.length;e<f;e++)d.aoOpenRows[e].nTr.colSpan=t(d);if(c===n||c)k(d),x(d);ra(d)}};this.fnSettings=function(){return s(this[j.ext.iApiIndex])};this.fnSort=function(a){var b=s(this[j.ext.iApiIndex]);b.aaSorting=a;O(b)};this.fnSortListener=function(a,b,c){ia(s(this[j.ext.iApiIndex]),a,b,c)};this.fnUpdate=function(a,b,c,d,e){var f=s(this[j.ext.iApiIndex]),b="object"===typeof b?I(f,b):b;if(h.isArray(a)&&c===n){f.aoData[b]._aData=a.slice();
-for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else if(h.isPlainObject(a)&&c===n){f.aoData[b]._aData=h.extend(!0,{},a);for(c=0;c<f.aoColumns.length;c++)this.fnUpdate(v(f,b,c),b,c,!1,!1)}else{F(f,b,c,a);var a=v(f,b,c,"display"),g=f.aoColumns[c];null!==g.fnRender&&(a=S(f,b,c),g.bUseRendered&&F(f,b,c,a));null!==f.aoData[b].nTr&&(J(f,b)[c].innerHTML=a)}c=h.inArray(b,f.aiDisplay);f.asDataSearch[c]=na(f,Y(f,b,"filter",r(f,"bSearchable")));(e===n||e)&&k(f);(d===n||d)&&aa(f);return 0};
-this.fnVersionCheck=j.ext.fnVersionCheck;this.oApi={_fnExternApiFunc:Va,_fnInitialise:ba,_fnInitComplete:$,_fnLanguageCompat:pa,_fnAddColumn:o,_fnColumnOptions:m,_fnAddData:H,_fnCreateTr:ea,_fnGatherData:ua,_fnBuildHead:va,_fnDrawHead:W,_fnDraw:x,_fnReDraw:aa,_fnAjaxUpdate:wa,_fnAjaxParameters:Ea,_fnAjaxUpdateDraw:Fa,_fnServerParams:ka,_fnAddOptionsHtml:xa,_fnFeatureHtmlTable:Ba,_fnScrollDraw:La,_fnAdjustColumnSizing:k,_fnFeatureHtmlFilter:za,_fnFilterComplete:K,_fnFilterCustom:Ia,_fnFilterColumn:Ha,
-_fnFilter:Ga,_fnBuildSearchArray:la,_fnBuildSearchRow:na,_fnFilterCreateSearch:ma,_fnDataToSearch:Ja,_fnSort:O,_fnSortAttachListener:ia,_fnSortingClasses:P,_fnFeatureHtmlPaginate:Da,_fnPageChange:qa,_fnFeatureHtmlInfo:Ca,_fnUpdateInfo:Ka,_fnFeatureHtmlLength:ya,_fnFeatureHtmlProcessing:Aa,_fnProcessingDisplay:E,_fnVisibleToColumnIndex:G,_fnColumnIndexToVisible:R,_fnNodeToDataIndex:I,_fnVisbleColumns:t,_fnCalculateEnd:y,_fnConvertToWidth:Ma,_fnCalculateColumnWidths:da,_fnScrollingWidthAdjust:Oa,_fnGetWidestNode:Na,
-_fnGetMaxLenString:Pa,_fnStringToCss:q,_fnDetectType:B,_fnSettingsFromNode:s,_fnGetDataMaster:Z,_fnGetTrNodes:T,_fnGetTdNodes:J,_fnEscapeRegex:oa,_fnDeleteIndex:ha,_fnReOrderIndex:u,_fnColumnOrdering:M,_fnLog:D,_fnClearTable:ga,_fnSaveState:ra,_fnLoadState:Sa,_fnCreateCookie:function(a,b,c,d,e){var f=new Date;f.setTime(f.getTime()+1E3*c);var c=X.location.pathname.split("/"),a=a+"_"+c.pop().replace(/[\/:]/g,"").toLowerCase(),g;null!==e?(g="function"===typeof h.parseJSON?h.parseJSON(b):eval("("+b+")"),
-b=e(a,g,f.toGMTString(),c.join("/")+"/")):b=a+"="+encodeURIComponent(b)+"; expires="+f.toGMTString()+"; path="+c.join("/")+"/";a=l.cookie.split(";");e=b.split(";")[0].length;f=[];if(4096<e+l.cookie.length+10){for(var j=0,o=a.length;j<o;j++)if(-1!=a[j].indexOf(d)){var k=a[j].split("=");try{(g=eval("("+decodeURIComponent(k[1])+")"))&&g.iCreate&&f.push({name:k[0],time:g.iCreate})}catch(m){}}for(f.sort(function(a,b){return b.time-a.time});4096<e+l.cookie.length+10;){if(0===f.length)return;d=f.pop();l.cookie=
-d.name+"=; expires=Thu, 01-Jan-1970 00:00:01 GMT; path="+c.join("/")+"/"}}l.cookie=b},_fnReadCookie:function(a){for(var b=X.location.pathname.split("/"),a=a+"_"+b[b.length-1].replace(/[\/:]/g,"").toLowerCase()+"=",b=l.cookie.split(";"),c=0;c<b.length;c++){for(var d=b[c];" "==d.charAt(0);)d=d.substring(1,d.length);if(0===d.indexOf(a))return decodeURIComponent(d.substring(a.length,d.length))}return null},_fnDetectHeader:V,_fnGetUniqueThs:N,_fnScrollBarWidth:Qa,_fnApplyToChildren:C,_fnMap:p,_fnGetRowData:Y,
-_fnGetCellData:v,_fnSetCellData:F,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:L,_fnApplyColumnDefs:ta,_fnBindAction:Ra,_fnExtend:Ta,_fnCallbackReg:z,_fnCallbackFire:A,_fnJsonString:Wa,_fnRender:S,_fnNodeToColumnIndex:fa,_fnInfoMacros:ja,_fnBrowserDetect:Ua,_fnGetColumns:r};h.extend(j.ext.oApi,this.oApi);for(var sa in j.ext.oApi)sa&&(this[sa]=Va(sa));var ca=this;this.each(function(){var a=0,b,c,d;c=this.getAttribute("id");var i=!1,f=!1;if("table"!=this.nodeName.toLowerCase())D(null,0,"Attempted to initialise DataTables on a node which is not a table: "+
-this.nodeName);else{a=0;for(b=j.settings.length;a<b;a++){if(j.settings[a].nTable==this){if(e===n||e.bRetrieve)return j.settings[a].oInstance;if(e.bDestroy){j.settings[a].oInstance.fnDestroy();break}else{D(j.settings[a],0,"Cannot reinitialise DataTable.\n\nTo retrieve the DataTables object for this table, pass no arguments or see the docs for bRetrieve and bDestroy");return}}if(j.settings[a].sTableId==this.id){j.settings.splice(a,1);break}}if(null===c||""===c)this.id=c="DataTables_Table_"+j.ext._oExternConfig.iNextUnique++;
-var g=h.extend(!0,{},j.models.oSettings,{nTable:this,oApi:ca.oApi,oInit:e,sDestroyWidth:h(this).width(),sInstance:c,sTableId:c});j.settings.push(g);g.oInstance=1===ca.length?ca:h(this).dataTable();e||(e={});e.oLanguage&&pa(e.oLanguage);e=Ta(h.extend(!0,{},j.defaults),e);p(g.oFeatures,e,"bPaginate");p(g.oFeatures,e,"bLengthChange");p(g.oFeatures,e,"bFilter");p(g.oFeatures,e,"bSort");p(g.oFeatures,e,"bInfo");p(g.oFeatures,e,"bProcessing");p(g.oFeatures,e,"bAutoWidth");p(g.oFeatures,e,"bSortClasses");
-p(g.oFeatures,e,"bServerSide");p(g.oFeatures,e,"bDeferRender");p(g.oScroll,e,"sScrollX","sX");p(g.oScroll,e,"sScrollXInner","sXInner");p(g.oScroll,e,"sScrollY","sY");p(g.oScroll,e,"bScrollCollapse","bCollapse");p(g.oScroll,e,"bScrollInfinite","bInfinite");p(g.oScroll,e,"iScrollLoadGap","iLoadGap");p(g.oScroll,e,"bScrollAutoCss","bAutoCss");p(g,e,"asStripeClasses");p(g,e,"asStripClasses","asStripeClasses");p(g,e,"fnServerData");p(g,e,"fnFormatNumber");p(g,e,"sServerMethod");p(g,e,"aaSorting");p(g,
-e,"aaSortingFixed");p(g,e,"aLengthMenu");p(g,e,"sPaginationType");p(g,e,"sAjaxSource");p(g,e,"sAjaxDataProp");p(g,e,"iCookieDuration");p(g,e,"sCookiePrefix");p(g,e,"sDom");p(g,e,"bSortCellsTop");p(g,e,"iTabIndex");p(g,e,"oSearch","oPreviousSearch");p(g,e,"aoSearchCols","aoPreSearchCols");p(g,e,"iDisplayLength","_iDisplayLength");p(g,e,"bJQueryUI","bJUI");p(g,e,"fnCookieCallback");p(g,e,"fnStateLoad");p(g,e,"fnStateSave");p(g.oLanguage,e,"fnInfoCallback");z(g,"aoDrawCallback",e.fnDrawCallback,"user");
-z(g,"aoServerParams",e.fnServerParams,"user");z(g,"aoStateSaveParams",e.fnStateSaveParams,"user");z(g,"aoStateLoadParams",e.fnStateLoadParams,"user");z(g,"aoStateLoaded",e.fnStateLoaded,"user");z(g,"aoRowCallback",e.fnRowCallback,"user");z(g,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(g,"aoHeaderCallback",e.fnHeaderCallback,"user");z(g,"aoFooterCallback",e.fnFooterCallback,"user");z(g,"aoInitComplete",e.fnInitComplete,"user");z(g,"aoPreDrawCallback",e.fnPreDrawCallback,"user");g.oFeatures.bServerSide&&
-g.oFeatures.bSort&&g.oFeatures.bSortClasses?z(g,"aoDrawCallback",P,"server_side_sort_classes"):g.oFeatures.bDeferRender&&z(g,"aoDrawCallback",P,"defer_sort_classes");e.bJQueryUI?(h.extend(g.oClasses,j.ext.oJUIClasses),e.sDom===j.defaults.sDom&&"lfrtip"===j.defaults.sDom&&(g.sDom='<"H"lfr>t<"F"ip>')):h.extend(g.oClasses,j.ext.oStdClasses);h(this).addClass(g.oClasses.sTable);if(""!==g.oScroll.sX||""!==g.oScroll.sY)g.oScroll.iBarWidth=Qa();g.iInitDisplayStart===n&&(g.iInitDisplayStart=e.iDisplayStart,
-g._iDisplayStart=e.iDisplayStart);e.bStateSave&&(g.oFeatures.bStateSave=!0,Sa(g,e),z(g,"aoDrawCallback",ra,"state_save"));null!==e.iDeferLoading&&(g.bDeferLoading=!0,a=h.isArray(e.iDeferLoading),g._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,g._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(g.oLanguage.sUrl=e.oLanguage.sUrl,h.getJSON(g.oLanguage.sUrl,null,function(a){pa(a);h.extend(true,g.oLanguage,e.oLanguage,a);ba(g)}),i=!0):h.extend(!0,
-g.oLanguage,e.oLanguage);null===e.asStripeClasses&&(g.asStripeClasses=[g.oClasses.sStripeOdd,g.oClasses.sStripeEven]);b=g.asStripeClasses.length;g.asDestroyStripes=[];if(b){c=!1;d=h(this).children("tbody").children("tr:lt("+b+")");for(a=0;a<b;a++)d.hasClass(g.asStripeClasses[a])&&(c=!0,g.asDestroyStripes.push(g.asStripeClasses[a]));c&&d.removeClass(g.asStripeClasses.join(" "))}c=[];a=this.getElementsByTagName("thead");0!==a.length&&(V(g.aoHeader,a[0]),c=N(g));if(null===e.aoColumns){d=[];a=0;for(b=
-c.length;a<b;a++)d.push(null)}else d=e.aoColumns;a=0;for(b=d.length;a<b;a++)e.saved_aoColumns!==n&&e.saved_aoColumns.length==b&&(null===d[a]&&(d[a]={}),d[a].bVisible=e.saved_aoColumns[a].bVisible),o(g,c?c[a]:null);ta(g,e.aoColumnDefs,d,function(a,b){m(g,a,b)});a=0;for(b=g.aaSorting.length;a<b;a++){g.aaSorting[a][0]>=g.aoColumns.length&&(g.aaSorting[a][0]=0);var k=g.aoColumns[g.aaSorting[a][0]];g.aaSorting[a][2]===n&&(g.aaSorting[a][2]=0);e.aaSorting===n&&g.saved_aaSorting===n&&(g.aaSorting[a][1]=
-k.asSorting[0]);c=0;for(d=k.asSorting.length;c<d;c++)if(g.aaSorting[a][1]==k.asSorting[c]){g.aaSorting[a][2]=c;break}}P(g);Ua(g);a=h(this).children("caption").each(function(){this._captionSide=h(this).css("caption-side")});b=h(this).children("thead");0===b.length&&(b=[l.createElement("thead")],this.appendChild(b[0]));g.nTHead=b[0];b=h(this).children("tbody");0===b.length&&(b=[l.createElement("tbody")],this.appendChild(b[0]));g.nTBody=b[0];g.nTBody.setAttribute("role","alert");g.nTBody.setAttribute("aria-live",
-"polite");g.nTBody.setAttribute("aria-relevant","all");b=h(this).children("tfoot");if(0===b.length&&0<a.length&&(""!==g.oScroll.sX||""!==g.oScroll.sY))b=[l.createElement("tfoot")],this.appendChild(b[0]);0<b.length&&(g.nTFoot=b[0],V(g.aoFooter,g.nTFoot));if(f)for(a=0;a<e.aaData.length;a++)H(g,e.aaData[a]);else ua(g);g.aiDisplay=g.aiDisplayMaster.slice();g.bInitialised=!0;!1===i&&ba(g)}});ca=null;return this};j.fnVersionCheck=function(e){for(var h=function(e,h){for(;e.length<h;)e+="0";return e},m=j.ext.sVersion.split("."),
-e=e.split("."),k="",n="",l=0,t=e.length;l<t;l++)k+=h(m[l],3),n+=h(e[l],3);return parseInt(k,10)>=parseInt(n,10)};j.fnIsDataTable=function(e){for(var h=j.settings,m=0;m<h.length;m++)if(h[m].nTable===e||h[m].nScrollHead===e||h[m].nScrollFoot===e)return!0;return!1};j.fnTables=function(e){var o=[];jQuery.each(j.settings,function(j,k){(!e||!0===e&&h(k.nTable).is(":visible"))&&o.push(k.nTable)});return o};j.version="1.9.4";j.settings=[];j.models={};j.models.ext={afnFiltering:[],afnSortData:[],aoFeatures:[],
-aTypes:[],fnVersionCheck:j.fnVersionCheck,iApiIndex:0,ofnSearch:{},oApi:{},oStdClasses:{},oJUIClasses:{},oPagination:{},oSort:{},sVersion:j.version,sErrMode:"alert",_oExternConfig:{iNextUnique:0}};j.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};j.models.oRow={nTr:null,_aData:[],_aSortData:[],_anHidden:[],_sRowStripe:""};j.models.oColumn={aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bUseRendered:null,bVisible:null,_bAutoType:!0,fnCreatedCell:null,fnGetData:null,
-fnRender:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};j.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,
-bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollAutoCss:!0,bScrollCollapse:!1,bScrollInfinite:!1,bServerSide:!1,bSort:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCookieCallback:null,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(e){if(1E3>e)return e;for(var h=e+"",e=h.split(""),j="",h=h.length,k=0;k<h;k++)0===k%3&&0!==k&&(j=this.oLanguage.sInfoThousands+j),j=e[h-k-1]+j;return j},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,
-fnRowCallback:null,fnServerData:function(e,j,m,k){k.jqXHR=h.ajax({url:e,data:j,success:function(e){e.sError&&k.oApi._fnLog(k,0,e.sError);h(k.oInstance).trigger("xhr",[k,e]);m(e)},dataType:"json",cache:!1,type:k.sServerMethod,error:function(e,h){"parsererror"==h&&k.oApi._fnLog(k,0,"DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error.")}})},fnServerParams:null,fnStateLoad:function(e){var e=this.oApi._fnReadCookie(e.sCookiePrefix+e.sInstance),j;try{j=
-"function"===typeof h.parseJSON?h.parseJSON(e):eval("("+e+")")}catch(m){j=null}return j},fnStateLoadParams:null,fnStateLoaded:null,fnStateSave:function(e,h){this.oApi._fnCreateCookie(e.sCookiePrefix+e.sInstance,this.oApi._fnJsonString(h),e.iCookieDuration,e.sCookiePrefix,e.fnCookieCallback)},fnStateSaveParams:null,iCookieDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iScrollLoadGap:100,iTabIndex:0,oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},
-oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sInfoThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},j.models.oSearch),sAjaxDataProp:"aaData",
-sAjaxSource:null,sCookiePrefix:"SpryMedia_DataTables_",sDom:"lfrtip",sPaginationType:"two_button",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET"};j.defaults.columns={aDataSort:null,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bUseRendered:!0,bVisible:!0,fnCreatedCell:null,fnRender:null,iDataSort:-1,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};j.models.oSettings={oFeatures:{bAutoWidth:null,
-bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortClasses:null,bStateSave:null},oScroll:{bAutoCss:null,bCollapse:null,bInfinite:null,iBarWidth:0,iLoadGap:null,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1},aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aoColumns:[],aoHeader:[],aoFooter:[],asDataSearch:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:null,
-asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,sPaginationType:"two_button",iCookieDuration:0,sCookiePrefix:"",fnCookieCallback:null,aoStateSave:[],aoStateLoad:[],
-oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iDisplayEnd:10,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsTotal,10):this.aiDisplayMaster.length},
-fnRecordsDisplay:function(){return this.oFeatures.bServerSide?parseInt(this._iRecordsDisplay,10):this.aiDisplay.length},fnDisplayEnd:function(){return this.oFeatures.bServerSide?!1===this.oFeatures.bPaginate||-1==this._iDisplayLength?this._iDisplayStart+this.aiDisplay.length:Math.min(this._iDisplayStart+this._iDisplayLength,this._iRecordsDisplay):this._iDisplayEnd},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null};j.ext=h.extend(!0,{},j.models.ext);h.extend(j.ext.oStdClasses,
-{sTable:"dataTable",sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active",sPageButtonStaticDisabled:"paginate_button paginate_button_disabled",sPageFirst:"first",sPagePrevious:"previous",sPageNext:"next",sPageLast:"last",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",
-sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",
-sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sFooterTH:"",sJUIHeader:"",sJUIFooter:""});h.extend(j.ext.oJUIClasses,j.ext.oStdClasses,{sPagePrevEnabled:"fg-button ui-button ui-state-default ui-corner-left",sPagePrevDisabled:"fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",sPageNextEnabled:"fg-button ui-button ui-state-default ui-corner-right",
-sPageNextDisabled:"fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",sPageJUINext:"ui-icon ui-icon-circle-arrow-e",sPageJUIPrev:"ui-icon ui-icon-circle-arrow-w",sPageButton:"fg-button ui-button ui-state-default",sPageButtonActive:"fg-button ui-button ui-state-default ui-state-disabled",sPageButtonStaticDisabled:"fg-button ui-button ui-state-default ui-state-disabled",sPageFirst:"first ui-corner-tl ui-corner-bl",sPageLast:"last ui-corner-tr ui-corner-br",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",
-sSortAsc:"ui-state-default",sSortDesc:"ui-state-default",sSortable:"ui-state-default",sSortableAsc:"ui-state-default",sSortableDesc:"ui-state-default",sSortableNone:"ui-state-default",sSortJUIAsc:"css_right ui-icon ui-icon-triangle-1-n",sSortJUIDesc:"css_right ui-icon ui-icon-triangle-1-s",sSortJUI:"css_right ui-icon ui-icon-carat-2-n-s",sSortJUIAscAllowed:"css_right ui-icon ui-icon-carat-1-n",sSortJUIDescAllowed:"css_right ui-icon ui-icon-carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",
-sScrollHead:"dataTables_scrollHead ui-state-default",sScrollFoot:"dataTables_scrollFoot ui-state-default",sFooterTH:"ui-state-default",sJUIHeader:"fg-toolbar ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix",sJUIFooter:"fg-toolbar ui-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix"});h.extend(j.ext.oPagination,{two_button:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)},k=!e.bJUI?'<a class="'+
-e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sPrevious+'</a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button">'+k.sNext+"</a>":'<a class="'+e.oClasses.sPagePrevDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUIPrev+'"></span></a><a class="'+e.oClasses.sPageNextDisabled+'" tabindex="'+e.iTabIndex+'" role="button"><span class="'+e.oClasses.sPageJUINext+'"></span></a>';h(j).append(k);var l=h("a",j),
-k=l[0],l=l[1];e.oApi._fnBindAction(k,{action:"previous"},n);e.oApi._fnBindAction(l,{action:"next"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",l.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),l.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var h=e.oClasses,j=e.aanFeatures.p,k,l=0,n=j.length;l<n;l++)if(k=j[l].firstChild)k.className=0===e._iDisplayStart?h.sPagePrevDisabled:h.sPagePrevEnabled,k=k.nextSibling,
-k.className=e.fnDisplayEnd()==e.fnRecordsDisplay()?h.sPageNextDisabled:h.sPageNextEnabled}},iFullNumbersShowPages:5,full_numbers:{fnInit:function(e,j,m){var k=e.oLanguage.oPaginate,l=e.oClasses,n=function(h){e.oApi._fnPageChange(e,h.data.action)&&m(e)};h(j).append('<a  tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageFirst+'">'+k.sFirst+'</a><a  tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPagePrevious+'">'+k.sPrevious+'</a><span></span><a tabindex="'+e.iTabIndex+'" class="'+
-l.sPageButton+" "+l.sPageNext+'">'+k.sNext+'</a><a tabindex="'+e.iTabIndex+'" class="'+l.sPageButton+" "+l.sPageLast+'">'+k.sLast+"</a>");var t=h("a",j),k=t[0],l=t[1],r=t[2],t=t[3];e.oApi._fnBindAction(k,{action:"first"},n);e.oApi._fnBindAction(l,{action:"previous"},n);e.oApi._fnBindAction(r,{action:"next"},n);e.oApi._fnBindAction(t,{action:"last"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",r.id=e.sTableId+"_next",t.id=e.sTableId+"_last")},
-fnUpdate:function(e,o){if(e.aanFeatures.p){var m=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(m/2),l=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),n=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,t="",r,B=e.oClasses,u,M=e.aanFeatures.p,L=function(h){e.oApi._fnBindAction(this,{page:h+r-1},function(h){e.oApi._fnPageChange(e,h.data.page);o(e);h.preventDefault()})};-1===e._iDisplayLength?n=k=r=1:l<m?(r=1,k=l):n<=k?(r=1,k=m):n>=l-k?(r=l-m+1,k=l):(r=n-Math.ceil(m/2)+1,k=r+m-1);for(m=r;m<=k;m++)t+=
-n!==m?'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButton+'">'+e.fnFormatNumber(m)+"</a>":'<a tabindex="'+e.iTabIndex+'" class="'+B.sPageButtonActive+'">'+e.fnFormatNumber(m)+"</a>";m=0;for(k=M.length;m<k;m++)u=M[m],u.hasChildNodes()&&(h("span:eq(0)",u).html(t).children("a").each(L),u=u.getElementsByTagName("a"),u=[u[0],u[1],u[u.length-2],u[u.length-1]],h(u).removeClass(B.sPageButton+" "+B.sPageButtonActive+" "+B.sPageButtonStaticDisabled),h([u[0],u[1]]).addClass(1==n?B.sPageButtonStaticDisabled:
-B.sPageButton),h([u[2],u[3]]).addClass(0===l||n===l||-1===e._iDisplayLength?B.sPageButtonStaticDisabled:B.sPageButton))}}}});h.extend(j.ext.oSort,{"string-pre":function(e){"string"!=typeof e&&(e=null!==e&&e.toString?e.toString():"");return e.toLowerCase()},"string-asc":function(e,h){return e<h?-1:e>h?1:0},"string-desc":function(e,h){return e<h?1:e>h?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,h){return e<h?-1:e>h?1:0},"html-desc":function(e,h){return e<
-h?1:e>h?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");return e},"date-asc":function(e,h){return e-h},"date-desc":function(e,h){return h-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,h){return e-h},"numeric-desc":function(e,h){return h-e}});h.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var h,j=!1;h=e.charAt(0);if(-1=="0123456789-".indexOf(h))return null;
-for(var k=1;k<e.length;k++){h=e.charAt(k);if(-1=="0123456789.".indexOf(h))return null;if("."==h){if(j)return null;j=!0}}return"numeric"},function(e){var h=Date.parse(e);return null!==h&&!isNaN(h)||"string"===typeof e&&0===e.length?"date":null},function(e){return"string"===typeof e&&-1!=e.indexOf("<")&&-1!=e.indexOf(">")?"html":null}]);h.fn.DataTable=j;h.fn.dataTable=j;h.fn.dataTableSettings=j.settings;h.fn.dataTableExt=j.ext};"function"===typeof define&&define.amd?define(["jquery"],L):jQuery&&!jQuery.fn.dataTable&&
-L(jQuery)})(window,document);
diff --git a/src/main/webapp/static/js/jquery/uilayout/jquery.layout-latest.js b/src/main/webapp/static/js/jquery/uilayout/jquery.layout-latest.js
deleted file mode 100644
index 8b729fff5e33eb87fff68c3063814ae4288060aa..0000000000000000000000000000000000000000
--- a/src/main/webapp/static/js/jquery/uilayout/jquery.layout-latest.js
+++ /dev/null
@@ -1,5938 +0,0 @@
-/**
- * @preserve
- * jquery.layout 1.3.0 - Release Candidate 30.79
- * $Date: 2013-01-12 08:00:00 (Sat, 12 Jan 2013) $
- * $Rev: 303007 $
- *
- * Copyright (c) 2012 
- *   Fabrizio Balliano (http://www.fabrizioballiano.net)
- *   Kevin Dalman (http://allpro.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.79
- *
- * Docs: http://layout.jquery-dev.net/documentation.html
- * Tips: http://layout.jquery-dev.net/tips.html
- * Help: http://groups.google.com/group/jquery-ui-layout
- */
-
-/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html
- * {!Object}	non-nullable type (never NULL)
- * {?string}	nullable type (sometimes NULL) - default for {Object}
- * {number=}	optional parameter
- * {*}			ALL types
- */
-/*	TODO for jQ 2.0 
- *	change .andSelf() to .addBack()
- *	$.fn.disableSelection won't work
- */
-
-// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars
-
-;(function ($) {
-
-// alias Math methods - used a lot!
-var	min		= Math.min
-,	max		= Math.max
-,	round	= Math.floor
-
-,	isStr	=  function (v) { return $.type(v) === "string"; }
-
-	/**
-	* @param {!Object}			Instance
-	* @param {Array.<string>}	a_fn
-	*/
-,	runPluginCallbacks = function (Instance, a_fn) {
-		if ($.isArray(a_fn))
-			for (var i=0, c=a_fn.length; i<c; i++) {
-				var fn = a_fn[i];
-				try {
-					if (isStr(fn)) // 'name' of a function
-						fn = eval(fn);
-					if ($.isFunction(fn))
-						g(fn)( Instance );
-				} catch (ex) {}
-			}
-		function g (f) { return f; }; // compiler hack
-	}
-;
-
-/*
- *	GENERIC $.layout METHODS - used by all layouts
- */
-$.layout = {
-
-	version:	"1.3.rc30.79"
-,	revision:	0.033007 // 1.3.0 final = 1.0300 - major(n+).minor(nn)+patch(nn+)
-
-	// $.layout.browser REPLACES $.browser
-,	browser:	{} // set below
-
-	// *PREDEFINED* EFFECTS & DEFAULTS 
-	// MUST list effect here - OR MUST set an fxSettings option (can be an empty hash: {})
-,	effects: {
-
-	//	Pane Open/Close Animations
-		slide: {
-			all:	{ duration:  "fast"	} // eg: duration: 1000, easing: "easeOutBounce"
-		,	north:	{ direction: "up"	}
-		,	south:	{ direction: "down"	}
-		,	east:	{ direction: "right"}
-		,	west:	{ direction: "left"	}
-		}
-	,	drop: {
-			all:	{ duration:  "slow"	}
-		,	north:	{ direction: "up"	}
-		,	south:	{ direction: "down"	}
-		,	east:	{ direction: "right"}
-		,	west:	{ direction: "left"	}
-		}
-	,	scale: {
-			all:	{ duration:	"fast"	}
-		}
-	//	these are not recommended, but can be used
-	,	blind:		{}
-	,	clip:		{}
-	,	explode:	{}
-	,	fade:		{}
-	,	fold:		{}
-	,	puff:		{}
-
-	//	Pane Resize Animations
-	,	size: {
-			all:	{ easing:	"swing"	}
-		}
-	}
-
-	// INTERNAL CONFIG DATA - DO NOT CHANGE THIS!
-,	config: {
-		optionRootKeys:	"effects,panes,north,south,west,east,center".split(",")
-	,	allPanes:		"north,south,west,east,center".split(",")
-	,	borderPanes:	"north,south,west,east".split(",")
-	,	oppositeEdge: {
-			north:	"south"
-		,	south:	"north"
-		,	east: 	"west"
-		,	west: 	"east"
-		}
-	//	offscreen data
-	,	offscreenCSS:	{ left: "-99999px", right: "auto" } // used by hide/close if useOffscreenClose=true
-	,	offscreenReset:	"offscreenReset" // key used for data
-	//	CSS used in multiple places
-	,	hidden:		{ visibility: "hidden" }
-	,	visible:	{ visibility: "visible" }
-	//	layout element settings
-	,	resizers: {
-			cssReq: {
-				position: 	"absolute"
-			,	padding: 	0
-			,	margin: 	0
-			,	fontSize:	"1px"
-			,	textAlign:	"left"	// to counter-act "center" alignment!
-			,	overflow: 	"hidden" // prevent toggler-button from overflowing
-			//	SEE $.layout.defaults.zIndexes.resizer_normal
-			}
-		,	cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
-				background: "#DDD"
-			,	border:		"none"
-			}
-		}
-	,	togglers: {
-			cssReq: {
-				position: 	"absolute"
-			,	display: 	"block"
-			,	padding: 	0
-			,	margin: 	0
-			,	overflow:	"hidden"
-			,	textAlign:	"center"
-			,	fontSize:	"1px"
-			,	cursor: 	"pointer"
-			,	zIndex: 	1
-			}
-		,	cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
-				background: "#AAA"
-			}
-		}
-	,	content: {
-			cssReq: {
-				position:	"relative" /* contain floated or positioned elements */
-			}
-		,	cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
-				overflow:	"auto"
-			,	padding:	"10px"
-			}
-		,	cssDemoPane: { // DEMO CSS - REMOVE scrolling from 'pane' when it has a content-div
-				overflow:	"hidden"
-			,	padding:	0
-			}
-		}
-	,	panes: { // defaults for ALL panes - overridden by 'per-pane settings' below
-			cssReq: {
-				position: 	"absolute"
-			,	margin:		0
-			//	$.layout.defaults.zIndexes.pane_normal
-			}
-		,	cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
-				padding:	"10px"
-			,	background:	"#FFF"
-			,	border:		"1px solid #BBB"
-			,	overflow:	"auto"
-			}
-		}
-	,	north: {
-			side:			"top"
-		,	sizeType:		"Height"
-		,	dir:			"horz"
-		,	cssReq: {
-				top: 		0
-			,	bottom: 	"auto"
-			,	left: 		0
-			,	right: 		0
-			,	width: 		"auto"
-			//	height: 	DYNAMIC
-			}
-		}
-	,	south: {
-			side:			"bottom"
-		,	sizeType:		"Height"
-		,	dir:			"horz"
-		,	cssReq: {
-				top: 		"auto"
-			,	bottom: 	0
-			,	left: 		0
-			,	right: 		0
-			,	width: 		"auto"
-			//	height: 	DYNAMIC
-			}
-		}
-	,	east: {
-			side:			"right"
-		,	sizeType:		"Width"
-		,	dir:			"vert"
-		,	cssReq: {
-				left: 		"auto"
-			,	right: 		0
-			,	top: 		"auto" // DYNAMIC
-			,	bottom: 	"auto" // DYNAMIC
-			,	height: 	"auto"
-			//	width: 		DYNAMIC
-			}
-		}
-	,	west: {
-			side:			"left"
-		,	sizeType:		"Width"
-		,	dir:			"vert"
-		,	cssReq: {
-				left: 		0
-			,	right: 		"auto"
-			,	top: 		"auto" // DYNAMIC
-			,	bottom: 	"auto" // DYNAMIC
-			,	height: 	"auto"
-			//	width: 		DYNAMIC
-			}
-		}
-	,	center: {
-			dir:			"center"
-		,	cssReq: {
-				left: 		"auto" // DYNAMIC
-			,	right: 		"auto" // DYNAMIC
-			,	top: 		"auto" // DYNAMIC
-			,	bottom: 	"auto" // DYNAMIC
-			,	height: 	"auto"
-			,	width: 		"auto"
-			}
-		}
-	}
-
-	// CALLBACK FUNCTION NAMESPACE - used to store reusable callback functions
-,	callbacks: {}
-
-,	getParentPaneElem: function (el) {
-		// must pass either a container or pane element
-		var $el = $(el)
-		,	layout = $el.data("layout") || $el.data("parentLayout");
-		if (layout) {
-			var $cont = layout.container;
-			// see if this container is directly-nested inside an outer-pane
-			if ($cont.data("layoutPane")) return $cont;
-			var $pane = $cont.closest("."+ $.layout.defaults.panes.paneClass);
-			// if a pane was found, return it
-			if ($pane.data("layoutPane")) return $pane;
-		}
-		return null;
-	}
-
-,	getParentPaneInstance: function (el) {
-		// must pass either a container or pane element
-		var $pane = $.layout.getParentPaneElem(el);
-		return $pane ? $pane.data("layoutPane") : null;
-	}
-
-,	getParentLayoutInstance: function (el) {
-		// must pass either a container or pane element
-		var $pane = $.layout.getParentPaneElem(el);
-		return $pane ? $pane.data("parentLayout") : null;
-	}
-
-,	getEventObject: function (evt) {
-		return typeof evt === "object" && evt.stopPropagation ? evt : null;
-	}
-,	parsePaneName: function (evt_or_pane) {
-		var evt = $.layout.getEventObject( evt_or_pane )
-		,	pane = evt_or_pane;
-		if (evt) {
-			// ALWAYS stop propagation of events triggered in Layout!
-			evt.stopPropagation();
-			pane = $(this).data("layoutEdge");
-		}
-		if (pane && !/^(west|east|north|south|center)$/.test(pane)) {
-			$.layout.msg('LAYOUT ERROR - Invalid pane-name: "'+ pane +'"');
-			pane = "error";
-		}
-		return pane;
-	}
-
-
-	// LAYOUT-PLUGIN REGISTRATION
-	// more plugins can added beyond this default list
-,	plugins: {
-		draggable:		!!$.fn.draggable // resizing
-	,	effects: {
-			core:		!!$.effects		// animimations (specific effects tested by initOptions)
-		,	slide:		$.effects && ($.effects.slide || ($.effects.effect && $.effects.effect.slide)) // default effect
-		}
-	}
-
-//	arrays of plugin or other methods to be triggered for events in *each layout* - will be passed 'Instance'
-,	onCreate:	[]	// runs when layout is just starting to be created - right after options are set
-,	onLoad:		[]	// runs after layout container and global events init, but before initPanes is called
-,	onReady:	[]	// runs after initialization *completes* - ie, after initPanes completes successfully
-,	onDestroy:	[]	// runs after layout is destroyed
-,	onUnload:	[]	// runs after layout is destroyed OR when page unloads
-,	afterOpen:	[]	// runs after setAsOpen() completes
-,	afterClose:	[]	// runs after setAsClosed() completes
-
-	/*
-	*	GENERIC UTILITY METHODS
-	*/
-
-	// calculate and return the scrollbar width, as an integer
-,	scrollbarWidth:		function () { return window.scrollbarWidth  || $.layout.getScrollbarSize('width'); }
-,	scrollbarHeight:	function () { return window.scrollbarHeight || $.layout.getScrollbarSize('height'); }
-,	getScrollbarSize:	function (dim) {
-		var $c	= $('<div style="position: absolute; top: -10000px; left: -10000px; width: 100px; height: 100px; overflow: scroll;"></div>').appendTo("body");
-		var d	= { width: $c.css("width") - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight };
-		$c.remove();
-		window.scrollbarWidth	= d.width;
-		window.scrollbarHeight	= d.height;
-		return dim.match(/^(width|height)$/) ? d[dim] : d;
-	}
-
-
-	/**
-	* Returns hash container 'display' and 'visibility'
-	*
-	* @see	$.swap() - swaps CSS, runs callback, resets CSS
-	* @param  {!Object}		$E				jQuery element
-	* @param  {boolean=}	[force=false]	Run even if display != none
-	* @return {!Object}						Returns current style props, if applicable
-	*/
-,	showInvisibly: function ($E, force) {
-		if ($E && $E.length && (force || $E.css("display") === "none")) { // only if not *already hidden*
-			var s = $E[0].style
-				// save ONLY the 'style' props because that is what we must restore
-			,	CSS = { display: s.display || '', visibility: s.visibility || '' };
-			// show element 'invisibly' so can be measured
-			$E.css({ display: "block", visibility: "hidden" });
-			return CSS;
-		}
-		return {};
-	}
-
-	/**
-	* Returns data for setting size of an element (container or a pane).
-	*
-	* @see  _create(), onWindowResize() for container, plus others for pane
-	* @return JSON  Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
-	*/
-,	getElementDimensions: function ($E, inset) {
-		var
-		//	dimensions hash - start with current data IF passed
-			d	= { css: {}, inset: {} }
-		,	x	= d.css			// CSS hash
-		,	i	= { bottom: 0 }	// TEMP insets (bottom = complier hack)
-		,	N	= $.layout.cssNum
-		,	off = $E.offset()
-		,	b, p, ei			// TEMP border, padding
-		;
-		d.offsetLeft = off.left;
-		d.offsetTop  = off.top;
-
-		if (!inset) inset = {}; // simplify logic below
-
-		$.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge
-			b = x["border" + e] = $.layout.borderWidth($E, e);
-			p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e);
-			ei = e.toLowerCase();
-			d.inset[ei] = inset[ei] >= 0 ? inset[ei] : p; // any missing insetX value = paddingX
-			i[ei] = d.inset[ei] + b; // total offset of content from outer side
-		});
-
-		x.width		= $E.width();
-		x.height	= $E.height();
-		x.top		= N($E,"top",true);
-		x.bottom	= N($E,"bottom",true);
-		x.left		= N($E,"left",true);
-		x.right		= N($E,"right",true);
-
-		d.outerWidth	= $E.outerWidth();
-		d.outerHeight	= $E.outerHeight();
-		// calc the TRUE inner-dimensions, even in quirks-mode!
-		d.innerWidth	= max(0, d.outerWidth  - i.left - i.right);
-		d.innerHeight	= max(0, d.outerHeight - i.top  - i.bottom);
-		// layoutWidth/Height is used in calcs for manual resizing
-		// layoutW/H only differs from innerW/H when in quirks-mode - then is like outerW/H
-		d.layoutWidth	= $E.innerWidth();
-		d.layoutHeight	= $E.innerHeight();
-
-		//if ($E.prop('tagName') === 'BODY') { debugData( d, $E.prop('tagName') ); } // DEBUG
-
-		//d.visible	= $E.is(":visible");// && x.width > 0 && x.height > 0;
-
-		return d;
-	}
-
-,	getElementStyles: function ($E, list) {
-		var
-			CSS	= {}
-		,	style	= $E[0].style
-		,	props	= list.split(",")
-		,	sides	= "Top,Bottom,Left,Right".split(",")
-		,	attrs	= "Color,Style,Width".split(",")
-		,	p, s, a, i, j, k
-		;
-		for (i=0; i < props.length; i++) {
-			p = props[i];
-			if (p.match(/(border|padding|margin)$/))
-				for (j=0; j < 4; j++) {
-					s = sides[j];
-					if (p === "border")
-						for (k=0; k < 3; k++) {
-							a = attrs[k];
-							CSS[p+s+a] = style[p+s+a];
-						}
-					else
-						CSS[p+s] = style[p+s];
-				}
-			else
-				CSS[p] = style[p];
-		};
-		return CSS
-	}
-
-	/**
-	* Return the innerWidth for the current browser/doctype
-	*
-	* @see  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
-	* @param  {Array.<Object>}	$E  Must pass a jQuery object - first element is processed
-	* @param  {number=}			outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized
-	* @return {number}			Returns the innerWidth of the elem by subtracting padding and borders
-	*/
-,	cssWidth: function ($E, outerWidth) {
-		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
-		if (outerWidth <= 0) return 0;
-
-		var bs	= !$.layout.browser.boxModel ? "border-box" : $.support.boxSizing ? $E.css("boxSizing") : "content-box"
-		,	b	= $.layout.borderWidth
-		,	n	= $.layout.cssNum
-		,	W	= outerWidth
-		;
-		// strip border and/or padding from outerWidth to get CSS Width
-		if (bs !== "border-box")
-			W -= (b($E, "Left") + b($E, "Right"));
-		if (bs === "content-box")
-			W -= (n($E, "paddingLeft") + n($E, "paddingRight"));
-		return max(0,W);
-	}
-
-	/**
-	* Return the innerHeight for the current browser/doctype
-	*
-	* @see  initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
-	* @param  {Array.<Object>}	$E  Must pass a jQuery object - first element is processed
-	* @param  {number=}			outerHeight  (optional) Can pass a width, allowing calculations BEFORE element is resized
-	* @return {number}			Returns the innerHeight of the elem by subtracting padding and borders
-	*/
-,	cssHeight: function ($E, outerHeight) {
-		// a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
-		if (outerHeight <= 0) return 0;
-
-		var bs	= !$.layout.browser.boxModel ? "border-box" : $.support.boxSizing ? $E.css("boxSizing") : "content-box"
-		,	b	= $.layout.borderWidth
-		,	n	= $.layout.cssNum
-		,	H	= outerHeight
-		;
-		// strip border and/or padding from outerHeight to get CSS Height
-		if (bs !== "border-box")
-			H -= (b($E, "Top") + b($E, "Bottom"));
-		if (bs === "content-box")
-			H -= (n($E, "paddingTop") + n($E, "paddingBottom"));
-		return max(0,H);
-	}
-
-	/**
-	* Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist
-	*
-	* @see  Called by many methods
-	* @param {Array.<Object>}	$E					Must pass a jQuery object - first element is processed
-	* @param {string}			prop				The name of the CSS property, eg: top, width, etc.
-	* @param {boolean=}			[allowAuto=false]	true = return 'auto' if that is value; false = return 0
-	* @return {(string|number)}						Usually used to get an integer value for position (top, left) or size (height, width)
-	*/
-,	cssNum: function ($E, prop, allowAuto) {
-		if (!$E.jquery) $E = $($E);
-		var CSS = $.layout.showInvisibly($E)
-		,	p	= $.css($E[0], prop, true)
-		,	v	= allowAuto && p=="auto" ? p : Math.round(parseFloat(p) || 0);
-		$E.css( CSS ); // RESET
-		return v;
-	}
-
-,	borderWidth: function (el, side) {
-		if (el.jquery) el = el[0];
-		var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left
-		return $.css(el, b+"Style", true) === "none" ? 0 : Math.round(parseFloat($.css(el, b+"Width", true)) || 0);
-	}
-
-	/**
-	* Mouse-tracking utility - FUTURE REFERENCE
-	*
-	* init: if (!window.mouse) {
-	*			window.mouse = { x: 0, y: 0 };
-	*			$(document).mousemove( $.layout.trackMouse );
-	*		}
-	*
-	* @param {Object}		evt
-	*
-,	trackMouse: function (evt) {
-		window.mouse = { x: evt.clientX, y: evt.clientY };
-	}
-	*/
-
-	/**
-	* SUBROUTINE for preventPrematureSlideClose option
-	*
-	* @param {Object}		evt
-	* @param {Object=}		el
-	*/
-,	isMouseOverElem: function (evt, el) {
-		var
-			$E	= $(el || this)
-		,	d	= $E.offset()
-		,	T	= d.top
-		,	L	= d.left
-		,	R	= L + $E.outerWidth()
-		,	B	= T + $E.outerHeight()
-		,	x	= evt.pageX	// evt.clientX ?
-		,	y	= evt.pageY	// evt.clientY ?
-		;
-		// if X & Y are < 0, probably means is over an open SELECT
-		return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B));
-	}
-
-	/**
-	* Message/Logging Utility
-	*
-	* @example $.layout.msg("My message");				// log text
-	* @example $.layout.msg("My message", true);		// alert text
-	* @example $.layout.msg({ foo: "bar" }, "Title");	// log hash-data, with custom title
-	* @example $.layout.msg({ foo: "bar" }, true, "Title", { sort: false }); -OR-
-	* @example $.layout.msg({ foo: "bar" }, "Title", { sort: false, display: true }); // alert hash-data
-	*
-	* @param {(Object|string)}			info			String message OR Hash/Array
-	* @param {(Boolean|string|Object)=}	[popup=false]	True means alert-box - can be skipped
-	* @param {(Object|string)=}			[debugTitle=""]	Title for Hash data - can be skipped
-	* @param {Object=}					[debugOpts]		Extra options for debug output
-	*/
-,	msg: function (info, popup, debugTitle, debugOpts) {
-		if ($.isPlainObject(info) && window.debugData) {
-			if (typeof popup === "string") {
-				debugOpts	= debugTitle;
-				debugTitle	= popup;
-			}
-			else if (typeof debugTitle === "object") {
-				debugOpts	= debugTitle;
-				debugTitle	= null;
-			}
-			var t = debugTitle || "log( <object> )"
-			,	o = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts);
-			if (popup === true || o.display)
-				debugData( info, t, o );
-			else if (window.console)
-				console.log(debugData( info, t, o ));
-		}
-		else if (popup)
-			alert(info);
-		else if (window.console)
-			console.log(info);
-		else {
-			var id	= "#layoutLogger"
-			,	$l = $(id);
-			if (!$l.length)
-				$l = createLog();
-			$l.children("ul").append('<li style="padding: 4px 10px; margin: 0; border-top: 1px solid #CCC;">'+ info.replace(/\</g,"&lt;").replace(/\>/g,"&gt;") +'</li>');
-		}
-
-		function createLog () {
-			var pos = $.support.fixedPosition ? 'fixed' : 'absolute'
-			,	$e = $('<div id="layoutLogger" style="position: '+ pos +'; top: 5px; z-index: 999999; max-width: 25%; overflow: hidden; border: 1px solid #000; border-radius: 5px; background: #FBFBFB; box-shadow: 0 2px 10px rgba(0,0,0,0.3);">'
-				+	'<div style="font-size: 13px; font-weight: bold; padding: 5px 10px; background: #F6F6F6; border-radius: 5px 5px 0 0; cursor: move;">'
-				+	'<span style="float: right; padding-left: 7px; cursor: pointer;" title="Remove Console" onclick="$(this).closest(\'#layoutLogger\').remove()">X</span>Layout console.log</div>'
-				+	'<ul style="font-size: 13px; font-weight: none; list-style: none; margin: 0; padding: 0 0 2px;"></ul>'
-				+ '</div>'
-				).appendTo("body");
-			$e.css('left', $(window).width() - $e.outerWidth() - 5)
-			if ($.ui.draggable) $e.draggable({ handle: ':first-child' });
-			return $e;
-		};
-	}
-
-};
-
-
-/*
- *	$.layout.browser REPLACES removed $.browser, with extra data
- *	Parsing code here adapted from jQuery 1.8 $.browse
- */
-var u = navigator.userAgent.toLowerCase()
-,	m = /(chrome)[ \/]([\w.]+)/.exec( u )
-	||	/(webkit)[ \/]([\w.]+)/.exec( u )
-	||	/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( u )
-	||	/(msie) ([\w.]+)/.exec( u )
-	||	u.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( u )
-	||	[]
-,	b = m[1] || ""
-,	v = m[2] || 0
-,	ie = b === "msie"
-;
-$.layout.browser = {
-	version:	v
-,	safari:		b === "webkit"	// webkit (NOT chrome) = safari
-,	webkit:		b === "chrome"	// chrome = webkit
-,	msie:		ie
-,	isIE6:		ie && v == 6
-	// ONLY IE reverts to old box-model - update for older jQ onReady
-,	boxModel:	!ie || $.support.boxModel !== false
-};
-if (b) $.layout.browser[b] = true; // set CURRENT browser
-/*	OLD versions of jQuery only set $.support.boxModel after page is loaded
- *	so if this is IE, use support.boxModel to test for quirks-mode (ONLY IE changes boxModel) */
-if (ie) $(function(){ $.layout.browser.boxModel = $.support.boxModel; });
-
-
-// DEFAULT OPTIONS
-$.layout.defaults = {
-/*
- *	LAYOUT & LAYOUT-CONTAINER OPTIONS
- *	- none of these options are applicable to individual panes
- */
-	name:						""			// Not required, but useful for buttons and used for the state-cookie
-,	containerClass:				"ui-layout-container" // layout-container element
-,	inset:						null		// custom container-inset values (override padding)
-,	scrollToBookmarkOnLoad:		true		// after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
-,	resizeWithWindow:			true		// bind thisLayout.resizeAll() to the window.resize event
-,	resizeWithWindowDelay:		200			// delay calling resizeAll because makes window resizing very jerky
-,	resizeWithWindowMaxDelay:	0			// 0 = none - force resize every XX ms while window is being resized
-,	maskPanesEarly:				false		// true = create pane-masks on resizer.mouseDown instead of waiting for resizer.dragstart
-,	onresizeall_start:			null		// CALLBACK when resizeAll() STARTS	- NOT pane-specific
-,	onresizeall_end:			null		// CALLBACK when resizeAll() ENDS	- NOT pane-specific
-,	onload_start:				null		// CALLBACK when Layout inits - after options initialized, but before elements
-,	onload_end:					null		// CALLBACK when Layout inits - after EVERYTHING has been initialized
-,	onunload_start:				null		// CALLBACK when Layout is destroyed OR onWindowUnload
-,	onunload_end:				null		// CALLBACK when Layout is destroyed OR onWindowUnload
-,	initPanes:					true		// false = DO NOT initialize the panes onLoad - will init later
-,	showErrorMessages:			true		// enables fatal error messages to warn developers of common errors
-,	showDebugMessages:			false		// display console-and-alert debug msgs - IF this Layout version _has_ debugging code!
-//	Changing this zIndex value will cause other zIndex values to automatically change
-,	zIndex:						null		// the PANE zIndex - resizers and masks will be +1
-//	DO NOT CHANGE the zIndex values below unless you clearly understand their relationships
-,	zIndexes: {								// set _default_ z-index values here...
-		pane_normal:			0			// normal z-index for panes
-	,	content_mask:			1			// applied to overlays used to mask content INSIDE panes during resizing
-	,	resizer_normal:			2			// normal z-index for resizer-bars
-	,	pane_sliding:			100			// applied to *BOTH* the pane and its resizer when a pane is 'slid open'
-	,	pane_animate:			1000		// applied to the pane when being animated - not applied to the resizer
-	,	resizer_drag:			10000		// applied to the CLONED resizer-bar when being 'dragged'
-	}
-,	errors: {
-		pane:					"pane"		// description of "layout pane element" - used only in error messages
-	,	selector:				"selector"	// description of "jQuery-selector" - used only in error messages
-	,	addButtonError:			"Error Adding Button\nInvalid "
-	,	containerMissing:		"UI Layout Initialization Error\nThe specified layout-container does not exist."
-	,	centerPaneMissing:		"UI Layout Initialization Error\nThe center-pane element does not exist.\nThe center-pane is a required element."
-	,	noContainerHeight:		"UI Layout Initialization Warning\nThe layout-container \"CONTAINER\" has no height.\nTherefore the layout is 0-height and hence 'invisible'!"
-	,	callbackError:			"UI Layout Callback Error\nThe EVENT callback is not a valid function."
-	}
-/*
- *	PANE DEFAULT SETTINGS
- *	- settings under the 'panes' key become the default settings for *all panes*
- *	- ALL pane-options can also be set specifically for each panes, which will override these 'default values'
- */
-,	panes: { // default options for 'all panes' - will be overridden by 'per-pane settings'
-		applyDemoStyles: 		false		// NOTE: renamed from applyDefaultStyles for clarity
-	,	closable:				true		// pane can open & close
-	,	resizable:				true		// when open, pane can be resized 
-	,	slidable:				true		// when closed, pane can 'slide open' over other panes - closes on mouse-out
-	,	initClosed:				false		// true = init pane as 'closed'
-	,	initHidden: 			false 		// true = init pane as 'hidden' - no resizer-bar/spacing
-	//	SELECTORS
-	//,	paneSelector:			""			// MUST be pane-specific - jQuery selector for pane
-	,	contentSelector:		".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane!
-	,	contentIgnoreSelector:	".ui-layout-ignore"	// element(s) to 'ignore' when measuring 'content'
-	,	findNestedContent:		false		// true = $P.find(contentSelector), false = $P.children(contentSelector)
-	//	GENERIC ROOT-CLASSES - for auto-generated classNames
-	,	paneClass:				"ui-layout-pane"	// Layout Pane
-	,	resizerClass:			"ui-layout-resizer"	// Resizer Bar
-	,	togglerClass:			"ui-layout-toggler"	// Toggler Button
-	,	buttonClass:			"ui-layout-button"	// CUSTOM Buttons	- eg: '[ui-layout-button]-toggle/-open/-close/-pin'
-	//	ELEMENT SIZE & SPACING
-	//,	size:					100			// MUST be pane-specific -initial size of pane
-	,	minSize:				0			// when manually resizing a pane
-	,	maxSize:				0			// ditto, 0 = no limit
-	,	spacing_open:			6			// space between pane and adjacent panes - when pane is 'open'
-	,	spacing_closed:			6			// ditto - when pane is 'closed'
-	,	togglerLength_open:		50			// Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides
-	,	togglerLength_closed: 	50			// 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
-	,	togglerAlign_open:		"center"	// top/left, bottom/right, center, OR...
-	,	togglerAlign_closed:	"center"	// 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
-	,	togglerContent_open:	""			// text or HTML to put INSIDE the toggler
-	,	togglerContent_closed:	""			// ditto
-	//	RESIZING OPTIONS
-	,	resizerDblClickToggle:	true		// 
-	,	autoResize:				true		// IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes
-	,	autoReopen:				true		// IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed
-	,	resizerDragOpacity:		1			// option for ui.draggable
-	//,	resizerCursor:			""			// MUST be pane-specific - cursor when over resizer-bar
-	,	maskContents:			false		// true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES
-	,	maskObjects:			false		// true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask
-	,	maskZindex:				null		// will override zIndexes.content_mask if specified - not applicable to iframe-panes
-	,	resizingGrid:			false		// grid size that the resizers will snap-to during resizing, eg: [20,20]
-	,	livePaneResizing:		false		// true = LIVE Resizing as resizer is dragged
-	,	liveContentResizing:	false		// true = re-measure header/footer heights as resizer is dragged
-	,	liveResizingTolerance:	1			// how many px change before pane resizes, to control performance
-	//	SLIDING OPTIONS
-	,	sliderCursor:			"pointer"	// cursor when resizer-bar will trigger 'sliding'
-	,	slideTrigger_open:		"click"		// click, dblclick, mouseenter
-	,	slideTrigger_close:		"mouseleave"// click, mouseleave
-	,	slideDelay_open:		300			// applies only for mouseenter event - 0 = instant open
-	,	slideDelay_close:		300			// applies only for mouseleave event (300ms is the minimum!)
-	,	hideTogglerOnSlide:		false		// when pane is slid-open, should the toggler show?
-	,	preventQuickSlideClose:	$.layout.browser.webkit // Chrome triggers slideClosed as it is opening
-	,	preventPrematureSlideClose: false	// handle incorrect mouseleave trigger, like when over a SELECT-list in IE
-	//	PANE-SPECIFIC TIPS & MESSAGES
-	,	tips: {
-			Open:				"Open"		// eg: "Open Pane"
-		,	Close:				"Close"
-		,	Resize:				"Resize"
-		,	Slide:				"Slide Open"
-		,	Pin:				"Pin"
-		,	Unpin:				"Un-Pin"
-		,	noRoomToOpen:		"Not enough room to show this panel."	// alert if user tries to open a pane that cannot
-		,	minSizeWarning:		"Panel has reached its minimum size"	// displays in browser statusbar
-		,	maxSizeWarning:		"Panel has reached its maximum size"	// ditto
-		}
-	//	HOT-KEYS & MISC
-	,	showOverflowOnHover:	false		// will bind allowOverflow() utility to pane.onMouseOver
-	,	enableCursorHotkey:		true		// enabled 'cursor' hotkeys
-	//,	customHotkey:			""			// MUST be pane-specific - EITHER a charCode OR a character
-	,	customHotkeyModifier:	"SHIFT"		// either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
-	//	PANE ANIMATION
-	//	NOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed
-	,	fxName:					"slide" 	// ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size'
-	,	fxSpeed:				null		// slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
-	,	fxSettings:				{}			// can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
-	,	fxOpacityFix:			true		// tries to fix opacity in IE to restore anti-aliasing after animation
-	,	animatePaneSizing:		false		// true = animate resizing after dragging resizer-bar OR sizePane() is called
-	/*  NOTE: Action-specific FX options are auto-generated from the options above if not specifically set:
-		fxName_open:			"slide"		// 'Open' pane animation
-		fnName_close:			"slide"		// 'Close' pane animation
-		fxName_size:			"slide"		// 'Size' pane animation - when animatePaneSizing = true
-		fxSpeed_open:			null
-		fxSpeed_close:			null
-		fxSpeed_size:			null
-		fxSettings_open:		{}
-		fxSettings_close:		{}
-		fxSettings_size:		{}
-	*/
-	//	CHILD/NESTED LAYOUTS
-	,	children:				null		// Layout-options for nested/child layout - even {} is valid as options
-	,	containerSelector:		''			// if child is NOT 'directly nested', a selector to find it/them (can have more than one child layout!)
-	,	initChildren:			true		// true = child layout will be created as soon as _this_ layout completes initialization
-	,	destroyChildren:		true		// true = destroy child-layout if this pane is destroyed
-	,	resizeChildren:			true		// true = trigger child-layout.resizeAll() when this pane is resized
-	//	EVENT TRIGGERING
-	,	triggerEventsOnLoad:	false		// true = trigger onopen OR onclose callbacks when layout initializes
-	,	triggerEventsDuringLiveResize: true	// true = trigger onresize callback REPEATEDLY if livePaneResizing==true
-	//	PANE CALLBACKS
-	,	onshow_start:			null		// CALLBACK when pane STARTS to Show	- BEFORE onopen/onhide_start
-	,	onshow_end:				null		// CALLBACK when pane ENDS being Shown	- AFTER  onopen/onhide_end
-	,	onhide_start:			null		// CALLBACK when pane STARTS to Close	- BEFORE onclose_start
-	,	onhide_end:				null		// CALLBACK when pane ENDS being Closed	- AFTER  onclose_end
-	,	onopen_start:			null		// CALLBACK when pane STARTS to Open
-	,	onopen_end:				null		// CALLBACK when pane ENDS being Opened
-	,	onclose_start:			null		// CALLBACK when pane STARTS to Close
-	,	onclose_end:			null		// CALLBACK when pane ENDS being Closed
-	,	onresize_start:			null		// CALLBACK when pane STARTS being Resized ***FOR ANY REASON***
-	,	onresize_end:			null		// CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
-	,	onsizecontent_start:	null		// CALLBACK when sizing of content-element STARTS
-	,	onsizecontent_end:		null		// CALLBACK when sizing of content-element ENDS
-	,	onswap_start:			null		// CALLBACK when pane STARTS to Swap
-	,	onswap_end:				null		// CALLBACK when pane ENDS being Swapped
-	,	ondrag_start:			null		// CALLBACK when pane STARTS being ***MANUALLY*** Resized
-	,	ondrag_end:				null		// CALLBACK when pane ENDS being ***MANUALLY*** Resized
-	}
-/*
- *	PANE-SPECIFIC SETTINGS
- *	- options listed below MUST be specified per-pane - they CANNOT be set under 'panes'
- *	- all options under the 'panes' key can also be set specifically for any pane
- *	- most options under the 'panes' key apply only to 'border-panes' - NOT the the center-pane
- */
-,	north: {
-		paneSelector:			".ui-layout-north"
-	,	size:					"auto"		// eg: "auto", "30%", .30, 200
-	,	resizerCursor:			"n-resize"	// custom = url(myCursor.cur)
-	,	customHotkey:			""			// EITHER a charCode (43) OR a character ("o")
-	}
-,	south: {
-		paneSelector:			".ui-layout-south"
-	,	size:					"auto"
-	,	resizerCursor:			"s-resize"
-	,	customHotkey:			""
-	}
-,	east: {
-		paneSelector:			".ui-layout-east"
-	,	size:					200
-	,	resizerCursor:			"e-resize"
-	,	customHotkey:			""
-	}
-,	west: {
-		paneSelector:			".ui-layout-west"
-	,	size:					200
-	,	resizerCursor:			"w-resize"
-	,	customHotkey:			""
-	}
-,	center: {
-		paneSelector:			".ui-layout-center"
-	,	minWidth:				0
-	,	minHeight:				0
-	}
-};
-
-$.layout.optionsMap = {
-	// layout/global options - NOT pane-options
-	layout: ("name,instanceKey,stateManagement,effects,inset,zIndexes,errors,"
-	+	"zIndex,scrollToBookmarkOnLoad,showErrorMessages,maskPanesEarly,"
-	+	"outset,resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,"
-	+	"onresizeall,onresizeall_start,onresizeall_end,onload,onload_start,onload_end,onunload,onunload_start,onunload_end").split(",")
-//	borderPanes: [ ALL options that are NOT specified as 'layout' ]
-	// default.panes options that apply to the center-pane (most options apply _only_ to border-panes)
-,	center: ("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad,"
-	+	"showOverflowOnHover,maskContents,maskObjects,liveContentResizing,"
-	+	"containerSelector,children,initChildren,resizeChildren,destroyChildren,"
-	+	"onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(",")
-	// options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key
-,	noDefault: ("paneSelector,resizerCursor,customHotkey").split(",")
-};
-
-/**
- * Processes options passed in converts flat-format data into subkey (JSON) format
- * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName
- * Plugins may also call this method so they can transform their own data
- *
- * @param  {!Object}	hash			Data/options passed by user - may be a single level or nested levels
- * @param  {boolean=}	[addKeys=false]	Should the primary layout.options keys be added if they do not exist?
- * @return {Object}						Returns hash of minWidth & minHeight
- */
-$.layout.transformData = function (hash, addKeys) {
-	var	json = addKeys ? { panes: {}, center: {} } : {} // init return object
-	,	branch, optKey, keys, key, val, i, c;
-
-	if (typeof hash !== "object") return json; // no options passed
-
-	// convert all 'flat-keys' to 'sub-key' format
-	for (optKey in hash) {
-		branch	= json;
-		val		= hash[ optKey ];
-		keys	= optKey.split("__"); // eg: west__size or north__fxSettings__duration
-		c		= keys.length - 1;
-		// convert underscore-delimited to subkeys
-		for (i=0; i <= c; i++) {
-			key = keys[i];
-			if (i === c) {	// last key = value
-				if ($.isPlainObject( val ))
-					branch[key] = $.layout.transformData( val ); // RECURSE
-				else
-					branch[key] = val;
-			}
-			else {
-				if (!branch[key])
-					branch[key] = {}; // create the subkey
-				// recurse to sub-key for next loop - if not done
-				branch = branch[key];
-			}
-		}
-	}
-	return json;
-};
-
-// INTERNAL CONFIG DATA - DO NOT CHANGE THIS!
-$.layout.backwardCompatibility = {
-	// data used by renameOldOptions()
-	map: {
-	//	OLD Option Name:			NEW Option Name
-		applyDefaultStyles:			"applyDemoStyles"
-	//	CHILD/NESTED LAYOUTS
-	,	childOptions:				"children"
-	,	initChildLayout:			"initChildren"
-	,	destroyChildLayout:			"destroyChildren"
-	,	resizeChildLayout:			"resizeChildren"
-	,	resizeNestedLayout:			"resizeChildren"
-	//	MISC Options
-	,	resizeWhileDragging:		"livePaneResizing"
-	,	resizeContentWhileDragging:	"liveContentResizing"
-	,	triggerEventsWhileDragging:	"triggerEventsDuringLiveResize"
-	,	maskIframesOnResize:		"maskContents"
-	//	STATE MANAGEMENT
-	,	useStateCookie:				"stateManagement.enabled"
-	,	"cookie.autoLoad":			"stateManagement.autoLoad"
-	,	"cookie.autoSave":			"stateManagement.autoSave"
-	,	"cookie.keys":				"stateManagement.stateKeys"
-	,	"cookie.name":				"stateManagement.cookie.name"
-	,	"cookie.domain":			"stateManagement.cookie.domain"
-	,	"cookie.path":				"stateManagement.cookie.path"
-	,	"cookie.expires":			"stateManagement.cookie.expires"
-	,	"cookie.secure":			"stateManagement.cookie.secure"
-	//	OLD Language options
-	,	noRoomToOpenTip:			"tips.noRoomToOpen"
-	,	togglerTip_open:			"tips.Close"	// open   = Close
-	,	togglerTip_closed:			"tips.Open"		// closed = Open
-	,	resizerTip:					"tips.Resize"
-	,	sliderTip:					"tips.Slide"
-	}
-
-/**
-* @param {Object}	opts
-*/
-,	renameOptions: function (opts) {
-		var map = $.layout.backwardCompatibility.map
-		,	oldData, newData, value
-		;
-		for (var itemPath in map) {
-			oldData	= getBranch( itemPath );
-			value	= oldData.branch[ oldData.key ];
-			if (value !== undefined) {
-				newData = getBranch( map[itemPath], true );
-				newData.branch[ newData.key ] = value;
-				delete oldData.branch[ oldData.key ];
-			}
-		}
-
-		/**
-		* @param {string}	path
-		* @param {boolean=}	[create=false]	Create path if does not exist
-		*/
-		function getBranch (path, create) {
-			var a = path.split(".") // split keys into array
-			,	c = a.length - 1
-			,	D = { branch: opts, key: a[c] } // init branch at top & set key (last item)
-			,	i = 0, k, undef;
-			for (; i<c; i++) { // skip the last key (data)
-				k = a[i];
-				if (D.branch[ k ] == undefined) { // child-key does not exist
-					if (create) {
-						D.branch = D.branch[ k ] = {}; // create child-branch
-					}
-					else // can't go any farther
-						D.branch = {}; // branch is undefined
-				}
-				else
-					D.branch = D.branch[ k ]; // get child-branch
-			}
-			return D;
-		};
-	}
-
-/**
-* @param {Object}	opts
-*/
-,	renameAllOptions: function (opts) {
-		var ren = $.layout.backwardCompatibility.renameOptions;
-		// rename root (layout) options
-		ren( opts );
-		// rename 'defaults' to 'panes'
-		if (opts.defaults) {
-			if (typeof opts.panes !== "object")
-				opts.panes = {};
-			$.extend(true, opts.panes, opts.defaults);
-			delete opts.defaults;
-		}
-		// rename options in the the options.panes key
-		if (opts.panes) ren( opts.panes );
-		// rename options inside *each pane key*, eg: options.west
-		$.each($.layout.config.allPanes, function (i, pane) {
-			if (opts[pane]) ren( opts[pane] );
-		});	
-		return opts;
-	}
-};
-
-
-
-
-/*	============================================================
- *	BEGIN WIDGET: $( selector ).layout( {options} );
- *	============================================================
- */
-$.fn.layout = function (opts) {
-	var
-
-	// local aliases to global data
-	browser	= $.layout.browser
-,	_c		= $.layout.config
-
-	// local aliases to utlity methods
-,	cssW	= $.layout.cssWidth
-,	cssH	= $.layout.cssHeight
-,	elDims	= $.layout.getElementDimensions
-,	styles	= $.layout.getElementStyles
-,	evtObj	= $.layout.getEventObject
-,	evtPane	= $.layout.parsePaneName
-
-/**
- * options - populated by initOptions()
- */
-,	options = $.extend(true, {}, $.layout.defaults)
-,	effects	= options.effects = $.extend(true, {}, $.layout.effects)
-
-/**
- * layout-state object
- */
-,	state = {
-		// generate unique ID to use for event.namespace so can unbind only events added by 'this layout'
-		id:				"layout"+ $.now()	// code uses alias: sID
-	,	initialized:	false
-	,	paneResizing:	false
-	,	panesSliding:	{}
-	,	container:	{ 	// list all keys referenced in code to avoid compiler error msgs
-			innerWidth:		0
-		,	innerHeight:	0
-		,	outerWidth:		0
-		,	outerHeight:	0
-		,	layoutWidth:	0
-		,	layoutHeight:	0
-		}
-	,	north:		{ childIdx: 0 }
-	,	south:		{ childIdx: 0 }
-	,	east:		{ childIdx: 0 }
-	,	west:		{ childIdx: 0 }
-	,	center:		{ childIdx: 0 }
-	}
-
-/**
- * parent/child-layout pointers
- */
-//,	hasParentLayout	= false	- exists ONLY inside Instance so can be set externally
-,	children = {
-		north:		null
-	,	south:		null
-	,	east:		null
-	,	west:		null
-	,	center:		null
-	}
-
-/*
- * ###########################
- *  INTERNAL HELPER FUNCTIONS
- * ###########################
- */
-
-	/**
-	* Manages all internal timers
-	*/
-,	timer = {
-		data:	{}
-	,	set:	function (s, fn, ms) { timer.clear(s); timer.data[s] = setTimeout(fn, ms); }
-	,	clear:	function (s) { var t=timer.data; if (t[s]) {clearTimeout(t[s]); delete t[s];} }
-	}
-
-	/**
-	* Alert or console.log a message - IF option is enabled.
-	*
-	* @param {(string|!Object)}	msg				Message (or debug-data) to display
-	* @param {boolean=}			[popup=false]	True by default, means 'alert', false means use console.log
-	* @param {boolean=}			[debug=false]	True means is a widget debugging message
-	*/
-,	_log = function (msg, popup, debug) {
-		var o = options;
-		if ((o.showErrorMessages && !debug) || (debug && o.showDebugMessages))
-			$.layout.msg( o.name +' / '+ msg, (popup !== false) );
-		return false;
-	}
-
-	/**
-	* Executes a Callback function after a trigger event, like resize, open or close
-	*
-	* @param {string}				evtName					Name of the layout callback, eg "onresize_start"
-	* @param {(string|boolean)=}	[pane=""]				This is passed only so we can pass the 'pane object' to the callback
-	* @param {(string|boolean)=}	[skipBoundEvents=false]	True = do not run events bound to the elements - only the callbacks set in options
-	*/
-,	_runCallbacks = function (evtName, pane, skipBoundEvents) {
-		var	hasPane	= pane && isStr(pane)
-		,	s		= hasPane ? state[pane] : state
-		,	o		= hasPane ? options[pane] : options
-		,	lName	= options.name
-			// names like onopen and onopen_end separate are interchangeable in options...
-		,	lng		= evtName + (evtName.match(/_/) ? "" : "_end")
-		,	shrt	= lng.match(/_end$/) ? lng.substr(0, lng.length - 4) : ""
-		,	fn		= o[lng] || o[shrt]
-		,	retVal	= "NC" // NC = No Callback
-		,	args	= []
-		,	$P
-		;
-		if ( !hasPane && $.type(pane) === 'boolean' ) {
-			skipBoundEvents = pane; // allow pane param to be skipped for Layout callback
-			pane = "";
-		}
-
-		// first trigger the callback set in the options
-		if (fn) {
-			try {
-				// convert function name (string) to function object
-				if (isStr( fn )) {
-					if (fn.match(/,/)) {
-						// function name cannot contain a comma, 
-						// so must be a function name AND a parameter to pass
-						args = fn.split(",")
-						,	fn = eval(args[0]);
-					}
-					else // just the name of an external function?
-						fn = eval(fn);
-				}
-				// execute the callback, if exists
-				if ($.isFunction( fn )) {
-					if (args.length)
-						retVal = g(fn)(args[1]); // pass the argument parsed from 'list'
-					else if ( hasPane )
-						// pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
-						retVal = g(fn)( pane, $Ps[pane], s, o, lName );
-					else // must be a layout/container callback - pass suitable info
-						retVal = g(fn)( Instance, s, o, lName );
-				}
-			}
-			catch (ex) {
-				_log( options.errors.callbackError.replace(/EVENT/, $.trim((pane || "") +" "+ lng)), false );
-				if ($.type(ex) === 'string' && string.length)
-					_log('Exception:  '+ ex, false );
-			}
-		}
-
-		// trigger additional events bound directly to the pane
-		if (!skipBoundEvents && retVal !== false) {
-			if ( hasPane ) { // PANE events can be bound to each pane-elements
-				$P	= $Ps[pane];
-				o	= options[pane];
-				s	= state[pane];
-				$P.triggerHandler('layoutpane'+ lng, [ pane, $P, s, o, lName ]);
-				if (shrt)
-					$P.triggerHandler('layoutpane'+ shrt, [ pane, $P, s, o, lName ]);
-			}
-			else { // LAYOUT events can be bound to the container-element
-				$N.triggerHandler('layout'+ lng, [ Instance, s, o, lName ]);
-				if (shrt)
-					$N.triggerHandler('layout'+ shrt, [ Instance, s, o, lName ]);
-			}
-		}
-
-		// ALWAYS resizeChildren after an onresize_end event - even during initialization
-		// IGNORE onsizecontent_end event because causes child-layouts to resize TWICE
-		if (hasPane && evtName === "onresize_end") // BAD: || evtName === "onsizecontent_end"
-			resizeChildren(pane+"", true); // compiler hack -force string
-
-		return retVal;
-
-		function g (f) { return f; }; // compiler hack
-	}
-
-
-	/**
-	* cure iframe display issues in IE & other browsers
-	*/
-,	_fixIframe = function (pane) {
-		if (browser.mozilla) return; // skip FireFox - it auto-refreshes iframes onShow
-		var $P = $Ps[pane];
-		// if the 'pane' is an iframe, do it
-		if (state[pane].tagName === "IFRAME")
-			$P.css(_c.hidden).css(_c.visible); 
-		else // ditto for any iframes INSIDE the pane
-			$P.find('IFRAME').css(_c.hidden).css(_c.visible);
-	}
-
-	/**
-	* @param  {string}		pane		Can accept ONLY a 'pane' (east, west, etc)
-	* @param  {number=}		outerSize	(optional) Can pass a width, allowing calculations BEFORE element is resized
-	* @return {number}		Returns the innerHeight/Width of el by subtracting padding and borders
-	*/
-,	cssSize = function (pane, outerSize) {
-		var fn = _c[pane].dir=="horz" ? cssH : cssW;
-		return fn($Ps[pane], outerSize);
-	}
-
-	/**
-	* @param  {string}		pane		Can accept ONLY a 'pane' (east, west, etc)
-	* @return {Object}		Returns hash of minWidth & minHeight
-	*/
-,	cssMinDims = function (pane) {
-		// minWidth/Height means CSS width/height = 1px
-		var	$P	= $Ps[pane]
-		,	dir	= _c[pane].dir
-		,	d	= {
-				minWidth:	1001 - cssW($P, 1000)
-			,	minHeight:	1001 - cssH($P, 1000)
-			}
-		;
-		if (dir === "horz") d.minSize = d.minHeight;
-		if (dir === "vert") d.minSize = d.minWidth;
-		return d;
-	}
-
-	// TODO: see if these methods can be made more useful...
-	// TODO: *maybe* return cssW/H from these so caller can use this info
-
-	/**
-	* @param {(string|!Object)}		el
-	* @param {number=}				outerWidth
-	* @param {boolean=}				[autoHide=false]
-	*/
-,	setOuterWidth = function (el, outerWidth, autoHide) {
-		var $E = el, w;
-		if (isStr(el)) $E = $Ps[el]; // west
-		else if (!el.jquery) $E = $(el);
-		w = cssW($E, outerWidth);
-		$E.css({ width: w });
-		if (w > 0) {
-			if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) {
-				$E.show().data('autoHidden', false);
-				if (!browser.mozilla) // FireFox refreshes iframes - IE does not
-					// make hidden, then visible to 'refresh' display after animation
-					$E.css(_c.hidden).css(_c.visible);
-			}
-		}
-		else if (autoHide && !$E.data('autoHidden'))
-			$E.hide().data('autoHidden', true);
-	}
-
-	/**
-	* @param {(string|!Object)}		el
-	* @param {number=}				outerHeight
-	* @param {boolean=}				[autoHide=false]
-	*/
-,	setOuterHeight = function (el, outerHeight, autoHide) {
-		var $E = el, h;
-		if (isStr(el)) $E = $Ps[el]; // west
-		else if (!el.jquery) $E = $(el);
-		h = cssH($E, outerHeight);
-		$E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent
-		if (h > 0 && $E.innerWidth() > 0) {
-			if (autoHide && $E.data('autoHidden')) {
-				$E.show().data('autoHidden', false);
-				if (!browser.mozilla) // FireFox refreshes iframes - IE does not
-					$E.css(_c.hidden).css(_c.visible);
-			}
-		}
-		else if (autoHide && !$E.data('autoHidden'))
-			$E.hide().data('autoHidden', true);
-	}
-
-
-	/**
-	* Converts any 'size' params to a pixel/integer size, if not already
-	* If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated
-	*
-	/**
-	* @param  {string}				pane
-	* @param  {(string|number)=}	size
-	* @param  {string=}				[dir]
-	* @return {number}
-	*/
-,	_parseSize = function (pane, size, dir) {
-		if (!dir) dir = _c[pane].dir;
-
-		if (isStr(size) && size.match(/%/))
-			size = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal
-
-		if (size === 0)
-			return 0;
-		else if (size >= 1)
-			return parseInt(size, 10);
-
-		var o = options, avail = 0;
-		if (dir=="horz") // north or south or center.minHeight
-			avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0);
-		else if (dir=="vert") // east or west or center.minWidth
-			avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0);
-
-		if (size === -1) // -1 == 100%
-			return avail;
-		else if (size > 0) // percentage, eg: .25
-			return round(avail * size);
-		else if (pane=="center")
-			return 0;
-		else { // size < 0 || size=='auto' || size==Missing || size==Invalid
-			// auto-size the pane
-			var	dim	= (dir === "horz" ? "height" : "width")
-			,	$P	= $Ps[pane]
-			,	$C	= dim === 'height' ? $Cs[pane] : false
-			,	vis	= $.layout.showInvisibly($P) // show pane invisibly if hidden
-			,	szP	= $P.css(dim) // SAVE current pane size
-			,	szC	= $C ? $C.css(dim) : 0 // SAVE current content size
-			;
-			$P.css(dim, "auto");
-			if ($C) $C.css(dim, "auto");
-			size = (dim === "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE
-			$P.css(dim, szP).css(vis); // RESET size & visibility
-			if ($C) $C.css(dim, szC);
-			return size;
-		}
-	}
-
-	/**
-	* Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added
-	*
-	* @param  {(string|!Object)}	pane
-	* @param  {boolean=}			[inclSpace=false]
-	* @return {number}				Returns EITHER Width for east/west panes OR Height for north/south panes
-	*/
-,	getPaneSize = function (pane, inclSpace) {
-		var 
-			$P	= $Ps[pane]
-		,	o	= options[pane]
-		,	s	= state[pane]
-		,	oSp	= (inclSpace ? o.spacing_open : 0)
-		,	cSp	= (inclSpace ? o.spacing_closed : 0)
-		;
-		if (!$P || s.isHidden)
-			return 0;
-		else if (s.isClosed || (s.isSliding && inclSpace))
-			return cSp;
-		else if (_c[pane].dir === "horz")
-			return $P.outerHeight() + oSp;
-		else // dir === "vert"
-			return $P.outerWidth() + oSp;
-	}
-
-	/**
-	* Calculate min/max pane dimensions and limits for resizing
-	*
-	* @param  {string}		pane
-	* @param  {boolean=}	[slide=false]
-	*/
-,	setSizeLimits = function (pane, slide) {
-		if (!isInitialized()) return;
-		var 
-			o				= options[pane]
-		,	s				= state[pane]
-		,	c				= _c[pane]
-		,	dir				= c.dir
-		,	type			= c.sizeType.toLowerCase()
-		,	isSliding		= (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param
-		,	$P				= $Ps[pane]
-		,	paneSpacing		= o.spacing_open
-		//	measure the pane on the *opposite side* from this pane
-		,	altPane			= _c.oppositeEdge[pane]
-		,	altS			= state[altPane]
-		,	$altP			= $Ps[altPane]
-		,	altPaneSize		= (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth()))
-		,	altPaneSpacing	= ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0)
-		//	limitSize prevents this pane from 'overlapping' opposite pane
-		,	containerSize	= (dir=="horz" ? sC.innerHeight : sC.innerWidth)
-		,	minCenterDims	= cssMinDims("center")
-		,	minCenterSize	= dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth)
-		//	if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them
-		,	limitSize		= (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing)))
-		,	minSize			= s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize )
-		,	maxSize			= s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize )
-		,	r				= s.resizerPosition = {} // used to set resizing limits
-		,	top				= sC.inset.top
-		,	left			= sC.inset.left
-		,	W				= sC.innerWidth
-		,	H				= sC.innerHeight
-		,	rW				= o.spacing_open // subtract resizer-width to get top/left position for south/east
-		;
-		switch (pane) {
-			case "north":	r.min = top + minSize;
-							r.max = top + maxSize;
-							break;
-			case "west":	r.min = left + minSize;
-							r.max = left + maxSize;
-							break;
-			case "south":	r.min = top + H - maxSize - rW;
-							r.max = top + H - minSize - rW;
-							break;
-			case "east":	r.min = left + W - maxSize - rW;
-							r.max = left + W - minSize - rW;
-							break;
-		};
-	}
-
-	/**
-	* Returns data for setting the size/position of center pane. Also used to set Height for east/west panes
-	*
-	* @return JSON  Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
-	*/
-,	calcNewCenterPaneDims = function () {
-		var d = {
-			top:	getPaneSize("north", true) // true = include 'spacing' value for pane
-		,	bottom:	getPaneSize("south", true)
-		,	left:	getPaneSize("west", true)
-		,	right:	getPaneSize("east", true)
-		,	width:	0
-		,	height:	0
-		};
-
-		// NOTE: sC = state.container
-		// calc center-pane outer dimensions
-		d.width		= sC.innerWidth - d.left - d.right;  // outerWidth
-		d.height	= sC.innerHeight - d.bottom - d.top; // outerHeight
-		// add the 'container border/padding' to get final positions relative to the container
-		d.top		+= sC.inset.top;
-		d.bottom	+= sC.inset.bottom;
-		d.left		+= sC.inset.left;
-		d.right		+= sC.inset.right;
-
-		return d;
-	}
-
-
-	/**
-	* @param {!Object}		el
-	* @param {boolean=}		[allStates=false]
-	*/
-,	getHoverClasses = function (el, allStates) {
-		var
-			$El		= $(el)
-		,	type	= $El.data("layoutRole")
-		,	pane	= $El.data("layoutEdge")
-		,	o		= options[pane]
-		,	root	= o[type +"Class"]
-		,	_pane	= "-"+ pane // eg: "-west"
-		,	_open	= "-open"
-		,	_closed	= "-closed"
-		,	_slide	= "-sliding"
-		,	_hover	= "-hover " // NOTE the trailing space
-		,	_state	= $El.hasClass(root+_closed) ? _closed : _open
-		,	_alt	= _state === _closed ? _open : _closed
-		,	classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover)
-		;
-		if (allStates) // when 'removing' classes, also remove alternate-state classes
-			classes += (root+_alt+_hover) + (root+_pane+_alt+_hover);
-
-		if (type=="resizer" && $El.hasClass(root+_slide))
-			classes += (root+_slide+_hover) + (root+_pane+_slide+_hover);
-
-		return $.trim(classes);
-	}
-,	addHover	= function (evt, el) {
-		var $E = $(el || this);
-		if (evt && $E.data("layoutRole") === "toggler")
-			evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar
-		$E.addClass( getHoverClasses($E) );
-	}
-,	removeHover	= function (evt, el) {
-		var $E = $(el || this);
-		$E.removeClass( getHoverClasses($E, true) );
-	}
-
-,	onResizerEnter	= function (evt) { // ALSO called by toggler.mouseenter
-		var pane	= $(this).data("layoutEdge")
-		,	s		= state[pane]
-		;
-		// ignore closed-panes and mouse moving back & forth over resizer!
-		// also ignore if ANY pane is currently resizing
-		if ( s.isClosed || s.isResizing || state.paneResizing ) return;
-
-		if ($.fn.disableSelection)
-			$("body").disableSelection();
-		if (options.maskPanesEarly)
-			showMasks( pane, { resizing: true });
-	}
-,	onResizerLeave	= function (evt, el) {
-		var	e		= el || this // el is only passed when called by the timer
-		,	pane	= $(e).data("layoutEdge")
-		,	name	= pane +"ResizerLeave"
-		;
-		timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set
-		timer.clear(name); // cancel enableSelection timer - may re/set below
-		// this method calls itself on a timer because it needs to allow
-		// enough time for dragging to kick-in and set the isResizing flag
-		// dragging has a 100ms delay set, so this delay must be >100
-		if (!el) // 1st call - mouseleave event
-			timer.set(name, function(){ onResizerLeave(evt, e); }, 200);
-		// if user is resizing, then dragStop will enableSelection(), so can skip it here
-		else if ( !state.paneResizing ) { // 2nd call - by timer
-			if ($.fn.enableSelection)
-				$("body").enableSelection();
-			if (options.maskPanesEarly)
-				hideMasks();
-		}
-	}
-
-/*
- * ###########################
- *   INITIALIZATION METHODS
- * ###########################
- */
-
-	/**
-	* Initialize the layout - called automatically whenever an instance of layout is created
-	*
-	* @see  none - triggered onInit
-	* @return  mixed	true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort
-	*/
-,	_create = function () {
-		// initialize config/options
-		initOptions();
-		var o = options
-		,	s = state;
-
-		// TEMP state so isInitialized returns true during init process
-		s.creatingLayout = true;
-
-		// init plugins for this layout, if there are any (eg: stateManagement)
-		runPluginCallbacks( Instance, $.layout.onCreate );
-
-		// options & state have been initialized, so now run beforeLoad callback
-		// onload will CANCEL layout creation if it returns false
-		if (false === _runCallbacks("onload_start"))
-			return 'cancel';
-
-		// initialize the container element
-		_initContainer();
-
-		// bind hotkey function - keyDown - if required
-		initHotkeys();
-
-		// bind window.onunload
-		$(window).bind("unload."+ sID, unload);
-
-		// init plugins for this layout, if there are any (eg: customButtons)
-		runPluginCallbacks( Instance, $.layout.onLoad );
-
-		// if layout elements are hidden, then layout WILL NOT complete initialization!
-		// initLayoutElements will set initialized=true and run the onload callback IF successful
-		if (o.initPanes) _initLayoutElements();
-
-		delete s.creatingLayout;
-
-		return state.initialized;
-	}
-
-	/**
-	* Initialize the layout IF not already
-	*
-	* @see  All methods in Instance run this test
-	* @return  boolean	true = layoutElements have been initialized | false = panes are not initialized (yet)
-	*/
-,	isInitialized = function () {
-		if (state.initialized || state.creatingLayout) return true;	// already initialized
-		else return _initLayoutElements();	// try to init panes NOW
-	}
-
-	/**
-	* Initialize the layout - called automatically whenever an instance of layout is created
-	*
-	* @see  _create() & isInitialized
-	* @param {boolean=}		[retry=false]	// indicates this is a 2nd try
-	* @return  An object pointer to the instance created
-	*/
-,	_initLayoutElements = function (retry) {
-		// initialize config/options
-		var o = options;
-		// CANNOT init panes inside a hidden container!
-		if (!$N.is(":visible")) {
-			// handle Chrome bug where popup window 'has no height'
-			// if layout is BODY element, try again in 50ms
-			// SEE: http://layout.jquery-dev.net/samples/test_popup_window.html
-			if ( !retry && browser.webkit && $N[0].tagName === "BODY" )
-				setTimeout(function(){ _initLayoutElements(true); }, 50);
-			return false;
-		}
-
-		// a center pane is required, so make sure it exists
-		if (!getPane("center").length) {
-			return _log( o.errors.centerPaneMissing );
-		}
-
-		// TEMP state so isInitialized returns true during init process
-		state.creatingLayout = true;
-
-		// update Container dims
-		$.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT include insetX values
-
-		// initialize all layout elements
-		initPanes();	// size & position panes - calls initHandles() - which calls initResizable()
-
-		if (o.scrollToBookmarkOnLoad) {
-			var l = self.location;
-			if (l.hash) l.replace( l.hash ); // scrollTo Bookmark
-		}
-
-		// check to see if this layout 'nested' inside a pane
-		if (Instance.hasParentLayout)
-			o.resizeWithWindow = false;
-		// bind resizeAll() for 'this layout instance' to window.resize event
-		else if (o.resizeWithWindow)
-			$(window).bind("resize."+ sID, windowResize);
-
-		delete state.creatingLayout;
-		state.initialized = true;
-
-		// init plugins for this layout, if there are any
-		runPluginCallbacks( Instance, $.layout.onReady );
-
-		// now run the onload callback, if exists
-		_runCallbacks("onload_end");
-
-		return true; // elements initialized successfully
-	}
-
-	/**
-	* Initialize nested layouts for a specific pane - can optionally pass layout-options
-	*
-	* @param {(string|Object)}	evt_or_pane	The pane being opened, ie: north, south, east, or west
-	* @param {Object=}			[opts]		Layout-options - if passed, will OVERRRIDE options[pane].children
-	* @return  An object pointer to the layout instance created - or null
-	*/
-,	createChildren = function (evt_or_pane, opts) {
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$P	= $Ps[pane]
-		;
-		if (!$P) return;
-		var	$C	= $Cs[pane]
-		,	s	= state[pane]
-		,	o	= options[pane]
-		,	sm	= options.stateManagement || {}
-		,	cos = opts ? (o.children = opts) : o.children
-		;
-		if ( $.isPlainObject( cos ) )
-			cos = [ cos ]; // convert a hash to a 1-elem array
-		else if (!cos || !$.isArray( cos ))
-			return;
-
-		$.each( cos, function (idx, co) {
-			if ( !$.isPlainObject( co ) ) return;
-
-			// determine which element is supposed to be the 'child container'
-			// if pane has a 'containerSelector' OR a 'content-div', use those instead of the pane
-			var $containers = co.containerSelector ? $P.find( co.containerSelector ) : ($C || $P);
-
-			$containers.each(function(){
-				var $cont	= $(this)
-				,	child	= $cont.data("layout") //	see if a child-layout ALREADY exists on this element
-				;
-				// if no layout exists, but children are set, try to create the layout now
-				if (!child) {
-					// TODO: see about moving this to the stateManagement plugin, as a method
-					// set a unique child-instance key for this layout, if not already set
-					setInstanceKey({ container: $cont, options: co }, s );
-					// If THIS layout has a hash in stateManagement.autoLoad,
-					// then see if it also contains state-data for this child-layout
-					// If so, copy the stateData to child.options.stateManagement.autoLoad
-					if ( sm.includeChildren && state.stateData[pane] ) {
-						//	THIS layout's state was cached when its state was loaded
-						var	paneChildren = state.stateData[pane].children || {}
-						,	childState	= paneChildren[ co.instanceKey ]
-						,	co_sm		= co.stateManagement || (co.stateManagement = { autoLoad: true })
-						;
-						// COPY the stateData into the autoLoad key
-						if ( co_sm.autoLoad === true && childState ) {
-							co_sm.autoSave			= false; // disable autoSave because saving handled by parent-layout
-							co_sm.includeChildren	= true;  // cascade option - FOR NOW
-							co_sm.autoLoad = $.extend(true, {}, childState); // COPY the state-hash
-						}
-					}
-
-					// create the layout
-					child = $cont.layout( co );
-
-					// if successful, update data
-					if (child) {
-						// add the child and update all layout-pointers
-						// MAY have already been done by child-layout calling parent.refreshChildren()
-						refreshChildren( pane, child );
-					}
-				}
-			});
-		});
-	}
-
-,	setInstanceKey = function (child, parentPaneState) {
-		// create a named key for use in state and instance branches
-		var	$c	= child.container
-		,	o	= child.options
-		,	sm	= o.stateManagement
-		,	key	= o.instanceKey || $c.data("layoutInstanceKey")
-		;
-		if (!key) key = (sm && sm.cookie ? sm.cookie.name : '') || o.name; // look for a name/key
-		if (!key) key = "layout"+ (++parentPaneState.childIdx);	// if no name/key found, generate one
-		else key = key.replace(/[^\w-]/gi, '_').replace(/_{2,}/g, '_');	 // ensure is valid as a hash key
-		o.instanceKey = key;
-		$c.data("layoutInstanceKey", key); // useful if layout is destroyed and then recreated
-		return key;
-	}
-
-	/**
-	* @param {string}		pane		The pane being opened, ie: north, south, east, or west
-	* @param {Object=}		newChild	New child-layout Instance to add to this pane
-	*/
-,	refreshChildren = function (pane, newChild) {
-		var	$P	= $Ps[pane]
-		,	pC	= children[pane]
-		,	s	= state[pane]
-		,	o
-		;
-		// check for destroy()ed layouts and update the child pointers & arrays
-		if ($.isPlainObject( pC )) {
-			$.each( pC, function (key, child) {
-				if (child.destroyed) delete pC[key]
-			});
-			// if no more children, remove the children hash
-			if ($.isEmptyObject( pC ))
-				pC = children[pane] = null; // clear children hash
-		}
-
-		// see if there is a directly-nested layout inside this pane
-		// if there is, then there can be only ONE child-layout, so check that...
-		if (!newChild && !pC) {
-			newChild = $P.data("layout");
-		}
-
-		// if a newChild instance was passed, add it to children[pane]
-		if (newChild) {
-			// update child.state
-			newChild.hasParentLayout = true; // set parent-flag in child
-			// instanceKey is a key-name used in both state and children
-			o = newChild.options;
-			// set a unique child-instance key for this layout, if not already set
-			setInstanceKey( newChild, s );
-			// add pointer to pane.children hash
-			if (!pC) pC = children[pane] = {}; // create an empty children hash
-			pC[ o.instanceKey ] = newChild.container.data("layout"); // add childLayout instance
-		}
-
-		// ALWAYS refresh the pane.children alias, even if null
-		Instance[pane].children = children[pane];
-
-		// if newChild was NOT passed - see if there is a child layout NOW
-		if (!newChild) {
-			createChildren(pane); // MAY create a child and re-call this method
-		}
-	}
-
-,	windowResize = function () {
-		var	o = options
-		,	delay = Number(o.resizeWithWindowDelay);
-		if (delay < 10) delay = 100; // MUST have a delay!
-		// resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway
-		timer.clear("winResize"); // if already running
-		timer.set("winResize", function(){
-			timer.clear("winResize");
-			timer.clear("winResizeRepeater");
-			var dims = elDims( $N, o.inset );
-			// only trigger resizeAll() if container has changed size
-			if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight)
-				resizeAll();
-		}, delay);
-		// ALSO set fixed-delay timer, if not already running
-		if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater();
-	}
-
-,	setWindowResizeRepeater = function () {
-		var delay = Number(options.resizeWithWindowMaxDelay);
-		if (delay > 0)
-			timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay);
-	}
-
-,	unload = function () {
-		var o = options;
-
-		_runCallbacks("onunload_start");
-
-		// trigger plugin callabacks for this layout (eg: stateManagement)
-		runPluginCallbacks( Instance, $.layout.onUnload );
-
-		_runCallbacks("onunload_end");
-	}
-
-	/**
-	* Validate and initialize container CSS and events
-	*
-	* @see  _create()
-	*/
-,	_initContainer = function () {
-		var
-			N		= $N[0]	
-		,	$H		= $("html")
-		,	tag		= sC.tagName = N.tagName
-		,	id		= sC.id = N.id
-		,	cls		= sC.className = N.className
-		,	o		= options
-		,	name	= o.name
-		,	props	= "position,margin,padding,border"
-		,	css		= "layoutCSS"
-		,	CSS		= {}
-		,	hid		= "hidden" // used A LOT!
-		//	see if this container is a 'pane' inside an outer-layout
-		,	parent	= $N.data("parentLayout")	// parent-layout Instance
-		,	pane	= $N.data("layoutEdge")		// pane-name in parent-layout
-		,	isChild	= parent && pane
-		,	num		= $.layout.cssNum
-		,	$parent, n
-		;
-		// sC = state.container
-		sC.selector = $N.selector.split(".slice")[0];
-		sC.ref		= (o.name ? o.name +' layout / ' : '') + tag + (id ? "#"+id : cls ? '.['+cls+']' : ''); // used in messages
-		sC.isBody	= (tag === "BODY");
-
-		// try to find a parent-layout
-		if (!isChild && !sC.isBody) {
-			$parent = $N.closest("."+ $.layout.defaults.panes.paneClass);
-			parent	= $parent.data("parentLayout");
-			pane	= $parent.data("layoutEdge");
-			isChild	= parent && pane;
-		}
-
-		$N	.data({
-				layout: Instance
-			,	layoutContainer: sID // FLAG to indicate this is a layout-container - contains unique internal ID
-			})
-			.addClass(o.containerClass)
-		;
-		var layoutMethods = {
-			destroy:	''
-		,	initPanes:	''
-		,	resizeAll:	'resizeAll'
-		,	resize:		'resizeAll'
-		};
-		// loop hash and bind all methods - include layoutID namespacing
-		for (name in layoutMethods) {
-			$N.bind("layout"+ name.toLowerCase() +"."+ sID, Instance[ layoutMethods[name] || name ]);
-		}
-
-		// if this container is another layout's 'pane', then set child/parent pointers
-		if (isChild) {
-			// update parent flag
-			Instance.hasParentLayout = true;
-			// set pointers to THIS child-layout (Instance) in parent-layout
-			parent.refreshChildren( pane, Instance );
-		}
-
-		// SAVE original container CSS for use in destroy()
-		if (!$N.data(css)) {
-			// handle props like overflow different for BODY & HTML - has 'system default' values
-			if (sC.isBody) {
-				// SAVE <BODY> CSS
-				$N.data(css, $.extend( styles($N, props), {
-					height:		$N.css("height")
-				,	overflow:	$N.css("overflow")
-				,	overflowX:	$N.css("overflowX")
-				,	overflowY:	$N.css("overflowY")
-				}));
-				// ALSO SAVE <HTML> CSS
-				$H.data(css, $.extend( styles($H, 'padding'), {
-					height:		"auto" // FF would return a fixed px-size!
-				,	overflow:	$H.css("overflow")
-				,	overflowX:	$H.css("overflowX")
-				,	overflowY:	$H.css("overflowY")
-				}));
-			}
-			else // handle props normally for non-body elements
-				$N.data(css, styles($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY") );
-		}
-
-		try {
-			// common container CSS
-			CSS = {
-				overflow:	hid
-			,	overflowX:	hid
-			,	overflowY:	hid
-			};
-			$N.css( CSS );
-
-			if (o.inset && !$.isPlainObject(o.inset)) {
-				// can specify a single number for equal outset all-around
-				n = parseInt(o.inset, 10) || 0
-				o.inset = {
-					top:	n
-				,	bottom:	n
-				,	left:	n
-				,	right:	n
-				};
-			}
-
-			// format html & body if this is a full page layout
-			if (sC.isBody) {
-				// if HTML has padding, use this as an outer-spacing around BODY
-				if (!o.outset) {
-					// use padding from parent-elem (HTML) as outset
-					o.outset = {
-						top:	num($H, "paddingTop")
-					,	bottom:	num($H, "paddingBottom")
-					,	left:	num($H, "paddingLeft")
-					,	right:	num($H, "paddingRight")
-					};
-				}
-				else if (!$.isPlainObject(o.outset)) {
-					// can specify a single number for equal outset all-around
-					n = parseInt(o.outset, 10) || 0
-					o.outset = {
-						top:	n
-					,	bottom:	n
-					,	left:	n
-					,	right:	n
-					};
-				}
-				// HTML
-				$H.css( CSS ).css({
-					height:		"100%"
-				,	border:		"none"	// no border or padding allowed when using height = 100%
-				,	padding:	0		// ditto
-				,	margin:		0
-				});
-				// BODY
-				if (browser.isIE6) {
-					// IE6 CANNOT use the trick of setting absolute positioning on all 4 sides - must have 'height'
-					$N.css({
-						width:		"100%"
-					,	height:		"100%"
-					,	border:		"none"	// no border or padding allowed when using height = 100%
-					,	padding:	0		// ditto
-					,	margin:		0
-					,	position:	"relative"
-					});
-					// convert body padding to an inset option - the border cannot be measured in IE6!
-					if (!o.inset) o.inset = elDims( $N ).inset;
-				}
-				else { // use absolute positioning for BODY to allow borders & padding without overflow
-					$N.css({
-						width:		"auto"
-					,	height:		"auto"
-					,	margin:		0
-					,	position:	"absolute"	// allows for border and padding on BODY
-					});
-					// apply edge-positioning created above
-					$N.css( o.outset );
-				}
-				// set current layout-container dimensions
-				$.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT include insetX values
-			}
-			else {
-				// container MUST have 'position'
-				var	p = $N.css("position");
-				if (!p || !p.match(/(fixed|absolute|relative)/))
-					$N.css("position","relative");
-
-				// set current layout-container dimensions
-				if ( $N.is(":visible") ) {
-					$.extend(sC, elDims( $N, o.inset )); // passing inset means DO NOT change insetX (padding) values
-					if (sC.innerHeight < 1) // container has no 'height' - warn developer
-						_log( o.errors.noContainerHeight.replace(/CONTAINER/, sC.ref) );
-				}
-			}
-
-			// if container has min-width/height, then enable scrollbar(s)
-			if ( num($N, "minWidth")  ) $N.parent().css("overflowX","auto");
-			if ( num($N, "minHeight") ) $N.parent().css("overflowY","auto");
-
-		} catch (ex) {}
-	}
-
-	/**
-	* Bind layout hotkeys - if options enabled
-	*
-	* @see  _create() and addPane()
-	* @param {string=}	[panes=""]	The edge(s) to process
-	*/
-,	initHotkeys = function (panes) {
-		panes = panes ? panes.split(",") : _c.borderPanes;
-		// bind keyDown to capture hotkeys, if option enabled for ANY pane
-		$.each(panes, function (i, pane) {
-			var o = options[pane];
-			if (o.enableCursorHotkey || o.customHotkey) {
-				$(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE
-				return false; // BREAK - binding was done
-			}
-		});
-	}
-
-	/**
-	* Build final OPTIONS data
-	*
-	* @see  _create()
-	*/
-,	initOptions = function () {
-		var data, d, pane, key, val, i, c, o;
-
-		// reprocess user's layout-options to have correct options sub-key structure
-		opts = $.layout.transformData( opts, true ); // panes = default subkey
-
-		// auto-rename old options for backward compatibility
-		opts = $.layout.backwardCompatibility.renameAllOptions( opts );
-
-		// if user-options has 'panes' key (pane-defaults), clean it...
-		if (!$.isEmptyObject(opts.panes)) {
-			// REMOVE any pane-defaults that MUST be set per-pane
-			data = $.layout.optionsMap.noDefault;
-			for (i=0, c=data.length; i<c; i++) {
-				key = data[i];
-				delete opts.panes[key]; // OK if does not exist
-			}
-			// REMOVE any layout-options specified under opts.panes
-			data = $.layout.optionsMap.layout;
-			for (i=0, c=data.length; i<c; i++) {
-				key = data[i];
-				delete opts.panes[key]; // OK if does not exist
-			}
-		}
-
-		// MOVE any NON-layout-options from opts-root to opts.panes
-		data = $.layout.optionsMap.layout;
-		var rootKeys = $.layout.config.optionRootKeys;
-		for (key in opts) {
-			val = opts[key];
-			if ($.inArray(key, rootKeys) < 0 && $.inArray(key, data) < 0) {
-				if (!opts.panes[key])
-					opts.panes[key] = $.isPlainObject(val) ? $.extend(true, {}, val) : val;
-				delete opts[key]
-			}
-		}
-
-		// START by updating ALL options from opts
-		$.extend(true, options, opts);
-
-		// CREATE final options (and config) for EACH pane
-		$.each(_c.allPanes, function (i, pane) {
-
-			// apply 'pane-defaults' to CONFIG.[PANE]
-			_c[pane] = $.extend(true, {}, _c.panes, _c[pane]);
-
-			d = options.panes;
-			o = options[pane];
-
-			// center-pane uses SOME keys in defaults.panes branch
-			if (pane === 'center') {
-				// ONLY copy keys from opts.panes listed in: $.layout.optionsMap.center
-				data = $.layout.optionsMap.center;		// list of 'center-pane keys'
-				for (i=0, c=data.length; i<c; i++) {	// loop the list...
-					key = data[i];
-					// only need to use pane-default if pane-specific value not set
-					if (!opts.center[key] && (opts.panes[key] || !o[key]))
-						o[key] = d[key]; // pane-default
-				}
-			}
-			else {
-				// border-panes use ALL keys in defaults.panes branch
-				o = options[pane] = $.extend(true, {}, d, o); // re-apply pane-specific opts AFTER pane-defaults
-				createFxOptions( pane );
-				// ensure all border-pane-specific base-classes exist
-				if (!o.resizerClass)	o.resizerClass	= "ui-layout-resizer";
-				if (!o.togglerClass)	o.togglerClass	= "ui-layout-toggler";
-			}
-			// ensure we have base pane-class (ALL panes)
-			if (!o.paneClass) o.paneClass = "ui-layout-pane";
-		});
-
-		// update options.zIndexes if a zIndex-option specified
-		var zo	= opts.zIndex
-		,	z	= options.zIndexes;
-		if (zo > 0) {
-			z.pane_normal		= zo;
-			z.content_mask		= max(zo+1, z.content_mask);	// MIN = +1
-			z.resizer_normal	= max(zo+2, z.resizer_normal);	// MIN = +2
-		}
-
-		// DELETE 'panes' key now that we are done - values were copied to EACH pane
-		delete options.panes;
-
-
-		function createFxOptions ( pane ) {
-			var	o = options[pane]
-			,	d = options.panes;
-			// ensure fxSettings key to avoid errors
-			if (!o.fxSettings) o.fxSettings = {};
-			if (!d.fxSettings) d.fxSettings = {};
-
-			$.each(["_open","_close","_size"], function (i,n) { 
-				var
-					sName		= "fxName"+ n
-				,	sSpeed		= "fxSpeed"+ n
-				,	sSettings	= "fxSettings"+ n
-					// recalculate fxName according to specificity rules
-				,	fxName = o[sName] =
-						o[sName]	// options.west.fxName_open
-					||	d[sName]	// options.panes.fxName_open
-					||	o.fxName	// options.west.fxName
-					||	d.fxName	// options.panes.fxName
-					||	"none"		// MEANS $.layout.defaults.panes.fxName == "" || false || null || 0
-				,	fxExists	= $.effects && ($.effects[fxName] || ($.effects.effect && $.effects.effect[fxName]))
-				;
-				// validate fxName to ensure is valid effect - MUST have effect-config data in options.effects
-				if (fxName === "none" || !options.effects[fxName] || !fxExists)
-					fxName = o[sName] = "none"; // effect not loaded OR unrecognized fxName
-
-				// set vars for effects subkeys to simplify logic
-				var	fx		= options.effects[fxName] || {}	// effects.slide
-				,	fx_all	= fx.all	|| null				// effects.slide.all
-				,	fx_pane	= fx[pane]	|| null				// effects.slide.west
-				;
-				// create fxSpeed[_open|_close|_size]
-				o[sSpeed] =
-					o[sSpeed]				// options.west.fxSpeed_open
-				||	d[sSpeed]				// options.west.fxSpeed_open
-				||	o.fxSpeed				// options.west.fxSpeed
-				||	d.fxSpeed				// options.panes.fxSpeed
-				||	null					// DEFAULT - let fxSetting.duration control speed
-				;
-				// create fxSettings[_open|_close|_size]
-				o[sSettings] = $.extend(
-					true
-				,	{}
-				,	fx_all					// effects.slide.all
-				,	fx_pane					// effects.slide.west
-				,	d.fxSettings			// options.panes.fxSettings
-				,	o.fxSettings			// options.west.fxSettings
-				,	d[sSettings]			// options.panes.fxSettings_open
-				,	o[sSettings]			// options.west.fxSettings_open
-				);
-			});
-
-			// DONE creating action-specific-settings for this pane,
-			// so DELETE generic options - are no longer meaningful
-			delete o.fxName;
-			delete o.fxSpeed;
-			delete o.fxSettings;
-		}
-	}
-
-	/**
-	* Initialize module objects, styling, size and position for all panes
-	*
-	* @see  _initElements()
-	* @param {string}	pane		The pane to process
-	*/
-,	getPane = function (pane) {
-		var sel = options[pane].paneSelector
-		if (sel.substr(0,1)==="#") // ID selector
-			// NOTE: elements selected 'by ID' DO NOT have to be 'children'
-			return $N.find(sel).eq(0);
-		else { // class or other selector
-			var $P = $N.children(sel).eq(0);
-			// look for the pane nested inside a 'form' element
-			return $P.length ? $P : $N.children("form:first").children(sel).eq(0);
-		}
-	}
-
-	/**
-	* @param {Object=}		evt
-	*/
-,	initPanes = function (evt) {
-		// stopPropagation if called by trigger("layoutinitpanes") - use evtPane utility 
-		evtPane(evt);
-
-		// NOTE: do north & south FIRST so we can measure their height - do center LAST
-		$.each(_c.allPanes, function (idx, pane) {
-			addPane( pane, true );
-		});
-
-		// init the pane-handles NOW in case we have to hide or close the pane below
-		initHandles();
-
-		// now that all panes have been initialized and initially-sized,
-		// make sure there is really enough space available for each pane
-		$.each(_c.borderPanes, function (i, pane) {
-			if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN
-				setSizeLimits(pane);
-				makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit()
-			}
-		});
-		// size center-pane AGAIN in case we 'closed' a border-pane in loop above
-		sizeMidPanes("center");
-
-		//	Chrome/Webkit sometimes fires callbacks BEFORE it completes resizing!
-		//	Before RC30.3, there was a 10ms delay here, but that caused layout 
-		//	to load asynchrously, which is BAD, so try skipping delay for now
-
-		// process pane contents and callbacks, and init/resize child-layout if exists
-		$.each(_c.allPanes, function (idx, pane) {
-			afterInitPane(pane);
-		});
-	}
-
-	/**
-	* Add a pane to the layout - subroutine of initPanes()
-	*
-	* @see  initPanes()
-	* @param {string}	pane			The pane to process
-	* @param {boolean=}	[force=false]	Size content after init
-	*/
-,	addPane = function (pane, force) {
-		if (!force && !isInitialized()) return;
-		var
-			o		= options[pane]
-		,	s		= state[pane]
-		,	c		= _c[pane]
-		,	dir		= c.dir
-		,	fx		= s.fx
-		,	spacing	= o.spacing_open || 0
-		,	isCenter = (pane === "center")
-		,	CSS		= {}
-		,	$P		= $Ps[pane]
-		,	size, minSize, maxSize, child
-		;
-		// if pane-pointer already exists, remove the old one first
-		if ($P)
-			removePane( pane, false, true, false );
-		else
-			$Cs[pane] = false; // init
-
-		$P = $Ps[pane] = getPane(pane);
-		if (!$P.length) {
-			$Ps[pane] = false; // logic
-			return;
-		}
-
-		// SAVE original Pane CSS
-		if (!$P.data("layoutCSS")) {
-			var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border";
-			$P.data("layoutCSS", styles($P, props));
-		}
-
-		// create alias for pane data in Instance - initHandles will add more
-		Instance[pane] = {
-			name:		pane
-		,	pane:		$Ps[pane]
-		,	content:	$Cs[pane]
-		,	options:	options[pane]
-		,	state:		state[pane]
-		,	children:	children[pane]
-		};
-
-		// add classes, attributes & events
-		$P	.data({
-				parentLayout:	Instance		// pointer to Layout Instance
-			,	layoutPane:		Instance[pane]	// NEW pointer to pane-alias-object
-			,	layoutEdge:		pane
-			,	layoutRole:		"pane"
-			})
-			.css(c.cssReq).css("zIndex", options.zIndexes.pane_normal)
-			.css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles
-			.addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
-			.bind("mouseenter."+ sID, addHover )
-			.bind("mouseleave."+ sID, removeHover )
-			;
-		var paneMethods = {
-				hide:				''
-			,	show:				''
-			,	toggle:				''
-			,	close:				''
-			,	open:				''
-			,	slideOpen:			''
-			,	slideClose:			''
-			,	slideToggle:		''
-			,	size:				'sizePane'
-			,	sizePane:			'sizePane'
-			,	sizeContent:		''
-			,	sizeHandles:		''
-			,	enableClosable:		''
-			,	disableClosable:	''
-			,	enableSlideable:	''
-			,	disableSlideable:	''
-			,	enableResizable:	''
-			,	disableResizable:	''
-			,	swapPanes:			'swapPanes'
-			,	swap:				'swapPanes'
-			,	move:				'swapPanes'
-			,	removePane:			'removePane'
-			,	remove:				'removePane'
-			,	createChildren:		''
-			,	resizeChildren:		''
-			,	resizeAll:			'resizeAll'
-			,	resizeLayout:		'resizeAll'
-			}
-		,	name;
-		// loop hash and bind all methods - include layoutID namespacing
-		for (name in paneMethods) {
-			$P.bind("layoutpane"+ name.toLowerCase() +"."+ sID, Instance[ paneMethods[name] || name ]);
-		}
-
-		// see if this pane has a 'scrolling-content element'
-		initContent(pane, false); // false = do NOT sizeContent() - called later
-
-		if (!isCenter) {
-			// call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden)
-			// if o.size is auto or not valid, then MEASURE the pane and use that as its 'size'
-			size	= s.size = _parseSize(pane, o.size);
-			minSize	= _parseSize(pane,o.minSize) || 1;
-			maxSize	= _parseSize(pane,o.maxSize) || 100000;
-			if (size > 0) size = max(min(size, maxSize), minSize);
-			s.autoResize = o.autoResize; // used with percentage sizes
-
-			// state for border-panes
-			s.isClosed  = false; // true = pane is closed
-			s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
-			s.isResizing= false; // true = pane is in process of being resized
-			s.isHidden	= false; // true = pane is hidden - no spacing, resizer or toggler is visible!
-
-			// array for 'pin buttons' whose classNames are auto-updated on pane-open/-close
-			if (!s.pins) s.pins = [];
-		}
-		//	states common to ALL panes
-		s.tagName	= $P[0].tagName;
-		s.edge		= pane;		// useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going)
-		s.noRoom	= false;	// true = pane 'automatically' hidden due to insufficient room - will unhide automatically
-		s.isVisible	= true;		// false = pane is invisible - closed OR hidden - simplify logic
-
-		// init pane positioning
-		setPanePosition( pane );
-
-		// if pane is not visible, 
-		if (dir === "horz") // north or south pane
-			CSS.height = cssH($P, size);
-		else if (dir === "vert") // east or west pane
-			CSS.width = cssW($P, size);
-		//else if (isCenter) {}
-
-		$P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes
-		if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback
-
-		// if manually adding a pane AFTER layout initialization, then...
-		if (state.initialized) {
-			initHandles( pane );
-			initHotkeys( pane );
-		}
-
-		// close or hide the pane if specified in settings
-		if (o.initClosed && o.closable && !o.initHidden)
-			close(pane, true, true); // true, true = force, noAnimation
-		else if (o.initHidden || o.initClosed)
-			hide(pane); // will be completely invisible - no resizer or spacing
-		else if (!s.noRoom)
-			// make the pane visible - in case was initially hidden
-			$P.css("display","block");
-		// ELSE setAsOpen() - called later by initHandles()
-
-		// RESET visibility now - pane will appear IF display:block
-		$P.css("visibility","visible");
-
-		// check option for auto-handling of pop-ups & drop-downs
-		if (o.showOverflowOnHover)
-			$P.hover( allowOverflow, resetOverflow );
-
-		// if manually adding a pane AFTER layout initialization, then...
-		if (state.initialized) {
-			afterInitPane( pane );
-		}
-	}
-
-,	afterInitPane = function (pane) {
-		var	$P	= $Ps[pane]
-		,	s	= state[pane]
-		,	o	= options[pane]
-		;
-		if (!$P) return;
-
-		// see if there is a directly-nested layout inside this pane
-		if ($P.data("layout"))
-			refreshChildren( pane, $P.data("layout") );
-
-		// process pane contents and callbacks, and init/resize child-layout if exists
-		if (s.isVisible) { // pane is OPEN
-			if (state.initialized) // this pane was added AFTER layout was created
-				resizeAll(); // will also sizeContent
-			else
-				sizeContent(pane);
-
-			if (o.triggerEventsOnLoad)
-				_runCallbacks("onresize_end", pane);
-			else // automatic if onresize called, otherwise call it specifically
-				// resize child - IF inner-layout already exists (created before this layout)
-				resizeChildren(pane, true); // a previously existing childLayout
-		}
-
-		// init childLayouts - even if pane is not visible
-		if (o.initChildren && o.children)
-			createChildren(pane);
-	}
-
-	/**
-	* @param {string=}	panes		The pane(s) to process
-	*/
-,	setPanePosition = function (panes) {
-		panes = panes ? panes.split(",") : _c.borderPanes;
-
-		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
-		$.each(panes, function (i, pane) {
-			var $P	= $Ps[pane]
-			,	$R	= $Rs[pane]
-			,	o	= options[pane]
-			,	s	= state[pane]
-			,	side =  _c[pane].side
-			,	CSS	= {}
-			;
-			if (!$P) return; // pane does not exist - skip
-
-			// set css-position to account for container borders & padding
-			switch (pane) {
-				case "north": 	CSS.top 	= sC.inset.top;
-								CSS.left 	= sC.inset.left;
-								CSS.right	= sC.inset.right;
-								break;
-				case "south": 	CSS.bottom	= sC.inset.bottom;
-								CSS.left 	= sC.inset.left;
-								CSS.right 	= sC.inset.right;
-								break;
-				case "west": 	CSS.left 	= sC.inset.left; // top, bottom & height set by sizeMidPanes()
-								break;
-				case "east": 	CSS.right 	= sC.inset.right; // ditto
-								break;
-				case "center":	// top, left, width & height set by sizeMidPanes()
-			}
-			// apply position
-			$P.css(CSS); 
-
-			// update resizer position
-			if ($R && s.isClosed)
-				$R.css(side, sC.inset[side]);
-			else if ($R && !s.isHidden)
-				$R.css(side, sC.inset[side] + getPaneSize(pane));
-		});
-	}
-
-	/**
-	* Initialize module objects, styling, size and position for all resize bars and toggler buttons
-	*
-	* @see  _create()
-	* @param {string=}	[panes=""]	The edge(s) to process
-	*/
-,	initHandles = function (panes) {
-		panes = panes ? panes.split(",") : _c.borderPanes;
-
-		// create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
-		$.each(panes, function (i, pane) {
-			var $P		= $Ps[pane];
-			$Rs[pane]	= false; // INIT
-			$Ts[pane]	= false;
-			if (!$P) return; // pane does not exist - skip
-
-			var	o		= options[pane]
-			,	s		= state[pane]
-			,	c		= _c[pane]
-			,	paneId	= o.paneSelector.substr(0,1) === "#" ? o.paneSelector.substr(1) : ""
-			,	rClass	= o.resizerClass
-			,	tClass	= o.togglerClass
-			,	spacing	= (s.isVisible ? o.spacing_open : o.spacing_closed)
-			,	_pane	= "-"+ pane // used for classNames
-			,	_state	= (s.isVisible ? "-open" : "-closed") // used for classNames
-			,	I		= Instance[pane]
-				// INIT RESIZER BAR
-			,	$R		= I.resizer = $Rs[pane] = $("<div></div>")
-				// INIT TOGGLER BUTTON
-			,	$T		= I.toggler = (o.closable ? $Ts[pane] = $("<div></div>") : false)
-			;
-
-			//if (s.isVisible && o.resizable) ... handled by initResizable
-			if (!s.isVisible && o.slidable)
-				$R.attr("title", o.tips.Slide).css("cursor", o.sliderCursor);
-
-			$R	// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
-				.attr("id", paneId ? paneId +"-resizer" : "" )
-				.data({
-					parentLayout:	Instance
-				,	layoutPane:		Instance[pane]	// NEW pointer to pane-alias-object
-				,	layoutEdge:		pane
-				,	layoutRole:		"resizer"
-				})
-				.css(_c.resizers.cssReq).css("zIndex", options.zIndexes.resizer_normal)
-				.css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles
-				.addClass(rClass +" "+ rClass+_pane)
-				.hover(addHover, removeHover) // ALWAYS add hover-classes, even if resizing is not enabled - handle with CSS instead
-				.hover(onResizerEnter, onResizerLeave) // ALWAYS NEED resizer.mouseleave to balance toggler.mouseenter
-				.appendTo($N) // append DIV to container
-			;
-			if (o.resizerDblClickToggle)
-				$R.bind("dblclick."+ sID, toggle );
-
-			if ($T) {
-				$T	// if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "#paneLeft-toggler"
-					.attr("id", paneId ? paneId +"-toggler" : "" )
-					.data({
-						parentLayout:	Instance
-					,	layoutPane:		Instance[pane]	// NEW pointer to pane-alias-object
-					,	layoutEdge:		pane
-					,	layoutRole:		"toggler"
-					})
-					.css(_c.togglers.cssReq) // add base/required styles
-					.css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles
-					.addClass(tClass +" "+ tClass+_pane)
-					.hover(addHover, removeHover) // ALWAYS add hover-classes, even if toggling is not enabled - handle with CSS instead
-					.bind("mouseenter", onResizerEnter) // NEED toggler.mouseenter because mouseenter MAY NOT fire on resizer
-					.appendTo($R) // append SPAN to resizer DIV
-				;
-				// ADD INNER-SPANS TO TOGGLER
-				if (o.togglerContent_open) // ui-layout-open
-					$("<span>"+ o.togglerContent_open +"</span>")
-						.data({
-							layoutEdge:		pane
-						,	layoutRole:		"togglerContent"
-						})
-						.data("layoutRole", "togglerContent")
-						.data("layoutEdge", pane)
-						.addClass("content content-open")
-						.css("display","none")
-						.appendTo( $T )
-						//.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead!
-					;
-				if (o.togglerContent_closed) // ui-layout-closed
-					$("<span>"+ o.togglerContent_closed +"</span>")
-						.data({
-							layoutEdge:		pane
-						,	layoutRole:		"togglerContent"
-						})
-						.addClass("content content-closed")
-						.css("display","none")
-						.appendTo( $T )
-						//.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead!
-					;
-				// ADD TOGGLER.click/.hover
-				enableClosable(pane);
-			}
-
-			// add Draggable events
-			initResizable(pane);
-
-			// ADD CLASSNAMES & SLIDE-BINDINGS - eg: class="resizer resizer-west resizer-open"
-			if (s.isVisible)
-				setAsOpen(pane);	// onOpen will be called, but NOT onResize
-			else {
-				setAsClosed(pane);	// onClose will be called
-				bindStartSlidingEvents(pane, true); // will enable events IF option is set
-			}
-
-		});
-
-		// SET ALL HANDLE DIMENSIONS
-		sizeHandles();
-	}
-
-
-	/**
-	* Initialize scrolling ui-layout-content div - if exists
-	*
-	* @see  initPane() - or externally after an Ajax injection
-	* @param {string}	pane			The pane to process
-	* @param {boolean=}	[resize=true]	Size content after init
-	*/
-,	initContent = function (pane, resize) {
-		if (!isInitialized()) return;
-		var 
-			o	= options[pane]
-		,	sel	= o.contentSelector
-		,	I	= Instance[pane]
-		,	$P	= $Ps[pane]
-		,	$C
-		;
-		if (sel) $C = I.content = $Cs[pane] = (o.findNestedContent)
-			? $P.find(sel).eq(0) // match 1-element only
-			: $P.children(sel).eq(0)
-		;
-		if ($C && $C.length) {
-			$C.data("layoutRole", "content");
-			// SAVE original Content CSS
-			if (!$C.data("layoutCSS"))
-				$C.data("layoutCSS", styles($C, "height"));
-			$C.css( _c.content.cssReq );
-			if (o.applyDemoStyles) {
-				$C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div
-				$P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane
-			}
-			// ensure no vertical scrollbar on pane - will mess up measurements
-			if ($P.css("overflowX").match(/(scroll|auto)/)) {
-				$P.css("overflow", "hidden");
-			}
-			state[pane].content = {}; // init content state
-			if (resize !== false) sizeContent(pane);
-			// sizeContent() is called AFTER init of all elements
-		}
-		else
-			I.content = $Cs[pane] = false;
-	}
-
-
-	/**
-	* Add resize-bars to all panes that specify it in options
-	* -dependancy: $.fn.resizable - will skip if not found
-	*
-	* @see  _create()
-	* @param {string=}	[panes=""]	The edge(s) to process
-	*/
-,	initResizable = function (panes) {
-		var	draggingAvailable = $.layout.plugins.draggable
-		,	side // set in start()
-		;
-		panes = panes ? panes.split(",") : _c.borderPanes;
-
-		$.each(panes, function (idx, pane) {
-			var o = options[pane];
-			if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
-				o.resizable = false;
-				return true; // skip to next
-			}
-
-			var s		= state[pane]
-			,	z		= options.zIndexes
-			,	c		= _c[pane]
-			,	side	= c.dir=="horz" ? "top" : "left"
-			,	$P 		= $Ps[pane]
-			,	$R		= $Rs[pane]
-			,	base	= o.resizerClass
-			,	lastPos	= 0 // used when live-resizing
-			,	r, live // set in start because may change
-			//	'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
-			,	resizerClass		= base+"-drag"				// resizer-drag
-			,	resizerPaneClass	= base+"-"+pane+"-drag"		// resizer-north-drag
-			//	'helper' class is applied to the CLONED resizer-bar while it is being dragged
-			,	helperClass			= base+"-dragging"			// resizer-dragging
-			,	helperPaneClass		= base+"-"+pane+"-dragging" // resizer-north-dragging
-			,	helperLimitClass	= base+"-dragging-limit"	// resizer-drag
-			,	helperPaneLimitClass = base+"-"+pane+"-dragging-limit"	// resizer-north-drag
-			,	helperClassesSet	= false 					// logic var
-			;
-
-			if (!s.isClosed)
-				$R.attr("title", o.tips.Resize)
-				  .css("cursor", o.resizerCursor); // n-resize, s-resize, etc
-
-			$R.draggable({
-				containment:	$N[0] // limit resizing to layout container
-			,	axis:			(c.dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
-			,	delay:			0
-			,	distance:		1
-			,	grid:			o.resizingGrid
-			//	basic format for helper - style it using class: .ui-draggable-dragging
-			,	helper:			"clone"
-			,	opacity:		o.resizerDragOpacity
-			,	addClasses:		false // avoid ui-state-disabled class when disabled
-			//,	iframeFix:		o.draggableIframeFix // TODO: consider using when bug is fixed
-			,	zIndex:			z.resizer_drag
-
-			,	start: function (e, ui) {
-					// REFRESH options & state pointers in case we used swapPanes
-					o = options[pane];
-					s = state[pane];
-					// re-read options
-					live = o.livePaneResizing;
-
-					// ondrag_start callback - will CANCEL hide if returns false
-					// TODO: dragging CANNOT be cancelled like this, so see if there is a way?
-					if (false === _runCallbacks("ondrag_start", pane)) return false;
-
-					s.isResizing		= true; // prevent pane from closing while resizing
-					state.paneResizing	= pane; // easy to see if ANY pane is resizing
-					timer.clear(pane+"_closeSlider"); // just in case already triggered
-
-					// SET RESIZER LIMITS - used in drag()
-					setSizeLimits(pane); // update pane/resizer state
-					r = s.resizerPosition;
-					lastPos = ui.position[ side ]
-
-					$R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes
-					helperClassesSet = false; // reset logic var - see drag()
-
-					// DISABLE TEXT SELECTION (probably already done by resizer.mouseOver)
-					$('body').disableSelection(); 
-
-					// MASK PANES CONTAINING IFRAMES, APPLETS OR OTHER TROUBLESOME ELEMENTS
-					showMasks( pane, { resizing: true });
-				}
-
-			,	drag: function (e, ui) {
-					if (!helperClassesSet) { // can only add classes after clone has been added to the DOM
-						//$(".ui-draggable-dragging")
-						ui.helper
-							.addClass( helperClass +" "+ helperPaneClass ) // add helper classes
-							.css({ right: "auto", bottom: "auto" })	// fix dir="rtl" issue
-							.children().css("visibility","hidden")	// hide toggler inside dragged resizer-bar
-						;
-						helperClassesSet = true;
-						// draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
-						if (s.isSliding) $Ps[pane].css("zIndex", z.pane_sliding);
-					}
-					// CONTAIN RESIZER-BAR TO RESIZING LIMITS
-					var limit = 0;
-					if (ui.position[side] < r.min) {
-						ui.position[side] = r.min;
-						limit = -1;
-					}
-					else if (ui.position[side] > r.max) {
-						ui.position[side] = r.max;
-						limit = 1;
-					}
-					// ADD/REMOVE dragging-limit CLASS
-					if (limit) {
-						ui.helper.addClass( helperLimitClass +" "+ helperPaneLimitClass ); // at dragging-limit
-						window.defaultStatus = (limit>0 && pane.match(/(north|west)/)) || (limit<0 && pane.match(/(south|east)/)) ? o.tips.maxSizeWarning : o.tips.minSizeWarning;
-					}
-					else {
-						ui.helper.removeClass( helperLimitClass +" "+ helperPaneLimitClass ); // not at dragging-limit
-						window.defaultStatus = "";
-					}
-					// DYNAMICALLY RESIZE PANES IF OPTION ENABLED
-					// won't trigger unless resizer has actually moved!
-					if (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) {
-						lastPos = ui.position[side];
-						resizePanes(e, ui, pane)
-					}
-				}
-
-			,	stop: function (e, ui) {
-					$('body').enableSelection(); // RE-ENABLE TEXT SELECTION
-					window.defaultStatus = ""; // clear 'resizing limit' message from statusbar
-					$R.removeClass( resizerClass +" "+ resizerPaneClass ); // remove drag classes from Resizer
-					s.isResizing		= false;
-					state.paneResizing	= false; // easy to see if ANY pane is resizing
-					resizePanes(e, ui, pane, true); // true = resizingDone
-				}
-
-			});
-		});
-
-		/**
-		* resizePanes
-		*
-		* Sub-routine called from stop() - and drag() if livePaneResizing
-		*
-		* @param {!Object}		evt
-		* @param {!Object}		ui
-		* @param {string}		pane
-		* @param {boolean=}		[resizingDone=false]
-		*/
-		var resizePanes = function (evt, ui, pane, resizingDone) {
-			var	dragPos	= ui.position
-			,	c		= _c[pane]
-			,	o		= options[pane]
-			,	s		= state[pane]
-			,	resizerPos
-			;
-			switch (pane) {
-				case "north":	resizerPos = dragPos.top; break;
-				case "west":	resizerPos = dragPos.left; break;
-				case "south":	resizerPos = sC.layoutHeight - dragPos.top  - o.spacing_open; break;
-				case "east":	resizerPos = sC.layoutWidth  - dragPos.left - o.spacing_open; break;
-			};
-			// remove container margin from resizer position to get the pane size
-			var newSize = resizerPos - sC.inset[c.side];
-
-			// Disable OR Resize Mask(s) created in drag.start
-			if (!resizingDone) {
-				// ensure we meet liveResizingTolerance criteria
-				if (Math.abs(newSize - s.size) < o.liveResizingTolerance)
-					return; // SKIP resize this time
-				// resize the pane
-				manualSizePane(pane, newSize, false, true); // true = noAnimation
-				sizeMasks(); // resize all visible masks
-			}
-			else { // resizingDone
-				// ondrag_end callback
-				if (false !== _runCallbacks("ondrag_end", pane))
-					manualSizePane(pane, newSize, false, true); // true = noAnimation
-				hideMasks(true); // true = force hiding all masks even if one is 'sliding'
-				if (s.isSliding) // RE-SHOW 'object-masks' so objects won't show through sliding pane
-					showMasks( pane, { resizing: true });
-			}
-		};
-	}
-
-	/**
-	*	sizeMask
-	*
-	*	Needed to overlay a DIV over an IFRAME-pane because mask CANNOT be *inside* the pane
-	*	Called when mask created, and during livePaneResizing
-	*/
-,	sizeMask = function () {
-		var $M		= $(this)
-		,	pane	= $M.data("layoutMask") // eg: "west"
-		,	s		= state[pane]
-		;
-		// only masks over an IFRAME-pane need manual resizing
-		if (s.tagName == "IFRAME" && s.isVisible) // no need to mask closed/hidden panes
-			$M.css({
-				top:	s.offsetTop
-			,	left:	s.offsetLeft
-			,	width:	s.outerWidth
-			,	height:	s.outerHeight
-			});
-		/* ALT Method...
-		var $P = $Ps[pane];
-		$M.css( $P.position() ).css({ width: $P[0].offsetWidth, height: $P[0].offsetHeight });
-		*/
-	}
-,	sizeMasks = function () {
-		$Ms.each( sizeMask ); // resize all 'visible' masks
-	}
-
-	/**
-	* @param {string}	pane		The pane being resized, animated or isSliding
-	* @param {Object=}	[args]		(optional) Options: which masks to apply, and to which panes
-	*/
-,	showMasks = function (pane, args) {
-		var	c		= _c[pane]
-		,	panes	=  ["center"]
-		,	z		= options.zIndexes
-		,	a		= $.extend({
-						objectsOnly:	false
-					,	animation:		false
-					,	resizing:		true
-					,	sliding:		state[pane].isSliding
-					},	args )
-		,	o, s
-		;
-		if (a.resizing)
-			panes.push( pane );
-		if (a.sliding)
-			panes.push( _c.oppositeEdge[pane] ); // ADD the oppositeEdge-pane
-
-		if (c.dir === "horz") {
-			panes.push("west");
-			panes.push("east");
-		}
-
-		$.each(panes, function(i,p){
-			s = state[p];
-			o = options[p];
-			if (s.isVisible && ( o.maskObjects || (!a.objectsOnly && o.maskContents) )) {
-				getMasks(p).each(function(){
-					sizeMask.call(this);
-					this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1
-					this.style.display = "block";
-				});
-			}
-		});
-	}
-
-	/**
-	* @param {boolean=}	force		Hide masks even if a pane is sliding
-	*/
-,	hideMasks = function (force) {
-		// ensure no pane is resizing - could be a timing issue
-		if (force || !state.paneResizing) {
-			$Ms.hide(); // hide ALL masks
-		}
-		// if ANY pane is sliding, then DO NOT remove masks from panes with maskObjects enabled
-		else if (!force && !$.isEmptyObject( state.panesSliding )) {
-			var	i = $Ms.length - 1
-			,	p, $M;
-			for (; i >= 0; i--) {
-				$M	= $Ms.eq(i);
-				p	= $M.data("layoutMask");
-				if (!options[p].maskObjects) {
-					$M.hide();
-				}
-			}
-		}
-	}
-
-	/**
-	* @param {string}	pane
-	*/
-,	getMasks = function (pane) {
-		var $Masks	= $([])
-		,	$M, i = 0, c = $Ms.length
-		;
-		for (; i<c; i++) {
-			$M = $Ms.eq(i);
-			if ($M.data("layoutMask") === pane)
-				$Masks = $Masks.add( $M );
-		}
-		if ($Masks.length)
-			return $Masks;
-		else
-			return createMasks(pane);
-	}
-
-	/**
-	* createMasks
-	*
-	* Generates both DIV (ALWAYS used) and IFRAME (optional) elements as masks
-	* An IFRAME mask is created *under* the DIV when maskObjects=true, because a DIV cannot mask an applet
-	*
-	* @param {string}	pane
-	*/
-,	createMasks = function (pane) {
-		var
-			$P		= $Ps[pane]
-		,	s		= state[pane]
-		,	o		= options[pane]
-		,	z		= options.zIndexes
-		//,	objMask	= o.maskObjects && s.tagName != "IFRAME" // check for option
-		,	$Masks	= $([])
-		,	isIframe, el, $M, css, i
-		;
-		if (!o.maskContents && !o.maskObjects) return $Masks;
-		// if o.maskObjects=true, then loop TWICE to create BOTH kinds of mask, else only create a DIV
-		for (i=0; i < (o.maskObjects ? 2 : 1); i++) {
-			isIframe = o.maskObjects && i==0;
-			el = document.createElement( isIframe ? "iframe" : "div" );
-			$M = $(el).data("layoutMask", pane); // add data to relate mask to pane
-			el.className = "ui-layout-mask ui-layout-mask-"+ pane; // for user styling
-			css = el.style;
-			// styles common to both DIVs and IFRAMES
-			css.display		= "block";
-			css.position	= "absolute";
-			css.background	= "#FFF";
-			if (isIframe) { // IFRAME-only props
-				el.frameborder = 0;
-				el.src		= "about:blank";
-				//el.allowTransparency = true; - for IE, but breaks masking ability!
-				css.opacity	= 0;
-				css.filter	= "Alpha(Opacity='0')";
-				css.border	= 0;
-			}
-			// if pane is an IFRAME, then must mask the pane itself
-			if (s.tagName == "IFRAME") {
-				// NOTE sizing done by a subroutine so can be called during live-resizing
-				css.zIndex	= z.pane_normal+1; // 1-higher than pane
-				$N.append( el ); // append to LAYOUT CONTAINER
-			}
-			// otherwise put masks *inside the pane* to mask its contents
-			else {
-				$M.addClass("ui-layout-mask-inside-pane");
-				css.zIndex	= o.maskZindex || z.content_mask; // usually 1, but customizable
-				css.top		= 0;
-				css.left	= 0;
-				css.width	= "100%";
-				css.height	= "100%";
-				$P.append( el ); // append INSIDE pane element
-			}
-			// add to return object
-			$Masks = $Masks.add( el );
-			// add Mask to cached array so can be resized & reused
-			$Ms = $Ms.add( el );
-		}
-		return $Masks;
-	}
-
-
-	/**
-	* Destroy this layout and reset all elements
-	*
-	* @param {boolean=}	[destroyChildren=false]		Destory Child-Layouts first?
-	*/
-,	destroy = function (evt_or_destroyChildren, destroyChildren) {
-		// UNBIND layout events and remove global object
-		$(window).unbind("."+ sID);		// resize & unload
-		$(document).unbind("."+ sID);	// keyDown (hotkeys)
-
-		if (typeof evt_or_destroyChildren === "object")
-			// stopPropagation if called by trigger("layoutdestroy") - use evtPane utility 
-			evtPane(evt_or_destroyChildren);
-		else // no event, so transfer 1st param to destroyChildren param
-			destroyChildren = evt_or_destroyChildren;
-
-		// need to look for parent layout BEFORE we remove the container data, else skips a level
-		//var parentPane = Instance.hasParentLayout ? $.layout.getParentPaneInstance( $N ) : null;
-
-		// reset layout-container
-		$N	.clearQueue()
-			.removeData("layout")
-			.removeData("layoutContainer")
-			.removeClass(options.containerClass)
-			.unbind("."+ sID) // remove ALL Layout events
-		;
-
-		// remove all mask elements that have been created
-		$Ms.remove();
-
-		// loop all panes to remove layout classes, attributes and bindings
-		$.each(_c.allPanes, function (i, pane) {
-			removePane( pane, false, true, destroyChildren ); // true = skipResize
-		});
-
-		// do NOT reset container CSS if is a 'pane' (or 'content') in an outer-layout - ie, THIS layout is 'nested'
-		var css = "layoutCSS";
-		if ($N.data(css) && !$N.data("layoutRole")) // RESET CSS
-			$N.css( $N.data(css) ).removeData(css);
-
-		// for full-page layouts, also reset the <HTML> CSS
-		if (sC.tagName === "BODY" && ($N = $("html")).data(css)) // RESET <HTML> CSS
-			$N.css( $N.data(css) ).removeData(css);
-
-		// trigger plugins for this layout, if there are any
-		runPluginCallbacks( Instance, $.layout.onDestroy );
-
-		// trigger state-management and onunload callback
-		unload();
-
-		// clear the Instance of everything except for container & options (so could recreate)
-		// RE-CREATE: myLayout = myLayout.container.layout( myLayout.options );
-		for (var n in Instance)
-			if (!n.match(/^(container|options)$/)) delete Instance[ n ];
-		// add a 'destroyed' flag to make it easy to check
-		Instance.destroyed = true;
-
-		// if this is a child layout, CLEAR the child-pointer in the parent
-		/* for now the pointer REMAINS, but with only container, options and destroyed keys
-		if (parentPane) {
-			var layout	= parentPane.pane.data("parentLayout")
-			,	key		= layout.options.instanceKey || 'error';
-			// THIS SYNTAX MAY BE WRONG!
-			parentPane.children[key] = layout.children[ parentPane.name ].children[key] = null;
-		}
-		*/
-
-		return Instance; // for coding convenience
-	}
-
-	/**
-	* Remove a pane from the layout - subroutine of destroy()
-	*
-	* @see  destroy()
-	* @param {(string|Object)}	evt_or_pane			The pane to process
-	* @param {boolean=}			[remove=false]		Remove the DOM element?
-	* @param {boolean=}			[skipResize=false]	Skip calling resizeAll()?
-	* @param {boolean=}			[destroyChild=true]	Destroy Child-layouts? If not passed, obeys options setting
-	*/
-,	removePane = function (evt_or_pane, remove, skipResize, destroyChild) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$P	= $Ps[pane]
-		,	$C	= $Cs[pane]
-		,	$R	= $Rs[pane]
-		,	$T	= $Ts[pane]
-		;
-		// NOTE: elements can still exist even after remove()
-		//		so check for missing data(), which is cleared by removed()
-		if ($P && $.isEmptyObject( $P.data() )) $P = false;
-		if ($C && $.isEmptyObject( $C.data() )) $C = false;
-		if ($R && $.isEmptyObject( $R.data() )) $R = false;
-		if ($T && $.isEmptyObject( $T.data() )) $T = false;
-
-		if ($P) $P.stop(true, true);
-
-		var	o	= options[pane]
-		,	s	= state[pane]
-		,	d	= "layout"
-		,	css	= "layoutCSS"
-		,	pC	= children[pane]
-		,	hasChildren	= $.isPlainObject( pC ) && !$.isEmptyObject( pC )
-		,	destroy		= destroyChild !== undefined ? destroyChild : o.destroyChildren
-		;
-		// FIRST destroy the child-layout(s)
-		if (hasChildren && destroy) {
-			$.each( pC, function (key, child) {
-				if (!child.destroyed)
-					child.destroy(true);// tell child-layout to destroy ALL its child-layouts too
-				if (child.destroyed)	// destroy was successful
-					delete pC[key];
-			});
-			// if no more children, remove the children hash
-			if ($.isEmptyObject( pC )) {
-				pC = children[pane] = null; // clear children hash
-				hasChildren = false;
-			}
-		}
-
-		// Note: can't 'remove' a pane element with non-destroyed children
-		if ($P && remove && !hasChildren)
-			$P.remove(); // remove the pane-element and everything inside it
-		else if ($P && $P[0]) {
-			//	create list of ALL pane-classes that need to be removed
-			var	root	= o.paneClass // default="ui-layout-pane"
-			,	pRoot	= root +"-"+ pane // eg: "ui-layout-pane-west"
-			,	_open	= "-open"
-			,	_sliding= "-sliding"
-			,	_closed	= "-closed"
-			,	classes	= [	root, root+_open, root+_closed, root+_sliding,		// generic classes
-							pRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ]	// pane-specific classes
-			;
-			$.merge(classes, getHoverClasses($P, true)); // ADD hover-classes
-			// remove all Layout classes from pane-element
-			$P	.removeClass( classes.join(" ") ) // remove ALL pane-classes
-				.removeData("parentLayout")
-				.removeData("layoutPane")
-				.removeData("layoutRole")
-				.removeData("layoutEdge")
-				.removeData("autoHidden")	// in case set
-				.unbind("."+ sID) // remove ALL Layout events
-				// TODO: remove these extra unbind commands when jQuery is fixed
-				//.unbind("mouseenter"+ sID)
-				//.unbind("mouseleave"+ sID)
-			;
-			// do NOT reset CSS if this pane/content is STILL the container of a nested layout!
-			// the nested layout will reset its 'container' CSS when/if it is destroyed
-			if (hasChildren && $C) {
-				// a content-div may not have a specific width, so give it one to contain the Layout
-				$C.width( $C.width() );
-				$.each( pC, function (key, child) {
-					child.resizeAll(); // resize the Layout
-				});
-			}
-			else if ($C)
-				$C.css( $C.data(css) ).removeData(css).removeData("layoutRole");
-			// remove pane AFTER content in case there was a nested layout
-			if (!$P.data(d))
-				$P.css( $P.data(css) ).removeData(css);
-		}
-
-		// REMOVE pane resizer and toggler elements
-		if ($T) $T.remove();
-		if ($R) $R.remove();
-
-		// CLEAR all pointers and state data
-		Instance[pane] = $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = false;
-		s = { removed: true };
-
-		if (!skipResize)
-			resizeAll();
-	}
-
-
-/*
- * ###########################
- *	   ACTION METHODS
- * ###########################
- */
-
-	/**
-	* @param {string}	pane
-	*/
-,	_hidePane = function (pane) {
-		var $P	= $Ps[pane]
-		,	o	= options[pane]
-		,	s	= $P[0].style
-		;
-		if (o.useOffscreenClose) {
-			if (!$P.data(_c.offscreenReset))
-				$P.data(_c.offscreenReset, { left: s.left, right: s.right });
-			$P.css( _c.offscreenCSS );
-		}
-		else
-			$P.hide().removeData(_c.offscreenReset);
-	}
-
-	/**
-	* @param {string}	pane
-	*/
-,	_showPane = function (pane) {
-		var $P	= $Ps[pane]
-		,	o	= options[pane]
-		,	off	= _c.offscreenCSS
-		,	old	= $P.data(_c.offscreenReset)
-		,	s	= $P[0].style
-		;
-		$P	.show() // ALWAYS show, just in case
-			.removeData(_c.offscreenReset);
-		if (o.useOffscreenClose && old) {
-			if (s.left == off.left)
-				s.left = old.left;
-			if (s.right == off.right)
-				s.right = old.right;
-		}
-	}
-
-
-	/**
-	* Completely 'hides' a pane, including its spacing - as if it does not exist
-	* The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
-	*
-	* @param {(string|Object)}	evt_or_pane			The pane being hidden, ie: north, south, east, or west
-	* @param {boolean=}			[noAnimation=false]	
-	*/
-,	hide = function (evt_or_pane, noAnimation) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	o	= options[pane]
-		,	s	= state[pane]
-		,	$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		;
-		if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
-
-		// onhide_start callback - will CANCEL hide if returns false
-		if (state.initialized && false === _runCallbacks("onhide_start", pane)) return;
-
-		s.isSliding = false; // just in case
-		delete state.panesSliding[pane];
-
-		// now hide the elements
-		if ($R) $R.hide(); // hide resizer-bar
-		if (!state.initialized || s.isClosed) {
-			s.isClosed = true; // to trigger open-animation on show()
-			s.isHidden  = true;
-			s.isVisible = false;
-			if (!state.initialized)
-				_hidePane(pane); // no animation when loading page
-			sizeMidPanes(_c[pane].dir === "horz" ? "" : "center");
-			if (state.initialized || o.triggerEventsOnLoad)
-				_runCallbacks("onhide_end", pane);
-		}
-		else {
-			s.isHiding = true; // used by onclose
-			close(pane, false, noAnimation); // adjust all panes to fit
-		}
-	}
-
-	/**
-	* Show a hidden pane - show as 'closed' by default unless openPane = true
-	*
-	* @param {(string|Object)}	evt_or_pane			The pane being opened, ie: north, south, east, or west
-	* @param {boolean=}			[openPane=false]
-	* @param {boolean=}			[noAnimation=false]
-	* @param {boolean=}			[noAlert=false]
-	*/
-,	show = function (evt_or_pane, openPane, noAnimation, noAlert) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	o	= options[pane]
-		,	s	= state[pane]
-		,	$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		;
-		if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
-
-		// onshow_start callback - will CANCEL show if returns false
-		if (false === _runCallbacks("onshow_start", pane)) return;
-
-		s.isShowing = true; // used by onopen/onclose
-		//s.isHidden  = false; - will be set by open/close - if not cancelled
-		s.isSliding = false; // just in case
-		delete state.panesSliding[pane];
-
-		// now show the elements
-		//if ($R) $R.show(); - will be shown by open/close
-		if (openPane === false)
-			close(pane, true); // true = force
-		else
-			open(pane, false, noAnimation, noAlert); // adjust all panes to fit
-	}
-
-
-	/**
-	* Toggles a pane open/closed by calling either open or close
-	*
-	* @param {(string|Object)}	evt_or_pane		The pane being toggled, ie: north, south, east, or west
-	* @param {boolean=}			[slide=false]
-	*/
-,	toggle = function (evt_or_pane, slide) {
-		if (!isInitialized()) return;
-		var	evt		= evtObj(evt_or_pane)
-		,	pane	= evtPane.call(this, evt_or_pane)
-		,	s		= state[pane]
-		;
-		if (evt) // called from to $R.dblclick OR triggerPaneEvent
-			evt.stopImmediatePropagation();
-		if (s.isHidden)
-			show(pane); // will call 'open' after unhiding it
-		else if (s.isClosed)
-			open(pane, !!slide);
-		else
-			close(pane);
-	}
-
-
-	/**
-	* Utility method used during init or other auto-processes
-	*
-	* @param {string}	pane   The pane being closed
-	* @param {boolean=}	[setHandles=false]
-	*/
-,	_closePane = function (pane, setHandles) {
-		var
-			$P	= $Ps[pane]
-		,	s	= state[pane]
-		;
-		_hidePane(pane);
-		s.isClosed = true;
-		s.isVisible = false;
-		if (setHandles) setAsClosed(pane);
-	}
-
-	/**
-	* Close the specified pane (animation optional), and resize all other panes as needed
-	*
-	* @param {(string|Object)}	evt_or_pane			The pane being closed, ie: north, south, east, or west
-	* @param {boolean=}			[force=false]
-	* @param {boolean=}			[noAnimation=false]
-	* @param {boolean=}			[skipCallback=false]
-	*/
-,	close = function (evt_or_pane, force, noAnimation, skipCallback) {
-		var	pane = evtPane.call(this, evt_or_pane);
-		// if pane has been initialized, but NOT the complete layout, close pane instantly
-		if (!state.initialized && $Ps[pane]) {
-			_closePane(pane, true); // INIT pane as closed
-			return;
-		}
-		if (!isInitialized()) return;
-
-		var
-			$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		,	$T	= $Ts[pane]
-		,	o	= options[pane]
-		,	s	= state[pane]
-		,	c	= _c[pane]
-		,	doFX, isShowing, isHiding, wasSliding;
-
-		// QUEUE in case another action/animation is in progress
-		$N.queue(function( queueNext ){
-
-			if ( !$P
-			||	(!o.closable && !s.isShowing && !s.isHiding)	// invalid request // (!o.resizable && !o.closable) ???
-			||	(!force && s.isClosed && !s.isShowing)			// already closed
-			) return queueNext();
-
-			// onclose_start callback - will CANCEL hide if returns false
-			// SKIP if just 'showing' a hidden pane as 'closed'
-			var abort = !s.isShowing && false === _runCallbacks("onclose_start", pane);
-
-			// transfer logic vars to temp vars
-			isShowing	= s.isShowing;
-			isHiding	= s.isHiding;
-			wasSliding	= s.isSliding;
-			// now clear the logic vars (REQUIRED before aborting)
-			delete s.isShowing;
-			delete s.isHiding;
-
-			if (abort) return queueNext();
-
-			doFX		= !noAnimation && !s.isClosed && (o.fxName_close != "none");
-			s.isMoving	= true;
-			s.isClosed	= true;
-			s.isVisible	= false;
-			// update isHidden BEFORE sizing panes
-			if (isHiding) s.isHidden = true;
-			else if (isShowing) s.isHidden = false;
-
-			if (s.isSliding) // pane is being closed, so UNBIND trigger events
-				bindStopSlidingEvents(pane, false); // will set isSliding=false
-			else // resize panes adjacent to this one
-				sizeMidPanes(_c[pane].dir === "horz" ? "" : "center", false); // false = NOT skipCallback
-
-			// if this pane has a resizer bar, move it NOW - before animation
-			setAsClosed(pane);
-
-			// CLOSE THE PANE
-			if (doFX) { // animate the close
-				lockPaneForFX(pane, true);	// need to set left/top so animation will work
-				$P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
-					lockPaneForFX(pane, false); // undo
-					if (s.isClosed) close_2();
-					queueNext();
-				});
-			}
-			else { // hide the pane without animation
-				_hidePane(pane);
-				close_2();
-				queueNext();
-			};
-		});
-
-		// SUBROUTINE
-		function close_2 () {
-			s.isMoving	= false;
-			bindStartSlidingEvents(pane, true); // will enable if o.slidable = true
-
-			// if opposite-pane was autoClosed, see if it can be autoOpened now
-			var altPane = _c.oppositeEdge[pane];
-			if (state[ altPane ].noRoom) {
-				setSizeLimits( altPane );
-				makePaneFit( altPane );
-			}
-
-			if (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) {
-				// onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
-				if (!isShowing)	_runCallbacks("onclose_end", pane);
-				// onhide OR onshow callback
-				if (isShowing)	_runCallbacks("onshow_end", pane);
-				if (isHiding)	_runCallbacks("onhide_end", pane);
-			}
-		}
-	}
-
-	/**
-	* @param {string}	pane	The pane just closed, ie: north, south, east, or west
-	*/
-,	setAsClosed = function (pane) {
-		if (!$Rs[pane]) return; // handles not initialized yet!
-		var
-			$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		,	$T		= $Ts[pane]
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	side	= _c[pane].side
-		,	rClass	= o.resizerClass
-		,	tClass	= o.togglerClass
-		,	_pane	= "-"+ pane // used for classNames
-		,	_open	= "-open"
-		,	_sliding= "-sliding"
-		,	_closed	= "-closed"
-		;
-		$R
-			.css(side, sC.inset[side]) // move the resizer
-			.removeClass( rClass+_open +" "+ rClass+_pane+_open )
-			.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
-			.addClass( rClass+_closed +" "+ rClass+_pane+_closed )
-		;
-		// DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvents?
-		if (o.resizable && $.layout.plugins.draggable)
-			$R
-				.draggable("disable")
-				.removeClass("ui-state-disabled") // do NOT apply disabled styling - not suitable here
-				.css("cursor", "default")
-				.attr("title","")
-			;
-
-		// if pane has a toggler button, adjust that too
-		if ($T) {
-			$T
-				.removeClass( tClass+_open +" "+ tClass+_pane+_open )
-				.addClass( tClass+_closed +" "+ tClass+_pane+_closed )
-				.attr("title", o.tips.Open) // may be blank
-			;
-			// toggler-content - if exists
-			$T.children(".content-open").hide();
-			$T.children(".content-closed").css("display","block");
-		}
-
-		// sync any 'pin buttons'
-		syncPinBtns(pane, false);
-
-		if (state.initialized) {
-			// resize 'length' and position togglers for adjacent panes
-			sizeHandles();
-		}
-	}
-
-	/**
-	* Open the specified pane (animation optional), and resize all other panes as needed
-	*
-	* @param {(string|Object)}	evt_or_pane			The pane being opened, ie: north, south, east, or west
-	* @param {boolean=}			[slide=false]
-	* @param {boolean=}			[noAnimation=false]
-	* @param {boolean=}			[noAlert=false]
-	*/
-,	open = function (evt_or_pane, slide, noAnimation, noAlert) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		,	$T	= $Ts[pane]
-		,	o	= options[pane]
-		,	s	= state[pane]
-		,	c	= _c[pane]
-		,	doFX, isShowing
-		;
-		// QUEUE in case another action/animation is in progress
-		$N.queue(function( queueNext ){
-
-			if ( !$P
-			||	(!o.resizable && !o.closable && !s.isShowing)	// invalid request
-			||	(s.isVisible && !s.isSliding)					// already open
-			) return queueNext();
-
-			// pane can ALSO be unhidden by just calling show(), so handle this scenario
-			if (s.isHidden && !s.isShowing) {
-				queueNext(); // call before show() because it needs the queue free
-				show(pane, true);
-				return;
-			}
-
-			if (s.autoResize && s.size != o.size) // resize pane to original size set in options
-				sizePane(pane, o.size, true, true, true); // true=skipCallback/noAnimation/forceResize
-			else
-				// make sure there is enough space available to open the pane
-				setSizeLimits(pane, slide);
-
-			// onopen_start callback - will CANCEL open if returns false
-			var cbReturn = _runCallbacks("onopen_start", pane);
-
-			if (cbReturn === "abort")
-				return queueNext();
-
-			// update pane-state again in case options were changed in onopen_start
-			if (cbReturn !== "NC") // NC = "No Callback"
-				setSizeLimits(pane, slide);
-
-			if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN!
-				syncPinBtns(pane, false); // make sure pin-buttons are reset
-				if (!noAlert && o.tips.noRoomToOpen)
-					alert(o.tips.noRoomToOpen);
-				return queueNext(); // ABORT
-			}
-
-			if (slide) // START Sliding - will set isSliding=true
-				bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane
-			else if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead
-				bindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false
-			else if (o.slidable)
-				bindStartSlidingEvents(pane, false); // UNBIND trigger events
-
-			s.noRoom = false; // will be reset by makePaneFit if 'noRoom'
-			makePaneFit(pane);
-
-			// transfer logic var to temp var
-			isShowing = s.isShowing;
-			// now clear the logic var
-			delete s.isShowing;
-
-			doFX		= !noAnimation && s.isClosed && (o.fxName_open != "none");
-			s.isMoving	= true;
-			s.isVisible	= true;
-			s.isClosed	= false;
-			// update isHidden BEFORE sizing panes - WHY??? Old?
-			if (isShowing) s.isHidden = false;
-
-			if (doFX) { // ANIMATE
-				// mask adjacent panes with objects
-				lockPaneForFX(pane, true);	// need to set left/top so animation will work
-					$P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
-					lockPaneForFX(pane, false); // undo
-					if (s.isVisible) open_2(); // continue
-					queueNext();
-				});
-			}
-			else { // no animation
-				_showPane(pane);// just show pane and...
-				open_2();		// continue
-				queueNext();
-			};
-		});
-
-		// SUBROUTINE
-		function open_2 () {
-			s.isMoving	= false;
-
-			// cure iframe display issues
-			_fixIframe(pane);
-
-			// NOTE: if isSliding, then other panes are NOT 'resized'
-			if (!s.isSliding) { // resize all panes adjacent to this one
-				sizeMidPanes(_c[pane].dir=="vert" ? "center" : "", false); // false = NOT skipCallback
-			}
-
-			// set classes, position handles and execute callbacks...
-			setAsOpen(pane);
-		};
-	
-	}
-
-	/**
-	* @param {string}	pane		The pane just opened, ie: north, south, east, or west
-	* @param {boolean=}	[skipCallback=false]
-	*/
-,	setAsOpen = function (pane, skipCallback) {
-		var 
-			$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		,	$T		= $Ts[pane]
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	side	= _c[pane].side
-		,	rClass	= o.resizerClass
-		,	tClass	= o.togglerClass
-		,	_pane	= "-"+ pane // used for classNames
-		,	_open	= "-open"
-		,	_closed	= "-closed"
-		,	_sliding= "-sliding"
-		;
-		$R
-			.css(side, sC.inset[side] + getPaneSize(pane)) // move the resizer
-			.removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
-			.addClass( rClass+_open +" "+ rClass+_pane+_open )
-		;
-		if (s.isSliding)
-			$R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
-		else // in case 'was sliding'
-			$R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
-
-		removeHover( 0, $R ); // remove hover classes
-		if (o.resizable && $.layout.plugins.draggable)
-			$R	.draggable("enable")
-				.css("cursor", o.resizerCursor)
-				.attr("title", o.tips.Resize);
-		else if (!s.isSliding)
-			$R.css("cursor", "default"); // n-resize, s-resize, etc
-
-		// if pane also has a toggler button, adjust that too
-		if ($T) {
-			$T	.removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
-				.addClass( tClass+_open +" "+ tClass+_pane+_open )
-				.attr("title", o.tips.Close); // may be blank
-			removeHover( 0, $T ); // remove hover classes
-			// toggler-content - if exists
-			$T.children(".content-closed").hide();
-			$T.children(".content-open").css("display","block");
-		}
-
-		// sync any 'pin buttons'
-		syncPinBtns(pane, !s.isSliding);
-
-		// update pane-state dimensions - BEFORE resizing content
-		$.extend(s, elDims($P));
-
-		if (state.initialized) {
-			// resize resizer & toggler sizes for all panes
-			sizeHandles();
-			// resize content every time pane opens - to be sure
-			sizeContent(pane, true); // true = remeasure headers/footers, even if 'pane.isMoving'
-		}
-
-		if (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(":visible")) {
-			// onopen callback
-			_runCallbacks("onopen_end", pane);
-			// onshow callback - TODO: should this be here?
-			if (s.isShowing) _runCallbacks("onshow_end", pane);
-
-			// ALSO call onresize because layout-size *may* have changed while pane was closed
-			if (state.initialized)
-				_runCallbacks("onresize_end", pane);
-		}
-
-		// TODO: Somehow sizePane("north") is being called after this point???
-	}
-
-
-	/**
-	* slideOpen / slideClose / slideToggle
-	*
-	* Pass-though methods for sliding
-	*/
-,	slideOpen = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	evt		= evtObj(evt_or_pane)
-		,	pane	= evtPane.call(this, evt_or_pane)
-		,	s		= state[pane]
-		,	delay	= options[pane].slideDelay_open
-		;
-		// prevent event from triggering on NEW resizer binding created below
-		if (evt) evt.stopImmediatePropagation();
-
-		if (s.isClosed && evt && evt.type === "mouseenter" && delay > 0)
-			// trigger = mouseenter - use a delay
-			timer.set(pane+"_openSlider", open_NOW, delay);
-		else
-			open_NOW(); // will unbind events if is already open
-
-		/**
-		* SUBROUTINE for timed open
-		*/
-		function open_NOW () {
-			if (!s.isClosed) // skip if no longer closed!
-				bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane
-			else if (!s.isMoving)
-				open(pane, true); // true = slide - open() will handle binding
-		};
-	}
-
-,	slideClose = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	evt		= evtObj(evt_or_pane)
-		,	pane	= evtPane.call(this, evt_or_pane)
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	delay	= s.isMoving ? 1000 : 300 // MINIMUM delay - option may override
-		;
-		if (s.isClosed || s.isResizing)
-			return; // skip if already closed OR in process of resizing
-		else if (o.slideTrigger_close === "click")
-			close_NOW(); // close immediately onClick
-		else if (o.preventQuickSlideClose && s.isMoving)
-			return; // handle Chrome quick-close on slide-open
-		else if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane]))
-			return; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE
-		else if (evt) // trigger = mouseleave - use a delay
-			// 1 sec delay if 'opening', else .3 sec
-			timer.set(pane+"_closeSlider", close_NOW, max(o.slideDelay_close, delay));
-		else // called programically
-			close_NOW();
-
-		/**
-		* SUBROUTINE for timed close
-		*/
-		function close_NOW () {
-			if (s.isClosed) // skip 'close' if already closed!
-				bindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here?
-			else if (!s.isMoving)
-				close(pane); // close will handle unbinding
-		};
-	}
-
-	/**
-	* @param {(string|Object)}	evt_or_pane		The pane being opened, ie: north, south, east, or west
-	*/
-,	slideToggle = function (evt_or_pane) {
-		var pane = evtPane.call(this, evt_or_pane);
-		toggle(pane, true);
-	}
-
-
-	/**
-	* Must set left/top on East/South panes so animation will work properly
-	*
-	* @param {string}	pane	The pane to lock, 'east' or 'south' - any other is ignored!
-	* @param {boolean}	doLock  true = set left/top, false = remove
-	*/
-,	lockPaneForFX = function (pane, doLock) {
-		var $P	= $Ps[pane]
-		,	s	= state[pane]
-		,	o	= options[pane]
-		,	z	= options.zIndexes
-		;
-		if (doLock) {
-			showMasks( pane, { animation: true, objectsOnly: true });
-			$P.css({ zIndex: z.pane_animate }); // overlay all elements during animation
-			if (pane=="south")
-				$P.css({ top: sC.inset.top + sC.innerHeight - $P.outerHeight() });
-			else if (pane=="east")
-				$P.css({ left: sC.inset.left + sC.innerWidth - $P.outerWidth() });
-		}
-		else { // animation DONE - RESET CSS
-			hideMasks();
-			$P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) });
-			if (pane=="south")
-				$P.css({ top: "auto" });
-			// if pane is positioned 'off-screen', then DO NOT screw with it!
-			else if (pane=="east" && !$P.css("left").match(/\-99999/))
-				$P.css({ left: "auto" });
-			// fix anti-aliasing in IE - only needed for animations that change opacity
-			if (browser.msie && o.fxOpacityFix && o.fxName_open != "slide" && $P.css("filter") && $P.css("opacity") == 1)
-				$P[0].style.removeAttribute('filter');
-		}
-	}
-
-
-	/**
-	* Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
-	*
-	* @see  open(), close()
-	* @param {string}	pane	The pane to enable/disable, 'north', 'south', etc.
-	* @param {boolean}	enable	Enable or Disable sliding?
-	*/
-,	bindStartSlidingEvents = function (pane, enable) {
-		var o		= options[pane]
-		,	$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		,	evtName	= o.slideTrigger_open.toLowerCase()
-		;
-		if (!$R || (enable && !o.slidable)) return;
-
-		// make sure we have a valid event
-		if (evtName.match(/mouseover/))
-			evtName = o.slideTrigger_open = "mouseenter";
-		else if (!evtName.match(/(click|dblclick|mouseenter)/)) 
-			evtName = o.slideTrigger_open = "click";
-
-		// must remove double-click-toggle when using dblclick-slide
-		if (o.resizerDblClickToggle && evtName.match(/click/)) {
-			$R[enable ? "unbind" : "bind"]('dblclick.'+ sID, toggle)
-		}
-
-		$R
-			// add or remove event
-			[enable ? "bind" : "unbind"](evtName +'.'+ sID, slideOpen)
-			// set the appropriate cursor & title/tip
-			.css("cursor", enable ? o.sliderCursor : "default")
-			.attr("title", enable ? o.tips.Slide : "")
-		;
-	}
-
-	/**
-	* Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed
-	* Also increases zIndex when pane is sliding open
-	* See bindStartSlidingEvents for code to control 'slide open'
-	*
-	* @see  slideOpen(), slideClose()
-	* @param {string}	pane	The pane to process, 'north', 'south', etc.
-	* @param {boolean}	enable	Enable or Disable events?
-	*/
-,	bindStopSlidingEvents = function (pane, enable) {
-		var	o		= options[pane]
-		,	s		= state[pane]
-		,	c		= _c[pane]
-		,	z		= options.zIndexes
-		,	evtName	= o.slideTrigger_close.toLowerCase()
-		,	action	= (enable ? "bind" : "unbind")
-		,	$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		;
-		timer.clear(pane+"_closeSlider"); // just in case
-
-		if (enable) {
-			s.isSliding = true;
-			state.panesSliding[pane] = true;
-			// remove 'slideOpen' event from resizer
-			// ALSO will raise the zIndex of the pane & resizer
-			bindStartSlidingEvents(pane, false);
-		}
-		else {
-			s.isSliding = false;
-			delete state.panesSliding[pane];
-		}
-
-		// RE/SET zIndex - increases when pane is sliding-open, resets to normal when not
-		$P.css("zIndex", enable ? z.pane_sliding : z.pane_normal);
-		$R.css("zIndex", enable ? z.pane_sliding+2 : z.resizer_normal); // NOTE: mask = pane_sliding+1
-
-		// make sure we have a valid event
-		if (!evtName.match(/(click|mouseleave)/))
-			evtName = o.slideTrigger_close = "mouseleave"; // also catches 'mouseout'
-
-		// add/remove slide triggers
-		$R[action](evtName, slideClose); // base event on resize
-		// need extra events for mouseleave
-		if (evtName === "mouseleave") {
-			// also close on pane.mouseleave
-			$P[action]("mouseleave."+ sID, slideClose);
-			// cancel timer when mouse moves between 'pane' and 'resizer'
-			$R[action]("mouseenter."+ sID, cancelMouseOut);
-			$P[action]("mouseenter."+ sID, cancelMouseOut);
-		}
-
-		if (!enable)
-			timer.clear(pane+"_closeSlider");
-		else if (evtName === "click" && !o.resizable) {
-			// IF pane is not resizable (which already has a cursor and tip) 
-			// then set the a cursor & title/tip on resizer when sliding
-			$R.css("cursor", enable ? o.sliderCursor : "default");
-			$R.attr("title", enable ? o.tips.Close : ""); // use Toggler-tip, eg: "Close Pane"
-		}
-
-		// SUBROUTINE for mouseleave timer clearing
-		function cancelMouseOut (evt) {
-			timer.clear(pane+"_closeSlider");
-			evt.stopPropagation();
-		}
-	}
-
-
-	/**
-	* Hides/closes a pane if there is insufficient room - reverses this when there is room again
-	* MUST have already called setSizeLimits() before calling this method
-	*
-	* @param {string}	pane					The pane being resized
-	* @param {boolean=}	[isOpening=false]		Called from onOpen?
-	* @param {boolean=}	[skipCallback=false]	Should the onresize callback be run?
-	* @param {boolean=}	[force=false]
-	*/
-,	makePaneFit = function (pane, isOpening, skipCallback, force) {
-		var	o	= options[pane]
-		,	s	= state[pane]
-		,	c	= _c[pane]
-		,	$P	= $Ps[pane]
-		,	$R	= $Rs[pane]
-		,	isSidePane 	= c.dir==="vert"
-		,	hasRoom		= false
-		;
-		// special handling for center & east/west panes
-		if (pane === "center" || (isSidePane && s.noVerticalRoom)) {
-			// see if there is enough room to display the pane
-			// ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth);
-			hasRoom = (s.maxHeight >= 0);
-			if (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now
-				_showPane(pane);
-				if ($R) $R.show();
-				s.isVisible = true;
-				s.noRoom = false;
-				if (isSidePane) s.noVerticalRoom = false;
-				_fixIframe(pane);
-			}
-			else if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now
-				_hidePane(pane);
-				if ($R) $R.hide();
-				s.isVisible = false;
-				s.noRoom = true;
-			}
-		}
-
-		// see if there is enough room to fit the border-pane
-		if (pane === "center") {
-			// ignore center in this block
-		}
-		else if (s.minSize <= s.maxSize) { // pane CAN fit
-			hasRoom = true;
-			if (s.size > s.maxSize) // pane is too big - shrink it
-				sizePane(pane, s.maxSize, skipCallback, true, force); // true = noAnimation
-			else if (s.size < s.minSize) // pane is too small - enlarge it
-				sizePane(pane, s.minSize, skipCallback, true, force); // true = noAnimation
-			// need s.isVisible because new pseudoClose method keeps pane visible, but off-screen
-			else if ($R && s.isVisible && $P.is(":visible")) {
-				// make sure resizer-bar is positioned correctly
-				// handles situation where nested layout was 'hidden' when initialized
-				var	pos = s.size + sC.inset[c.side];
-				if ($.layout.cssNum( $R, c.side ) != pos) $R.css( c.side, pos );
-			}
-
-			// if was previously hidden due to noRoom, then RESET because NOW there is room
-			if (s.noRoom) {
-				// s.noRoom state will be set by open or show
-				if (s.wasOpen && o.closable) {
-					if (o.autoReopen)
-						open(pane, false, true, true); // true = noAnimation, true = noAlert
-					else // leave the pane closed, so just update state
-						s.noRoom = false;
-				}
-				else
-					show(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert
-			}
-		}
-		else { // !hasRoom - pane CANNOT fit
-			if (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now...
-				s.noRoom = true; // update state
-				s.wasOpen = !s.isClosed && !s.isSliding;
-				if (s.isClosed){} // SKIP
-				else if (o.closable) // 'close' if possible
-					close(pane, true, true); // true = force, true = noAnimation
-				else // 'hide' pane if cannot just be closed
-					hide(pane, true); // true = noAnimation
-			}
-		}
-	}
-
-
-	/**
-	* manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized'
-	*
-	* @param {(string|Object)}	evt_or_pane				The pane being resized
-	* @param {number}			size					The *desired* new size for this pane - will be validated
-	* @param {boolean=}			[skipCallback=false]	Should the onresize callback be run?
-	* @param {boolean=}			[noAnimation=false]
-	* @param {boolean=}			[force=false]			Force resizing even if does not seem necessary
-	*/
-,	manualSizePane = function (evt_or_pane, size, skipCallback, noAnimation, force) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	o	= options[pane]
-		,	s	= state[pane]
-		//	if resizing callbacks have been delayed and resizing is now DONE, force resizing to complete...
-		,	forceResize = force || (o.livePaneResizing && !s.isResizing)
-		;
-		// ANY call to manualSizePane disables autoResize - ie, percentage sizing
-		s.autoResize = false;
-		// flow-through...
-		sizePane(pane, size, skipCallback, noAnimation, forceResize); // will animate resize if option enabled
-	}
-
-	/**
-	* sizePane is called only by internal methods whenever a pane needs to be resized
-	*
-	* @param {(string|Object)}	evt_or_pane				The pane being resized
-	* @param {number}			size					The *desired* new size for this pane - will be validated
-	* @param {boolean=}			[skipCallback=false]	Should the onresize callback be run?
-	* @param {boolean=}			[noAnimation=false]
-	* @param {boolean=}			[force=false]			Force resizing even if does not seem necessary
-	*/
-,	sizePane = function (evt_or_pane, size, skipCallback, noAnimation, force) {
-		if (!isInitialized()) return;
-		var	pane	= evtPane.call(this, evt_or_pane) // probably NEVER called from event?
-		,	o		= options[pane]
-		,	s		= state[pane]
-		,	$P		= $Ps[pane]
-		,	$R		= $Rs[pane]
-		,	side	= _c[pane].side
-		,	dimName	= _c[pane].sizeType.toLowerCase()
-		,	skipResizeWhileDragging = s.isResizing && !o.triggerEventsDuringLiveResize
-		,	doFX	= noAnimation !== true && o.animatePaneSizing
-		,	oldSize, newSize
-		;
-		// QUEUE in case another action/animation is in progress
-		$N.queue(function( queueNext ){
-			// calculate 'current' min/max sizes
-			setSizeLimits(pane); // update pane-state
-			oldSize = s.size;
-			size = _parseSize(pane, size); // handle percentages & auto
-			size = max(size, _parseSize(pane, o.minSize));
-			size = min(size, s.maxSize);
-			if (size < s.minSize) { // not enough room for pane!
-				queueNext(); // call before makePaneFit() because it needs the queue free
-				makePaneFit(pane, false, skipCallback);	// will hide or close pane
-				return;
-			}
-
-			// IF newSize is same as oldSize, then nothing to do - abort
-			if (!force && size === oldSize)
-				return queueNext();
-
-			s.newSize = size;
-
-			// onresize_start callback CANNOT cancel resizing because this would break the layout!
-			if (!skipCallback && state.initialized && s.isVisible)
-				_runCallbacks("onresize_start", pane);
-
-			// resize the pane, and make sure its visible
-			newSize = cssSize(pane, size);
-
-			if (doFX && $P.is(":visible")) { // ANIMATE
-				var fx		= $.layout.effects.size[pane] || $.layout.effects.size.all
-				,	easing	= o.fxSettings_size.easing || fx.easing
-				,	z		= options.zIndexes
-				,	props	= {};
-				props[ dimName ] = newSize +'px';
-				s.isMoving = true;
-				// overlay all elements during animation
-				$P.css({ zIndex: z.pane_animate })
-				  .show().animate( props, o.fxSpeed_size, easing, function(){
-					// reset zIndex after animation
-					$P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) });
-					s.isMoving = false;
-					delete s.newSize;
-					sizePane_2(); // continue
-					queueNext();
-				});
-			}
-			else { // no animation
-				$P.css( dimName, newSize );	// resize pane
-				delete s.newSize;
-				// if pane is visible, then 
-				if ($P.is(":visible"))
-					sizePane_2(); // continue
-				else {
-					// pane is NOT VISIBLE, so just update state data...
-					// when pane is *next opened*, it will have the new size
-					s.size = size;				// update state.size
-					$.extend(s, elDims($P));	// update state dimensions
-				}
-				queueNext();
-			};
-
-		});
-
-		// SUBROUTINE
-		function sizePane_2 () {
-			/*	Panes are sometimes not sized precisely in some browsers!?
-			 *	This code will resize the pane up to 3 times to nudge the pane to the correct size
-			 */
-			var	actual	= dimName==='width' ? $P.outerWidth() : $P.outerHeight()
-			,	tries	= [{
-						   	pane:		pane
-						,	count:		1
-						,	target:		size
-						,	actual:		actual
-						,	correct:	(size === actual)
-						,	attempt:	size
-						,	cssSize:	newSize
-						}]
-			,	lastTry = tries[0]
-			,	thisTry	= {}
-			,	msg		= 'Inaccurate size after resizing the '+ pane +'-pane.'
-			;
-			while ( !lastTry.correct ) {
-				thisTry = { pane: pane, count: lastTry.count+1, target: size };
-
-				if (lastTry.actual > size)
-					thisTry.attempt = max(0, lastTry.attempt - (lastTry.actual - size));
-				else // lastTry.actual < size
-					thisTry.attempt = max(0, lastTry.attempt + (size - lastTry.actual));
-
-				thisTry.cssSize = cssSize(pane, thisTry.attempt);
-				$P.css( dimName, thisTry.cssSize );
-
-				thisTry.actual	= dimName=='width' ? $P.outerWidth() : $P.outerHeight();
-				thisTry.correct	= (size === thisTry.actual);
-
-				// log attempts and alert the user of this *non-fatal error* (if showDebugMessages)
-				if ( tries.length === 1) {
-					_log(msg, false, true);
-					_log(lastTry, false, true);
-				}
-				_log(thisTry, false, true);
-				// after 4 tries, is as close as its gonna get!
-				if (tries.length > 3) break;
-
-				tries.push( thisTry );
-				lastTry = tries[ tries.length - 1 ];
-			}
-			// END TESTING CODE
-
-			// update pane-state dimensions
-			s.size	= size;
-			$.extend(s, elDims($P));
-
-			if (s.isVisible && $P.is(":visible")) {
-				// reposition the resizer-bar
-				if ($R) $R.css( side, size + sC.inset[side] );
-				// resize the content-div
-				sizeContent(pane);
-			}
-
-			if (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible)
-				_runCallbacks("onresize_end", pane);
-
-			// resize all the adjacent panes, and adjust their toggler buttons
-			// when skipCallback passed, it means the controlling method will handle 'other panes'
-			if (!skipCallback) {
-				// also no callback if live-resize is in progress and NOT triggerEventsDuringLiveResize
-				if (!s.isSliding) sizeMidPanes(_c[pane].dir=="horz" ? "" : "center", skipResizeWhileDragging, force);
-				sizeHandles();
-			}
-
-			// if opposite-pane was autoClosed, see if it can be autoOpened now
-			var altPane = _c.oppositeEdge[pane];
-			if (size < oldSize && state[ altPane ].noRoom) {
-				setSizeLimits( altPane );
-				makePaneFit( altPane, false, skipCallback );
-			}
-
-			// DEBUG - ALERT user/developer so they know there was a sizing problem
-			if (tries.length > 1)
-				_log(msg +'\nSee the Error Console for details.', true, true);
-		}
-	}
-
-	/**
-	* @see  initPanes(), sizePane(), 	resizeAll(), open(), close(), hide()
-	* @param {(Array.<string>|string)}	panes					The pane(s) being resized, comma-delmited string
-	* @param {boolean=}					[skipCallback=false]	Should the onresize callback be run?
-	* @param {boolean=}					[force=false]
-	*/
-,	sizeMidPanes = function (panes, skipCallback, force) {
-		panes = (panes ? panes : "east,west,center").split(",");
-
-		$.each(panes, function (i, pane) {
-			if (!$Ps[pane]) return; // NO PANE - skip
-			var 
-				o		= options[pane]
-			,	s		= state[pane]
-			,	$P		= $Ps[pane]
-			,	$R		= $Rs[pane]
-			,	isCenter= (pane=="center")
-			,	hasRoom	= true
-			,	CSS		= {}
-			//	if pane is not visible, show it invisibly NOW rather than for *each call* in this script
-			,	visCSS	= $.layout.showInvisibly($P)
-
-			,	newCenter	= calcNewCenterPaneDims()
-			;
-
-			// update pane-state dimensions
-			$.extend(s, elDims($P));
-
-			if (pane === "center") {
-				if (!force && s.isVisible && newCenter.width === s.outerWidth && newCenter.height === s.outerHeight) {
-					$P.css(visCSS);
-					return true; // SKIP - pane already the correct size
-				}
-				// set state for makePaneFit() logic
-				$.extend(s, cssMinDims(pane), {
-					maxWidth:	newCenter.width
-				,	maxHeight:	newCenter.height
-				});
-				CSS = newCenter;
-				s.newWidth	= CSS.width;
-				s.newHeight	= CSS.height;
-				// convert OUTER width/height to CSS width/height 
-				CSS.width	= cssW($P, CSS.width);
-				// NEW - allow pane to extend 'below' visible area rather than hide it
-				CSS.height	= cssH($P, CSS.height);
-				hasRoom		= CSS.width >= 0 && CSS.height >= 0; // height >= 0 = ALWAYS TRUE NOW
-
-				// during layout init, try to shrink east/west panes to make room for center
-				if (!state.initialized && o.minWidth > newCenter.width) {
-					var
-						reqPx	= o.minWidth - s.outerWidth
-					,	minE	= options.east.minSize || 0
-					,	minW	= options.west.minSize || 0
-					,	sizeE	= state.east.size
-					,	sizeW	= state.west.size
-					,	newE	= sizeE
-					,	newW	= sizeW
-					;
-					if (reqPx > 0 && state.east.isVisible && sizeE > minE) {
-						newE = max( sizeE-minE, sizeE-reqPx );
-						reqPx -= sizeE-newE;
-					}
-					if (reqPx > 0 && state.west.isVisible && sizeW > minW) {
-						newW = max( sizeW-minW, sizeW-reqPx );
-						reqPx -= sizeW-newW;
-					}
-					// IF we found enough extra space, then resize the border panes as calculated
-					if (reqPx === 0) {
-						if (sizeE && sizeE != minE)
-							sizePane('east', newE, true, true, force); // true = skipCallback/noAnimation - initPanes will handle when done
-						if (sizeW && sizeW != minW)
-							sizePane('west', newW, true, true, force); // true = skipCallback/noAnimation
-						// now start over!
-						sizeMidPanes('center', skipCallback, force);
-						$P.css(visCSS);
-						return; // abort this loop
-					}
-				}
-			}
-			else { // for east and west, set only the height, which is same as center height
-				// set state.min/maxWidth/Height for makePaneFit() logic
-				if (s.isVisible && !s.noVerticalRoom)
-					$.extend(s, elDims($P), cssMinDims(pane))
-				if (!force && !s.noVerticalRoom && newCenter.height === s.outerHeight) {
-					$P.css(visCSS);
-					return true; // SKIP - pane already the correct size
-				}
-				// east/west have same top, bottom & height as center
-				CSS.top		= newCenter.top;
-				CSS.bottom	= newCenter.bottom;
-				s.newSize	= newCenter.height
-				// NEW - allow pane to extend 'below' visible area rather than hide it
-				CSS.height	= cssH($P, newCenter.height);
-				s.maxHeight	= CSS.height;
-				hasRoom		= (s.maxHeight >= 0); // ALWAYS TRUE NOW
-				if (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic
-			}
-
-			if (hasRoom) {
-				// resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized
-				if (!skipCallback && state.initialized)
-					_runCallbacks("onresize_start", pane);
-
-				$P.css(CSS); // apply the CSS to pane
-				if (pane !== "center")
-					sizeHandles(pane); // also update resizer length
-				if (s.noRoom && !s.isClosed && !s.isHidden)
-					makePaneFit(pane); // will re-open/show auto-closed/hidden pane
-				if (s.isVisible) {
-					$.extend(s, elDims($P)); // update pane dimensions
-					if (state.initialized) sizeContent(pane); // also resize the contents, if exists
-				}
-			}
-			else if (!s.noRoom && s.isVisible) // no room for pane
-				makePaneFit(pane); // will hide or close pane
-
-			// reset visibility, if necessary
-			$P.css(visCSS);
-
-			delete s.newSize;
-			delete s.newWidth;
-			delete s.newHeight;
-
-			if (!s.isVisible)
-				return true; // DONE - next pane
-
-			/*
-			* Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
-			* Normally these panes have only 'left' & 'right' positions so pane auto-sizes
-			* ALSO required when pane is an IFRAME because will NOT default to 'full width'
-			*	TODO: Can I use width:100% for a north/south iframe?
-			*	TODO: Sounds like a job for $P.outerWidth( sC.innerWidth ) SETTER METHOD
-			*/
-			if (pane === "center") { // finished processing midPanes
-				var fix = browser.isIE6 || !browser.boxModel;
-				if ($Ps.north && (fix || state.north.tagName=="IFRAME")) 
-					$Ps.north.css("width", cssW($Ps.north, sC.innerWidth));
-				if ($Ps.south && (fix || state.south.tagName=="IFRAME"))
-					$Ps.south.css("width", cssW($Ps.south, sC.innerWidth));
-			}
-
-			// resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized
-			if (!skipCallback && state.initialized)
-				_runCallbacks("onresize_end", pane);
-		});
-	}
-
-
-	/**
-	* @see  window.onresize(), callbacks or custom code
-	* @param {(Object|boolean)=}	evt_or_refresh	If 'true', then also reset pane-positioning
-	*/
-,	resizeAll = function (evt_or_refresh) {
-		var	oldW	= sC.innerWidth
-		,	oldH	= sC.innerHeight
-		;
-		// stopPropagation if called by trigger("layoutdestroy") - use evtPane utility 
-		evtPane(evt_or_refresh);
-
-		// cannot size layout when 'container' is hidden or collapsed
-		if (!$N.is(":visible")) return;
-
-		if (!state.initialized) {
-			_initLayoutElements();
-			return; // no need to resize since we just initialized!
-		}
-
-		if (evt_or_refresh === true && $.isPlainObject(options.outset)) {
-			// update container CSS in case outset option has changed
-			$N.css( options.outset );
-		}
-		// UPDATE container dimensions
-		$.extend(sC, elDims( $N, options.inset ));
-		if (!sC.outerHeight) return;
-
-		// if 'true' passed, refresh pane & handle positioning too
-		if (evt_or_refresh === true) {
-			setPanePosition();
-		}
-
-		// onresizeall_start will CANCEL resizing if returns false
-		// state.container has already been set, so user can access this info for calcuations
-		if (false === _runCallbacks("onresizeall_start")) return false;
-
-		var	// see if container is now 'smaller' than before
-			shrunkH	= (sC.innerHeight < oldH)
-		,	shrunkW	= (sC.innerWidth < oldW)
-		,	$P, o, s
-		;
-		// NOTE special order for sizing: S-N-E-W
-		$.each(["south","north","east","west"], function (i, pane) {
-			if (!$Ps[pane]) return; // no pane - SKIP
-			o = options[pane];
-			s = state[pane];
-			if (s.autoResize && s.size != o.size) // resize pane to original size set in options
-				sizePane(pane, o.size, true, true, true); // true=skipCallback/noAnimation/forceResize
-			else {
-				setSizeLimits(pane);
-				makePaneFit(pane, false, true, true); // true=skipCallback/forceResize
-			}
-		});
-
-		sizeMidPanes("", true, true); // true=skipCallback/forceResize
-		sizeHandles(); // reposition the toggler elements
-
-		// trigger all individual pane callbacks AFTER layout has finished resizing
-		$.each(_c.allPanes, function (i, pane) {
-			$P = $Ps[pane];
-			if (!$P) return; // SKIP
-			if (state[pane].isVisible) // undefined for non-existent panes
-				_runCallbacks("onresize_end", pane); // callback - if exists
-		});
-
-		_runCallbacks("onresizeall_end");
-		//_triggerLayoutEvent(pane, 'resizeall');
-	}
-
-	/**
-	* Whenever a pane resizes or opens that has a nested layout, trigger resizeAll
-	*
-	* @param {(string|Object)}	evt_or_pane		The pane just resized or opened
-	*/
-,	resizeChildren = function (evt_or_pane, skipRefresh) {
-		var	pane = evtPane.call(this, evt_or_pane);
-
-		if (!options[pane].resizeChildren) return;
-
-		// ensure the pane-children are up-to-date
-		if (!skipRefresh) refreshChildren( pane );
-		var pC = children[pane];
-		if ($.isPlainObject( pC )) {
-			// resize one or more children
-			$.each( pC, function (key, child) {
-				if (!child.destroyed) child.resizeAll();
-			});
-		}
-	}
-
-	/**
-	* IF pane has a content-div, then resize all elements inside pane to fit pane-height
-	*
-	* @param {(string|Object)}	evt_or_panes		The pane(s) being resized
-	* @param {boolean=}			[remeasure=false]	Should the content (header/footer) be remeasured?
-	*/
-,	sizeContent = function (evt_or_panes, remeasure) {
-		if (!isInitialized()) return;
-
-		var panes = evtPane.call(this, evt_or_panes);
-		panes = panes ? panes.split(",") : _c.allPanes;
-
-		$.each(panes, function (idx, pane) {
-			var
-				$P	= $Ps[pane]
-			,	$C	= $Cs[pane]
-			,	o	= options[pane]
-			,	s	= state[pane]
-			,	m	= s.content // m = measurements
-			;
-			if (!$P || !$C || !$P.is(":visible")) return true; // NOT VISIBLE - skip
-
-			// if content-element was REMOVED, update OR remove the pointer
-			if (!$C.length) {
-				initContent(pane, false);	// false = do NOT sizeContent() - already there!
-				if (!$C) return;			// no replacement element found - pointer have been removed
-			}
-
-			// onsizecontent_start will CANCEL resizing if returns false
-			if (false === _runCallbacks("onsizecontent_start", pane)) return;
-
-			// skip re-measuring offsets if live-resizing
-			if ((!s.isMoving && !s.isResizing) || o.liveContentResizing || remeasure || m.top == undefined) {
-				_measure();
-				// if any footers are below pane-bottom, they may not measure correctly,
-				// so allow pane overflow and re-measure
-				if (m.hiddenFooters > 0 && $P.css("overflow") === "hidden") {
-					$P.css("overflow", "visible");
-					_measure(); // remeasure while overflowing
-					$P.css("overflow", "hidden");
-				}
-			}
-			// NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders
-			var newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom);
-
-			if (!$C.is(":visible") || m.height != newH) {
-				// size the Content element to fit new pane-size - will autoHide if not enough room
-				setOuterHeight($C, newH, true); // true=autoHide
-				m.height = newH; // save new height
-			};
-
-			if (state.initialized)
-				_runCallbacks("onsizecontent_end", pane);
-
-			function _below ($E) {
-				return max(s.css.paddingBottom, (parseInt($E.css("marginBottom"), 10) || 0));
-			};
-
-			function _measure () {
-				var
-					ignore	= options[pane].contentIgnoreSelector
-				,	$Fs		= $C.nextAll().not(".ui-layout-mask").not(ignore || ":lt(0)") // not :lt(0) = ALL
-				,	$Fs_vis	= $Fs.filter(':visible')
-				,	$F		= $Fs_vis.filter(':last')
-				;
-				m = {
-					top:			$C[0].offsetTop
-				,	height:			$C.outerHeight()
-				,	numFooters:		$Fs.length
-				,	hiddenFooters:	$Fs.length - $Fs_vis.length
-				,	spaceBelow:		0 // correct if no content footer ($E)
-				}
-					m.spaceAbove	= m.top; // just for state - not used in calc
-					m.bottom		= m.top + m.height;
-				if ($F.length)
-					//spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom)
-					m.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F);
-				else // no footer - check marginBottom on Content element itself
-					m.spaceBelow = _below($C);
-			};
-		});
-	}
-
-
-	/**
-	* Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
-	*
-	* @see  initHandles(), open(), close(), resizeAll()
-	* @param {(string|Object)=}		evt_or_panes	The pane(s) being resized
-	*/
-,	sizeHandles = function (evt_or_panes) {
-		var panes = evtPane.call(this, evt_or_panes)
-		panes = panes ? panes.split(",") : _c.borderPanes;
-
-		$.each(panes, function (i, pane) {
-			var 
-				o	= options[pane]
-			,	s	= state[pane]
-			,	$P	= $Ps[pane]
-			,	$R	= $Rs[pane]
-			,	$T	= $Ts[pane]
-			,	$TC
-			;
-			if (!$P || !$R) return;
-
-			var
-				dir			= _c[pane].dir
-			,	_state		= (s.isClosed ? "_closed" : "_open")
-			,	spacing		= o["spacing"+ _state]
-			,	togAlign	= o["togglerAlign"+ _state]
-			,	togLen		= o["togglerLength"+ _state]
-			,	paneLen
-			,	left
-			,	offset
-			,	CSS = {}
-			;
-
-			if (spacing === 0) {
-				$R.hide();
-				return;
-			}
-			else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
-				$R.show(); // in case was previously hidden
-
-			// Resizer Bar is ALWAYS same width/height of pane it is attached to
-			if (dir === "horz") { // north/south
-				//paneLen = $P.outerWidth(); // s.outerWidth || 
-				paneLen = sC.innerWidth; // handle offscreen-panes
-				s.resizerLength = paneLen;
-				left = $.layout.cssNum($P, "left")
-				$R.css({
-					width:	cssW($R, paneLen) // account for borders & padding
-				,	height:	cssH($R, spacing) // ditto
-				,	left:	left > -9999 ? left : sC.inset.left // handle offscreen-panes
-				});
-			}
-			else { // east/west
-				paneLen = $P.outerHeight(); // s.outerHeight || 
-				s.resizerLength = paneLen;
-				$R.css({
-					height:	cssH($R, paneLen) // account for borders & padding
-				,	width:	cssW($R, spacing) // ditto
-				,	top:	sC.inset.top + getPaneSize("north", true) // TODO: what if no North pane?
-				//,	top:	$.layout.cssNum($Ps["center"], "top")
-				});
-			}
-
-			// remove hover classes
-			removeHover( o, $R );
-
-			if ($T) {
-				if (togLen === 0 || (s.isSliding && o.hideTogglerOnSlide)) {
-					$T.hide(); // always HIDE the toggler when 'sliding'
-					return;
-				}
-				else
-					$T.show(); // in case was previously hidden
-
-				if (!(togLen > 0) || togLen === "100%" || togLen > paneLen) {
-					togLen = paneLen;
-					offset = 0;
-				}
-				else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
-					if (isStr(togAlign)) {
-						switch (togAlign) {
-							case "top":
-							case "left":	offset = 0;
-											break;
-							case "bottom":
-							case "right":	offset = paneLen - togLen;
-											break;
-							case "middle":
-							case "center":
-							default:		offset = round((paneLen - togLen) / 2); // 'default' catches typos
-						}
-					}
-					else { // togAlign = number
-						var x = parseInt(togAlign, 10); //
-						if (togAlign >= 0) offset = x;
-						else offset = paneLen - togLen + x; // NOTE: x is negative!
-					}
-				}
-
-				if (dir === "horz") { // north/south
-					var width = cssW($T, togLen);
-					$T.css({
-						width:	width  // account for borders & padding
-					,	height:	cssH($T, spacing) // ditto
-					,	left:	offset // TODO: VERIFY that toggler  positions correctly for ALL values
-					,	top:	0
-					});
-					// CENTER the toggler content SPAN
-					$T.children(".content").each(function(){
-						$TC = $(this);
-						$TC.css("marginLeft", round((width-$TC.outerWidth())/2)); // could be negative
-					});
-				}
-				else { // east/west
-					var height = cssH($T, togLen);
-					$T.css({
-						height:	height // account for borders & padding
-					,	width:	cssW($T, spacing) // ditto
-					,	top:	offset // POSITION the toggler
-					,	left:	0
-					});
-					// CENTER the toggler content SPAN
-					$T.children(".content").each(function(){
-						$TC = $(this);
-						$TC.css("marginTop", round((height-$TC.outerHeight())/2)); // could be negative
-					});
-				}
-
-				// remove ALL hover classes
-				removeHover( 0, $T );
-			}
-
-			// DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
-			if (!state.initialized && (o.initHidden || s.isHidden)) {
-				$R.hide();
-				if ($T) $T.hide();
-			}
-		});
-	}
-
-
-	/**
-	* @param {(string|Object)}	evt_or_pane
-	*/
-,	enableClosable = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$T	= $Ts[pane]
-		,	o	= options[pane]
-		;
-		if (!$T) return;
-		o.closable = true;
-		$T	.bind("click."+ sID, function(evt){ evt.stopPropagation(); toggle(pane); })
-			.css("visibility", "visible")
-			.css("cursor", "pointer")
-			.attr("title", state[pane].isClosed ? o.tips.Open : o.tips.Close) // may be blank
-			.show();
-	}
-	/**
-	* @param {(string|Object)}	evt_or_pane
-	* @param {boolean=}			[hide=false]
-	*/
-,	disableClosable = function (evt_or_pane, hide) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$T	= $Ts[pane]
-		;
-		if (!$T) return;
-		options[pane].closable = false;
-		// is closable is disable, then pane MUST be open!
-		if (state[pane].isClosed) open(pane, false, true);
-		$T	.unbind("."+ sID)
-			.css("visibility", hide ? "hidden" : "visible") // instead of hide(), which creates logic issues
-			.css("cursor", "default")
-			.attr("title", "");
-	}
-
-
-	/**
-	* @param {(string|Object)}	evt_or_pane
-	*/
-,	enableSlidable = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$R	= $Rs[pane]
-		;
-		if (!$R || !$R.data('draggable')) return;
-		options[pane].slidable = true; 
-		if (state[pane].isClosed)
-			bindStartSlidingEvents(pane, true);
-	}
-	/**
-	* @param {(string|Object)}	evt_or_pane
-	*/
-,	disableSlidable = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$R	= $Rs[pane]
-		;
-		if (!$R) return;
-		options[pane].slidable = false; 
-		if (state[pane].isSliding)
-			close(pane, false, true);
-		else {
-			bindStartSlidingEvents(pane, false);
-			$R	.css("cursor", "default")
-				.attr("title", "");
-			removeHover(null, $R[0]); // in case currently hovered
-		}
-	}
-
-
-	/**
-	* @param {(string|Object)}	evt_or_pane
-	*/
-,	enableResizable = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$R	= $Rs[pane]
-		,	o	= options[pane]
-		;
-		if (!$R || !$R.data('draggable')) return;
-		o.resizable = true; 
-		$R.draggable("enable");
-		if (!state[pane].isClosed)
-			$R	.css("cursor", o.resizerCursor)
-			 	.attr("title", o.tips.Resize);
-	}
-	/**
-	* @param {(string|Object)}	evt_or_pane
-	*/
-,	disableResizable = function (evt_or_pane) {
-		if (!isInitialized()) return;
-		var	pane = evtPane.call(this, evt_or_pane)
-		,	$R	= $Rs[pane]
-		;
-		if (!$R || !$R.data('draggable')) return;
-		options[pane].resizable = false; 
-		$R	.draggable("disable")
-			.css("cursor", "default")
-			.attr("title", "");
-		removeHover(null, $R[0]); // in case currently hovered
-	}
-
-
-	/**
-	* Move a pane from source-side (eg, west) to target-side (eg, east)
-	* If pane exists on target-side, move that to source-side, ie, 'swap' the panes
-	*
-	* @param {(string|Object)}	evt_or_pane1	The pane/edge being swapped
-	* @param {string}			pane2			ditto
-	*/
-,	swapPanes = function (evt_or_pane1, pane2) {
-		if (!isInitialized()) return;
-		var pane1 = evtPane.call(this, evt_or_pane1);
-		// change state.edge NOW so callbacks can know where pane is headed...
-		state[pane1].edge = pane2;
-		state[pane2].edge = pane1;
-		// run these even if NOT state.initialized
-		if (false === _runCallbacks("onswap_start", pane1)
-		 ||	false === _runCallbacks("onswap_start", pane2)
-		) {
-			state[pane1].edge = pane1; // reset
-			state[pane2].edge = pane2;
-			return;
-		}
-
-		var
-			oPane1	= copy( pane1 )
-		,	oPane2	= copy( pane2 )
-		,	sizes	= {}
-		;
-		sizes[pane1] = oPane1 ? oPane1.state.size : 0;
-		sizes[pane2] = oPane2 ? oPane2.state.size : 0;
-
-		// clear pointers & state
-		$Ps[pane1] = false; 
-		$Ps[pane2] = false;
-		state[pane1] = {};
-		state[pane2] = {};
-		
-		// ALWAYS remove the resizer & toggler elements
-		if ($Ts[pane1]) $Ts[pane1].remove();
-		if ($Ts[pane2]) $Ts[pane2].remove();
-		if ($Rs[pane1]) $Rs[pane1].remove();
-		if ($Rs[pane2]) $Rs[pane2].remove();
-		$Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false;
-
-		// transfer element pointers and data to NEW Layout keys
-		move( oPane1, pane2 );
-		move( oPane2, pane1 );
-
-		// cleanup objects
-		oPane1 = oPane2 = sizes = null;
-
-		// make panes 'visible' again
-		if ($Ps[pane1]) $Ps[pane1].css(_c.visible);
-		if ($Ps[pane2]) $Ps[pane2].css(_c.visible);
-
-		// fix any size discrepancies caused by swap
-		resizeAll();
-
-		// run these even if NOT state.initialized
-		_runCallbacks("onswap_end", pane1);
-		_runCallbacks("onswap_end", pane2);
-
-		return;
-
-		function copy (n) { // n = pane
-			var
-				$P	= $Ps[n]
-			,	$C	= $Cs[n]
-			;
-			return !$P ? false : {
-				pane:		n
-			,	P:			$P ? $P[0] : false
-			,	C:			$C ? $C[0] : false
-			,	state:		$.extend(true, {}, state[n])
-			,	options:	$.extend(true, {}, options[n])
-			}
-		};
-
-		function move (oPane, pane) {
-			if (!oPane) return;
-			var
-				P		= oPane.P
-			,	C		= oPane.C
-			,	oldPane = oPane.pane
-			,	c		= _c[pane]
-			//	save pane-options that should be retained
-			,	s		= $.extend(true, {}, state[pane])
-			,	o		= options[pane]
-			//	RETAIN side-specific FX Settings - more below
-			,	fx		= { resizerCursor: o.resizerCursor }
-			,	re, size, pos
-			;
-			$.each("fxName,fxSpeed,fxSettings".split(","), function (i, k) {
-				fx[k +"_open"]  = o[k +"_open"];
-				fx[k +"_close"] = o[k +"_close"];
-				fx[k +"_size"]  = o[k +"_size"];
-			});
-
-			// update object pointers and attributes
-			$Ps[pane] = $(P)
-				.data({
-					layoutPane:		Instance[pane]	// NEW pointer to pane-alias-object
-				,	layoutEdge:		pane
-				})
-				.css(_c.hidden)
-				.css(c.cssReq)
-			;
-			$Cs[pane] = C ? $(C) : false;
-
-			// set options and state
-			options[pane]	= $.extend(true, {}, oPane.options, fx);
-			state[pane]		= $.extend(true, {}, oPane.state);
-
-			// change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west
-			re = new RegExp(o.paneClass +"-"+ oldPane, "g");
-			P.className = P.className.replace(re, o.paneClass +"-"+ pane);
-
-			// ALWAYS regenerate the resizer & toggler elements
-			initHandles(pane); // create the required resizer & toggler
-
-			// if moving to different orientation, then keep 'target' pane size
-			if (c.dir != _c[oldPane].dir) {
-				size = sizes[pane] || 0;
-				setSizeLimits(pane); // update pane-state
-				size = max(size, state[pane].minSize);
-				// use manualSizePane to disable autoResize - not useful after panes are swapped
-				manualSizePane(pane, size, true, true); // true/true = skipCallback/noAnimation
-			}
-			else // move the resizer here
-				$Rs[pane].css(c.side, sC.inset[c.side] + (state[pane].isVisible ? getPaneSize(pane) : 0));
-
-
-			// ADD CLASSNAMES & SLIDE-BINDINGS
-			if (oPane.state.isVisible && !s.isVisible)
-				setAsOpen(pane, true); // true = skipCallback
-			else {
-				setAsClosed(pane);
-				bindStartSlidingEvents(pane, true); // will enable events IF option is set
-			}
-
-			// DESTROY the object
-			oPane = null;
-		};
-	}
-
-
-	/**
-	* INTERNAL method to sync pin-buttons when pane is opened or closed
-	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
-	*
-	* @see  open(), setAsOpen(), setAsClosed()
-	* @param {string}	pane   These are the params returned to callbacks by layout()
-	* @param {boolean}	doPin  True means set the pin 'down', False means 'up'
-	*/
-,	syncPinBtns = function (pane, doPin) {
-		if ($.layout.plugins.buttons)
-			$.each(state[pane].pins, function (i, selector) {
-				$.layout.buttons.setPinState(Instance, $(selector), pane, doPin);
-			});
-	}
-
-;	// END var DECLARATIONS
-
-	/**
-	* Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
-	*
-	* @see  document.keydown()
-	*/
-	function keyDown (evt) {
-		if (!evt) return true;
-		var code = evt.keyCode;
-		if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
-
-		var
-			PANE = {
-				38: "north" // Up Cursor	- $.ui.keyCode.UP
-			,	40: "south" // Down Cursor	- $.ui.keyCode.DOWN
-			,	37: "west"  // Left Cursor	- $.ui.keyCode.LEFT
-			,	39: "east"  // Right Cursor	- $.ui.keyCode.RIGHT
-			}
-		,	ALT		= evt.altKey // no worky!
-		,	SHIFT	= evt.shiftKey
-		,	CTRL	= evt.ctrlKey
-		,	CURSOR	= (CTRL && code >= 37 && code <= 40)
-		,	o, k, m, pane
-		;
-
-		if (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
-			pane = PANE[code];
-		else if (CTRL || SHIFT) // check to see if this matches a custom-hotkey
-			$.each(_c.borderPanes, function (i, p) { // loop each pane to check its hotkey
-				o = options[p];
-				k = o.customHotkey;
-				m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
-				if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
-					if (k && code === (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
-						pane = p;
-						return false; // BREAK
-					}
-				}
-			});
-
-		// validate pane
-		if (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden)
-			return true;
-
-		toggle(pane);
-
-		evt.stopPropagation();
-		evt.returnValue = false; // CANCEL key
-		return false;
-	};
-
-
-/*
- * ######################################
- *	UTILITY METHODS
- *	called externally or by initButtons
- * ######################################
- */
-
-	/**
-	* Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work
-	*
-	* @param {Object=}   [el]	(optional) Can also be 'bound' to a click, mouseOver, or other event
-	*/
-	function allowOverflow (el) {
-		if (!isInitialized()) return;
-		if (this && this.tagName) el = this; // BOUND to element
-		var $P;
-		if (isStr(el))
-			$P = $Ps[el];
-		else if ($(el).data("layoutRole"))
-			$P = $(el);
-		else
-			$(el).parents().each(function(){
-				if ($(this).data("layoutRole")) {
-					$P = $(this);
-					return false; // BREAK
-				}
-			});
-		if (!$P || !$P.length) return; // INVALID
-
-		var
-			pane	= $P.data("layoutEdge")
-		,	s		= state[pane]
-		;
-
-		// if pane is already raised, then reset it before doing it again!
-		// this would happen if allowOverflow is attached to BOTH the pane and an element 
-		if (s.cssSaved)
-			resetOverflow(pane); // reset previous CSS before continuing
-
-		// if pane is raised by sliding or resizing, or its closed, then abort
-		if (s.isSliding || s.isResizing || s.isClosed) {
-			s.cssSaved = false;
-			return;
-		}
-
-		var
-			newCSS	= { zIndex: (options.zIndexes.resizer_normal + 1) }
-		,	curCSS	= {}
-		,	of		= $P.css("overflow")
-		,	ofX		= $P.css("overflowX")
-		,	ofY		= $P.css("overflowY")
-		;
-		// determine which, if any, overflow settings need to be changed
-		if (of != "visible") {
-			curCSS.overflow = of;
-			newCSS.overflow = "visible";
-		}
-		if (ofX && !ofX.match(/(visible|auto)/)) {
-			curCSS.overflowX = ofX;
-			newCSS.overflowX = "visible";
-		}
-		if (ofY && !ofY.match(/(visible|auto)/)) {
-			curCSS.overflowY = ofX;
-			newCSS.overflowY = "visible";
-		}
-
-		// save the current overflow settings - even if blank!
-		s.cssSaved = curCSS;
-
-		// apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
-		$P.css( newCSS );
-
-		// make sure the zIndex of all other panes is normal
-		$.each(_c.allPanes, function(i, p) {
-			if (p != pane) resetOverflow(p);
-		});
-
-	};
-	/**
-	* @param {Object=}   [el]	(optional) Can also be 'bound' to a click, mouseOver, or other event
-	*/
-	function resetOverflow (el) {
-		if (!isInitialized()) return;
-		if (this && this.tagName) el = this; // BOUND to element
-		var $P;
-		if (isStr(el))
-			$P = $Ps[el];
-		else if ($(el).data("layoutRole"))
-			$P = $(el);
-		else
-			$(el).parents().each(function(){
-				if ($(this).data("layoutRole")) {
-					$P = $(this);
-					return false; // BREAK
-				}
-			});
-		if (!$P || !$P.length) return; // INVALID
-
-		var
-			pane	= $P.data("layoutEdge")
-		,	s		= state[pane]
-		,	CSS		= s.cssSaved || {}
-		;
-		// reset the zIndex
-		if (!s.isSliding && !s.isResizing)
-			$P.css("zIndex", options.zIndexes.pane_normal);
-
-		// reset Overflow - if necessary
-		$P.css( CSS );
-
-		// clear var
-		s.cssSaved = false;
-	};
-
-/*
- * #####################
- * CREATE/RETURN LAYOUT
- * #####################
- */
-
-	// validate that container exists
-	var $N = $(this).eq(0); // FIRST matching Container element
-	if (!$N.length) {
-		return _log( options.errors.containerMissing );
-	};
-
-	// Users retrieve Instance of a layout with: $N.layout() OR $N.data("layout")
-	// return the Instance-pointer if layout has already been initialized
-	if ($N.data("layoutContainer") && $N.data("layout"))
-		return $N.data("layout"); // cached pointer
-
-	// init global vars
-	var 
-		$Ps	= {}	// Panes x5		- set in initPanes()
-	,	$Cs	= {}	// Content x5	- set in initPanes()
-	,	$Rs	= {}	// Resizers x4	- set in initHandles()
-	,	$Ts	= {}	// Togglers x4	- set in initHandles()
-	,	$Ms	= $([])	// Masks - up to 2 masks per pane (IFRAME + DIV)
-	//	aliases for code brevity
-	,	sC	= state.container // alias for easy access to 'container dimensions'
-	,	sID	= state.id // alias for unique layout ID/namespace - eg: "layout435"
-	;
-
-	// create Instance object to expose data & option Properties, and primary action Methods
-	var Instance = {
-	//	layout data
-		options:			options			// property - options hash
-	,	state:				state			// property - dimensions hash
-	//	object pointers
-	,	container:			$N				// property - object pointers for layout container
-	,	panes:				$Ps				// property - object pointers for ALL Panes: panes.north, panes.center
-	,	contents:			$Cs				// property - object pointers for ALL Content: contents.north, contents.center
-	,	resizers:			$Rs				// property - object pointers for ALL Resizers, eg: resizers.north
-	,	togglers:			$Ts				// property - object pointers for ALL Togglers, eg: togglers.north
-	//	border-pane open/close
-	,	hide:				hide			// method - ditto
-	,	show:				show			// method - ditto
-	,	toggle:				toggle			// method - pass a 'pane' ("north", "west", etc)
-	,	open:				open			// method - ditto
-	,	close:				close			// method - ditto
-	,	slideOpen:			slideOpen		// method - ditto
-	,	slideClose:			slideClose		// method - ditto
-	,	slideToggle:		slideToggle		// method - ditto
-	//	pane actions
-	,	setSizeLimits:		setSizeLimits	// method - pass a 'pane' - update state min/max data
-	,	_sizePane:			sizePane		// method -intended for user by plugins only!
-	,	sizePane:			manualSizePane	// method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto'
-	,	sizeContent:		sizeContent		// method - pass a 'pane'
-	,	swapPanes:			swapPanes		// method - pass TWO 'panes' - will swap them
-	,	showMasks:			showMasks		// method - pass a 'pane' OR list of panes - default = all panes with mask option set
-	,	hideMasks:			hideMasks		// method - ditto'
-	//	pane element methods
-	,	initContent:		initContent		// method - ditto
-	,	addPane:			addPane			// method - pass a 'pane'
-	,	removePane:			removePane		// method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem
-	,	createChildren:		createChildren	// method - pass a 'pane' and (optional) layout-options (OVERRIDES options[pane].children
-	,	refreshChildren:	refreshChildren	// method - pass a 'pane' and a layout-instance
-	//	special pane option setting
-	,	enableClosable:		enableClosable	// method - pass a 'pane'
-	,	disableClosable:	disableClosable	// method - ditto
-	,	enableSlidable:		enableSlidable	// method - ditto
-	,	disableSlidable:	disableSlidable	// method - ditto
-	,	enableResizable:	enableResizable	// method - ditto
-	,	disableResizable:	disableResizable// method - ditto
-	//	utility methods for panes
-	,	allowOverflow:		allowOverflow	// utility - pass calling element (this)
-	,	resetOverflow:		resetOverflow	// utility - ditto
-	//	layout control
-	,	destroy:			destroy			// method - no parameters
-	,	initPanes:			isInitialized	// method - no parameters
-	,	resizeAll:			resizeAll		// method - no parameters
-	//	callback triggering
-	,	runCallbacks:		_runCallbacks	// method - pass evtName & pane (if a pane-event), eg: trigger("onopen", "west")
-	//	alias collections of options, state and children - created in addPane and extended elsewhere
-	,	hasParentLayout:	false			// set by initContainer()
-	,	children:			children		// pointers to child-layouts, eg: Instance.children.west.layoutName
-	,	north:				false			// alias group: { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], children: children[pane] }
-	,	south:				false			// ditto
-	,	west:				false			// ditto
-	,	east:				false			// ditto
-	,	center:				false			// ditto
-	};
-
-	// create the border layout NOW
-	if (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation
-		return null;
-	else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later
-		return Instance; // return the Instance object
-
-}
-
-
-})( jQuery );
-// END Layout - keep internal vars internal!
-
-
-
-// START Plugins - shared wrapper, no global vars
-(function ($) {
-
-
-/**
- * jquery.layout.state 1.0
- * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $
- *
- * Copyright (c) 2012 
- *   Kevin Dalman (http://allpro.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * @requires: UI Layout 1.3.0.rc30.1 or higher
- * @requires: $.ui.cookie (above)
- *
- * @see: http://groups.google.com/group/jquery-ui-layout
- */
-/*
- *	State-management options stored in options.stateManagement, which includes a .cookie hash
- *	Default options saves ALL KEYS for ALL PANES, ie: pane.size, pane.isClosed, pane.isHidden
- *
- *	// STATE/COOKIE OPTIONS
- *	@example $(el).layout({
-				stateManagement: {
-					enabled:	true
-				,	stateKeys:	"east.size,west.size,east.isClosed,west.isClosed"
-				,	cookie:		{ name: "appLayout", path: "/" }
-				}
-			})
- *	@example $(el).layout({ stateManagement__enabled: true }) // enable auto-state-management using cookies
- *	@example $(el).layout({ stateManagement__cookie: { name: "appLayout", path: "/" } })
- *	@example $(el).layout({ stateManagement__cookie__name: "appLayout", stateManagement__cookie__path: "/" })
- *
- *	// STATE/COOKIE METHODS
- *	@example myLayout.saveCookie( "west.isClosed,north.size,south.isHidden", {expires: 7} );
- *	@example myLayout.loadCookie();
- *	@example myLayout.deleteCookie();
- *	@example var JSON = myLayout.readState();	// CURRENT Layout State
- *	@example var JSON = myLayout.readCookie();	// SAVED Layout State (from cookie)
- *	@example var JSON = myLayout.state.stateData;	// LAST LOADED Layout State (cookie saved in layout.state hash)
- *
- *	CUSTOM STATE-MANAGEMENT (eg, saved in a database)
- *	@example var JSON = myLayout.readState( "west.isClosed,north.size,south.isHidden" );
- *	@example myLayout.loadState( JSON );
- */
-
-/**
- *	UI COOKIE UTILITY
- *
- *	A $.cookie OR $.ui.cookie namespace *should be standard*, but until then...
- *	This creates $.ui.cookie so Layout does not need the cookie.jquery.js plugin
- *	NOTE: This utility is REQUIRED by the layout.state plugin
- *
- *	Cookie methods in Layout are created as part of State Management 
- */
-if (!$.ui) $.ui = {};
-$.ui.cookie = {
-
-	// cookieEnabled is not in DOM specs, but DOES works in all browsers,including IE6
-	acceptsCookies: !!navigator.cookieEnabled
-
-,	read: function (name) {
-		var	c		= document.cookie
-		,	cs		= c ? c.split(';') : []
-		,	pair	// loop var
-		;
-		for (var i=0, n=cs.length; i < n; i++) {
-			pair = $.trim(cs[i]).split('='); // name=value pair
-			if (pair[0] == name) // found the layout cookie
-				return decodeURIComponent(pair[1]);
-		}
-		return null;
-	}
-
-,	write: function (name, val, cookieOpts) {
-		var	params	= ""
-		,	date	= ""
-		,	clear	= false
-		,	o		= cookieOpts || {}
-		,	x		= o.expires  || null
-		,	t		= $.type(x)
-		;
-		if (t === "date")
-			date = x;
-		else if (t === "string" && x > 0) {
-			x = parseInt(x,10);
-			t = "number";
-		}
-		if (t === "number") {
-			date = new Date();
-			if (x > 0)
-				date.setDate(date.getDate() + x);
-			else {
-				date.setFullYear(1970);
-				clear = true;
-			}
-		}
-		if (date)		params += ";expires="+ date.toUTCString();
-		if (o.path)		params += ";path="+ o.path;
-		if (o.domain)	params += ";domain="+ o.domain;
-		if (o.secure)	params += ";secure";
-		document.cookie = name +"="+ (clear ? "" : encodeURIComponent( val )) + params; // write or clear cookie
-	}
-
-,	clear: function (name) {
-		$.ui.cookie.write(name, "", {expires: -1});
-	}
-
-};
-// if cookie.jquery.js is not loaded, create an alias to replicate it
-// this may be useful to other plugins or code dependent on that plugin
-if (!$.cookie) $.cookie = function (k, v, o) {
-	var C = $.ui.cookie;
-	if (v === null)
-		C.clear(k);
-	else if (v === undefined)
-		return C.read(k);
-	else
-		C.write(k, v, o);
-};
-
-
-// tell Layout that the state plugin is available
-$.layout.plugins.stateManagement = true;
-
-//	Add State-Management options to layout.defaults
-$.layout.config.optionRootKeys.push("stateManagement");
-$.layout.defaults.stateManagement = {
-	enabled:		false	// true = enable state-management, even if not using cookies
-,	autoSave:		true	// Save a state-cookie when page exits?
-,	autoLoad:		true	// Load the state-cookie when Layout inits?
-,	animateLoad:	true	// animate panes when loading state into an active layout
-,	includeChildren: true	// recurse into child layouts to include their state as well
-	// List state-data to save - must be pane-specific
-,	stateKeys:	"north.size,south.size,east.size,west.size,"+
-				"north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+
-				"north.isHidden,south.isHidden,east.isHidden,west.isHidden"
-,	cookie: {
-		name:	""	// If not specified, will use Layout.name, else just "Layout"
-	,	domain:	""	// blank = current domain
-	,	path:	""	// blank = current page, "/" = entire website
-	,	expires: ""	// 'days' to keep cookie - leave blank for 'session cookie'
-	,	secure:	false
-	}
-};
-// Set stateManagement as a layout-option, NOT a pane-option
-$.layout.optionsMap.layout.push("stateManagement");
-
-/*
- *	State Management methods
- */
-$.layout.state = {
-
-	/**
-	 * Get the current layout state and save it to a cookie
-	 *
-	 * myLayout.saveCookie( keys, cookieOpts )
-	 *
-	 * @param {Object}			inst
-	 * @param {(string|Array)=}	keys
-	 * @param {Object=}			cookieOpts
-	 */
-	saveCookie: function (inst, keys, cookieOpts) {
-		var o	= inst.options
-		,	sm	= o.stateManagement
-		,	oC	= $.extend(true, {}, sm.cookie, cookieOpts || null)
-		,	data = inst.state.stateData = inst.readState( keys || sm.stateKeys ) // read current panes-state
-		;
-		$.ui.cookie.write( oC.name || o.name || "Layout", $.layout.state.encodeJSON(data), oC );
-		return $.extend(true, {}, data); // return COPY of state.stateData data
-	}
-
-	/**
-	 * Remove the state cookie
-	 *
-	 * @param {Object}	inst
-	 */
-,	deleteCookie: function (inst) {
-		var o = inst.options;
-		$.ui.cookie.clear( o.stateManagement.cookie.name || o.name || "Layout" );
-	}
-
-	/**
-	 * Read & return data from the cookie - as JSON
-	 *
-	 * @param {Object}	inst
-	 */
-,	readCookie: function (inst) {
-		var o = inst.options;
-		var c = $.ui.cookie.read( o.stateManagement.cookie.name || o.name || "Layout" );
-		// convert cookie string back to a hash and return it
-		return c ? $.layout.state.decodeJSON(c) : {};
-	}
-
-	/**
-	 * Get data from the cookie and USE IT to loadState
-	 *
-	 * @param {Object}	inst
-	 */
-,	loadCookie: function (inst) {
-		var c = $.layout.state.readCookie(inst); // READ the cookie
-		if (c) {
-			inst.state.stateData = $.extend(true, {}, c); // SET state.stateData
-			inst.loadState(c); // LOAD the retrieved state
-		}
-		return c;
-	}
-
-	/**
-	 * Update layout options from the cookie, if one exists
-	 *
-	 * @param {Object}		inst
-	 * @param {Object=}		stateData
-	 * @param {boolean=}	animate
-	 */
-,	loadState: function (inst, data, opts) {
-		if (!$.isPlainObject( data ) || $.isEmptyObject( data )) return;
-
-		// normalize data & cache in the state object
-		data = inst.state.stateData = $.layout.transformData( data ); // panes = default subkey
-
-		// add missing/default state-restore options
-		var smo = inst.options.stateManagement;
-		opts = $.extend({
-			animateLoad:		false //smo.animateLoad
-		,	includeChildren:	smo.includeChildren
-		}, opts );
-
-		if (!inst.state.initialized) {
-			/*
-			 *	layout NOT initialized, so just update its options
-			 */
-			// MUST remove pane.children keys before applying to options
-			// use a copy so we don't remove keys from original data
-			var o = $.extend(true, {}, data);
-			//delete o.center; // center has no state-data - only children
-			$.each($.layout.config.allPanes, function (idx, pane) {
-				if (o[pane]) delete o[pane].children;		   
-			 });
-			// update CURRENT layout-options with saved state data
-			$.extend(true, inst.options, o);
-		}
-		else {
-			/*
-			 *	layout already initialized, so modify layout's configuration
-			 */
-			var noAnimate = !opts.animateLoad
-			,	o, c, h, state, open
-			;
-			$.each($.layout.config.borderPanes, function (idx, pane) {
-				o = data[ pane ];
-				if (!$.isPlainObject( o )) return; // no key, skip pane
-
-				s	= o.size;
-				c	= o.initClosed;
-				h	= o.initHidden;
-				ar	= o.autoResize
-				state	= inst.state[pane];
-				open	= state.isVisible;
-
-				// reset autoResize
-				if (ar)
-					state.autoResize = ar;
-				// resize BEFORE opening
-				if (!open)
-					inst._sizePane(pane, s, false, false, false); // false=skipCallback/noAnimation/forceResize
-				// open/close as necessary - DO NOT CHANGE THIS ORDER!
-				if (h === true)			inst.hide(pane, noAnimate);
-				else if (c === true)	inst.close(pane, false, noAnimate);
-				else if (c === false)	inst.open (pane, false, noAnimate);
-				else if (h === false)	inst.show (pane, false, noAnimate);
-				// resize AFTER any other actions
-				if (open)
-					inst._sizePane(pane, s, false, false, noAnimate); // animate resize if option passed
-			});
-
-			/*
-			 *	RECURSE INTO CHILD-LAYOUTS
-			 */
-			if (opts.includeChildren) {
-				var paneStateChildren, childState;
-				$.each(inst.children, function (pane, paneChildren) {
-					paneStateChildren = data[pane] ? data[pane].children : 0;
-					if (paneStateChildren && paneChildren) {
-						$.each(paneChildren, function (stateKey, child) {
-							childState = paneStateChildren[stateKey];
-							if (child && childState)
-								child.loadState( childState );
-						});
-					}
-				});
-			}
-		}
-	}
-
-	/**
-	 * Get the *current layout state* and return it as a hash
-	 *
-	 * @param {Object=}		inst	// Layout instance to get state for
-	 * @param {object=}		[opts]	// State-Managements override options
-	 */
-,	readState: function (inst, opts) {
-		// backward compatility
-		if ($.type(opts) === 'string') opts = { keys: opts };
-		if (!opts) opts = {};
-		var	sm		= inst.options.stateManagement
-		,	ic		= opts.includeChildren
-		,	recurse	= ic !== undefined ? ic : sm.includeChildren
-		,	keys	= opts.stateKeys || sm.stateKeys
-		,	alt		= { isClosed: 'initClosed', isHidden: 'initHidden' }
-		,	state	= inst.state
-		,	panes	= $.layout.config.allPanes
-		,	data	= {}
-		,	pair, pane, key, val
-		,	ps, pC, child, array, count, branch
-		;
-		if ($.isArray(keys)) keys = keys.join(",");
-		// convert keys to an array and change delimiters from '__' to '.'
-		keys = keys.replace(/__/g, ".").split(',');
-		// loop keys and create a data hash
-		for (var i=0, n=keys.length; i < n; i++) {
-			pair = keys[i].split(".");
-			pane = pair[0];
-			key  = pair[1];
-			if ($.inArray(pane, panes) < 0) continue; // bad pane!
-			val = state[ pane ][ key ];
-			if (val == undefined) continue;
-			if (key=="isClosed" && state[pane]["isSliding"])
-				val = true; // if sliding, then *really* isClosed
-			( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val;
-		}
-
-		// recurse into the child-layouts for each pane
-		if (recurse) {
-			$.each(panes, function (idx, pane) {
-				pC = inst.children[pane];
-				ps = state.stateData[pane];
-				if ($.isPlainObject( pC ) && !$.isEmptyObject( pC )) {
-					// ensure a key exists for this 'pane', eg: branch = data.center
-					branch = data[pane] || (data[pane] = {});
-					if (!branch.children) branch.children = {};
-					$.each( pC, function (key, child) {
-						// ONLY read state from an initialize layout
-						if ( child.state.initialized )
-							branch.children[ key ] = $.layout.state.readState( child );
-						// if we have PREVIOUS (onLoad) state for this child-layout, KEEP IT!
-						else if ( ps && ps.children && ps.children[ key ] ) {
-							branch.children[ key ] = $.extend(true, {}, ps.children[ key ] );
-						}
-					});
-				}
-			});
-		}
-
-		return data;
-	}
-
-	/**
-	 *	Stringify a JSON hash so can save in a cookie or db-field
-	 */
-,	encodeJSON: function (JSON) {
-		return parse(JSON);
-		function parse (h) {
-			var D=[], i=0, k, v, t // k = key, v = value
-			,	a = $.isArray(h)
-			;
-			for (k in h) {
-				v = h[k];
-				t = typeof v;
-				if (t == 'string')		// STRING - add quotes
-					v = '"'+ v +'"';
-				else if (t == 'object')	// SUB-KEY - recurse into it
-					v = parse(v);
-				D[i++] = (!a ? '"'+ k +'":' : '') + v;
-			}
-			return (a ? '[' : '{') + D.join(',') + (a ? ']' : '}');
-		};
-	}
-
-	/**
-	 *	Convert stringified JSON back to a hash object
-	 *	@see		$.parseJSON(), adding in jQuery 1.4.1
-	 */
-,	decodeJSON: function (str) {
-		try { return $.parseJSON ? $.parseJSON(str) : window["eval"]("("+ str +")") || {}; }
-		catch (e) { return {}; }
-	}
-
-
-,	_create: function (inst) {
-		var _	= $.layout.state
-		,	o	= inst.options
-		,	sm	= o.stateManagement
-		;
-		//	ADD State-Management plugin methods to inst
-		 $.extend( inst, {
-		//	readCookie - update options from cookie - returns hash of cookie data
-			readCookie:		function () { return _.readCookie(inst); }
-		//	deleteCookie
-		,	deleteCookie:	function () { _.deleteCookie(inst); }
-		//	saveCookie - optionally pass keys-list and cookie-options (hash)
-		,	saveCookie:		function (keys, cookieOpts) { return _.saveCookie(inst, keys, cookieOpts); }
-		//	loadCookie - readCookie and use to loadState() - returns hash of cookie data
-		,	loadCookie:		function () { return _.loadCookie(inst); }
-		//	loadState - pass a hash of state to use to update options
-		,	loadState:		function (stateData, opts) { _.loadState(inst, stateData, opts); }
-		//	readState - returns hash of current layout-state
-		,	readState:		function (keys) { return _.readState(inst, keys); }
-		//	add JSON utility methods too...
-		,	encodeJSON:		_.encodeJSON
-		,	decodeJSON:		_.decodeJSON
-		});
-
-		// init state.stateData key, even if plugin is initially disabled
-		inst.state.stateData = {};
-
-		// autoLoad MUST BE one of: data-array, data-hash, callback-function, or TRUE
-		if ( !sm.autoLoad ) return;
-
-		//	When state-data exists in the autoLoad key USE IT,
-		//	even if stateManagement.enabled == false
-		if ($.isPlainObject( sm.autoLoad )) {
-			if (!$.isEmptyObject( sm.autoLoad )) {
-				inst.loadState( sm.autoLoad );
-			}
-		}
-		else if ( sm.enabled ) {
-			// update the options from cookie or callback
-			// if options is a function, call it to get stateData
-			if ($.isFunction( sm.autoLoad )) {
-				var d = {};
-				try {
-					d = sm.autoLoad( inst, inst.state, inst.options, inst.options.name || '' ); // try to get data from fn
-				} catch (e) {}
-				if (d && $.isPlainObject( d ) && !$.isEmptyObject( d ))
-					inst.loadState(d);
-			}
-			else // any other truthy value will trigger loadCookie
-				inst.loadCookie();
-		}
-	}
-
-,	_unload: function (inst) {
-		var sm = inst.options.stateManagement;
-		if (sm.enabled && sm.autoSave) {
-			// if options is a function, call it to save the stateData
-			if ($.isFunction( sm.autoSave )) {
-				try {
-					sm.autoSave( inst, inst.state, inst.options, inst.options.name || '' ); // try to get data from fn
-				} catch (e) {}
-			}
-			else // any truthy value will trigger saveCookie
-				inst.saveCookie();
-		}
-	}
-
-};
-
-// add state initialization method to Layout's onCreate array of functions
-$.layout.onCreate.push( $.layout.state._create );
-$.layout.onUnload.push( $.layout.state._unload );
-
-
-
-
-/**
- * jquery.layout.buttons 1.0
- * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $
- *
- * Copyright (c) 2012 
- *   Kevin Dalman (http://allpro.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * @requires: UI Layout 1.3.0.rc30.1 or higher
- *
- * @see: http://groups.google.com/group/jquery-ui-layout
- *
- * Docs: [ to come ]
- * Tips: [ to come ]
- */
-
-// tell Layout that the state plugin is available
-$.layout.plugins.buttons = true;
-
-//	Add buttons options to layout.defaults
-$.layout.defaults.autoBindCustomButtons = false;
-// Specify autoBindCustomButtons as a layout-option, NOT a pane-option
-$.layout.optionsMap.layout.push("autoBindCustomButtons");
-
-/*
- *	Button methods
- */
-$.layout.buttons = {
-
-	/**
-	* Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons
-	*
-	* @see  _create()
-	*
-	* @param  {Object}		inst	Layout Instance object
-	*/
-	init: function (inst) {
-		var pre		= "ui-layout-button-"
-		,	layout	= inst.options.name || ""
-		,	name;
-		$.each("toggle,open,close,pin,toggle-slide,open-slide".split(","), function (i, action) {
-			$.each($.layout.config.borderPanes, function (ii, pane) {
-				$("."+pre+action+"-"+pane).each(function(){
-					// if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name'
-					name = $(this).data("layoutName") || $(this).attr("layoutName");
-					if (name == undefined || name === layout)
-						inst.bindButton(this, action, pane);
-				});
-			});
-		});
-	}
-
-	/**
-	* Helper function to validate params received by addButton utilities
-	*
-	* Two classes are added to the element, based on the buttonClass...
-	* The type of button is appended to create the 2nd className:
-	*  - ui-layout-button-pin		// action btnClass
-	*  - ui-layout-button-pin-west	// action btnClass + pane
-	*  - ui-layout-button-toggle
-	*  - ui-layout-button-open
-	*  - ui-layout-button-close
-	*
-	* @param {Object}			inst		Layout Instance object
-	* @param {(string|!Object)}	selector	jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
-	* @param {string}   		pane 		Name of the pane the button is for: 'north', 'south', etc.
-	*
-	* @return {Array.<Object>}	If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null
-	*/
-,	get: function (inst, selector, pane, action) {
-		var $E	= $(selector)
-		,	o	= inst.options
-		,	err	= o.errors.addButtonError
-		;
-		if (!$E.length) { // element not found
-			$.layout.msg(err +" "+ o.errors.selector +": "+ selector, true);
-		}
-		else if ($.inArray(pane, $.layout.config.borderPanes) < 0) { // invalid 'pane' sepecified
-			$.layout.msg(err +" "+ o.errors.pane +": "+ pane, true);
-			$E = $("");  // NO BUTTON
-		}
-		else { // VALID
-			var btn = o[pane].buttonClass +"-"+ action;
-			$E	.addClass( btn +" "+ btn +"-"+ pane )
-				.data("layoutName", o.name); // add layout identifier - even if blank!
-		}
-		return $E;
-	}
-
-
-	/**
-	* NEW syntax for binding layout-buttons - will eventually replace addToggle, addOpen, etc.
-	*
-	* @param {Object}			inst		Layout Instance object
-	* @param {(string|!Object)}	selector	jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
-	* @param {string}			action
-	* @param {string}			pane
-	*/
-,	bind: function (inst, selector, action, pane) {
-		var _ = $.layout.buttons;
-		switch (action.toLowerCase()) {
-			case "toggle":			_.addToggle	(inst, selector, pane); break;	
-			case "open":			_.addOpen	(inst, selector, pane); break;
-			case "close":			_.addClose	(inst, selector, pane); break;
-			case "pin":				_.addPin	(inst, selector, pane); break;
-			case "toggle-slide":	_.addToggle	(inst, selector, pane, true); break;	
-			case "open-slide":		_.addOpen	(inst, selector, pane, true); break;
-		}
-		return inst;
-	}
-
-	/**
-	* Add a custom Toggler button for a pane
-	*
-	* @param {Object}			inst		Layout Instance object
-	* @param {(string|!Object)}	selector	jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
-	* @param {string}  			pane 		Name of the pane the button is for: 'north', 'south', etc.
-	* @param {boolean=}			slide 		true = slide-open, false = pin-open
-	*/
-,	addToggle: function (inst, selector, pane, slide) {
-		$.layout.buttons.get(inst, selector, pane, "toggle")
-			.click(function(evt){
-				inst.toggle(pane, !!slide);
-				evt.stopPropagation();
-			});
-		return inst;
-	}
-
-	/**
-	* Add a custom Open button for a pane
-	*
-	* @param {Object}			inst		Layout Instance object
-	* @param {(string|!Object)}	selector	jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
-	* @param {string}			pane 		Name of the pane the button is for: 'north', 'south', etc.
-	* @param {boolean=}			slide 		true = slide-open, false = pin-open
-	*/
-,	addOpen: function (inst, selector, pane, slide) {
-		$.layout.buttons.get(inst, selector, pane, "open")
-			.attr("title", inst.options[pane].tips.Open)
-			.click(function (evt) {
-				inst.open(pane, !!slide);
-				evt.stopPropagation();
-			});
-		return inst;
-	}
-
-	/**
-	* Add a custom Close button for a pane
-	*
-	* @param {Object}			inst		Layout Instance object
-	* @param {(string|!Object)}	selector	jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
-	* @param {string}   		pane 		Name of the pane the button is for: 'north', 'south', etc.
-	*/
-,	addClose: function (inst, selector, pane) {
-		$.layout.buttons.get(inst, selector, pane, "close")
-			.attr("title", inst.options[pane].tips.Close)
-			.click(function (evt) {
-				inst.close(pane);
-				evt.stopPropagation();
-			});
-		return inst;
-	}
-
-	/**
-	* Add a custom Pin button for a pane
-	*
-	* Four classes are added to the element, based on the paneClass for the associated pane...
-	* Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
-	*  - ui-layout-pane-pin
-	*  - ui-layout-pane-west-pin
-	*  - ui-layout-pane-pin-up
-	*  - ui-layout-pane-west-pin-up
-	*
-	* @param {Object}			inst		Layout Instance object
-	* @param {(string|!Object)}	selector	jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
-	* @param {string}   		pane 		Name of the pane the pin is for: 'north', 'south', etc.
-	*/
-,	addPin: function (inst, selector, pane) {
-		var	_	= $.layout.buttons
-		,	$E	= _.get(inst, selector, pane, "pin");
-		if ($E.length) {
-			var s = inst.state[pane];
-			$E.click(function (evt) {
-				_.setPinState(inst, $(this), pane, (s.isSliding || s.isClosed));
-				if (s.isSliding || s.isClosed) inst.open( pane ); // change from sliding to open
-				else inst.close( pane ); // slide-closed
-				evt.stopPropagation();
-			});
-			// add up/down pin attributes and classes
-			_.setPinState(inst, $E, pane, (!s.isClosed && !s.isSliding));
-			// add this pin to the pane data so we can 'sync it' automatically
-			// PANE.pins key is an array so we can store multiple pins for each pane
-			s.pins.push( selector ); // just save the selector string
-		}
-		return inst;
-	}
-
-	/**
-	* Change the class of the pin button to make it look 'up' or 'down'
-	*
-	* @see  addPin(), syncPins()
-	*
-	* @param {Object}			inst	Layout Instance object
-	* @param {Array.<Object>}	$Pin	The pin-span element in a jQuery wrapper
-	* @param {string}			pane	These are the params returned to callbacks by layout()
-	* @param {boolean}			doPin	true = set the pin 'down', false = set it 'up'
-	*/
-,	setPinState: function (inst, $Pin, pane, doPin) {
-		var updown = $Pin.attr("pin");
-		if (updown && doPin === (updown=="down")) return; // already in correct state
-		var
-			o		= inst.options[pane]
-		,	pin		= o.buttonClass +"-pin"
-		,	side	= pin +"-"+ pane
-		,	UP		= pin +"-up "+	side +"-up"
-		,	DN		= pin +"-down "+side +"-down"
-		;
-		$Pin
-			.attr("pin", doPin ? "down" : "up") // logic
-			.attr("title", doPin ? o.tips.Unpin : o.tips.Pin)
-			.removeClass( doPin ? UP : DN ) 
-			.addClass( doPin ? DN : UP ) 
-		;
-	}
-
-	/**
-	* INTERNAL function to sync 'pin buttons' when pane is opened or closed
-	* Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
-	*
-	* @see  open(), close()
-	*
-	* @param {Object}			inst	Layout Instance object
-	* @param {string}	pane	These are the params returned to callbacks by layout()
-	* @param {boolean}	doPin	True means set the pin 'down', False means 'up'
-	*/
-,	syncPinBtns: function (inst, pane, doPin) {
-		// REAL METHOD IS _INSIDE_ LAYOUT - THIS IS HERE JUST FOR REFERENCE
-		$.each(inst.state[pane].pins, function (i, selector) {
-			$.layout.buttons.setPinState(inst, $(selector), pane, doPin);
-		});
-	}
-
-
-,	_load: function (inst) {
-		var	_	= $.layout.buttons;
-		// ADD Button methods to Layout Instance
-		// Note: sel = jQuery Selector string
-		$.extend( inst, {
-			bindButton:		function (sel, action, pane) { return _.bind(inst, sel, action, pane); }
-		//	DEPRECATED METHODS
-		,	addToggleBtn:	function (sel, pane, slide) { return _.addToggle(inst, sel, pane, slide); }
-		,	addOpenBtn:		function (sel, pane, slide) { return _.addOpen(inst, sel, pane, slide); }
-		,	addCloseBtn:	function (sel, pane) { return _.addClose(inst, sel, pane); }
-		,	addPinBtn:		function (sel, pane) { return _.addPin(inst, sel, pane); }
-		});
-
-		// init state array to hold pin-buttons
-		for (var i=0; i<4; i++) {
-			var pane = $.layout.config.borderPanes[i];
-			inst.state[pane].pins = [];
-		}
-
-		// auto-init buttons onLoad if option is enabled
-		if ( inst.options.autoBindCustomButtons )
-			_.init(inst);
-	}
-
-,	_unload: function (inst) {
-		// TODO: unbind all buttons???
-	}
-
-};
-
-// add initialization method to Layout's onLoad array of functions
-$.layout.onLoad.push(  $.layout.buttons._load );
-//$.layout.onUnload.push( $.layout.buttons._unload );
-
-
-
-/**
- * jquery.layout.browserZoom 1.0
- * $Date: 2011-12-29 08:00:00 (Thu, 29 Dec 2011) $
- *
- * Copyright (c) 2012 
- *   Kevin Dalman (http://allpro.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * @requires: UI Layout 1.3.0.rc30.1 or higher
- *
- * @see: http://groups.google.com/group/jquery-ui-layout
- *
- * TODO: Extend logic to handle other problematic zooming in browsers
- * TODO: Add hotkey/mousewheel bindings to _instantly_ respond to these zoom event
- */
-
-// tell Layout that the plugin is available
-$.layout.plugins.browserZoom = true;
-
-$.layout.defaults.browserZoomCheckInterval = 1000;
-$.layout.optionsMap.layout.push("browserZoomCheckInterval");
-
-/*
- *	browserZoom methods
- */
-$.layout.browserZoom = {
-
-	_init: function (inst) {
-		// abort if browser does not need this check
-		if ($.layout.browserZoom.ratio() !== false)
-			$.layout.browserZoom._setTimer(inst);
-	}
-
-,	_setTimer: function (inst) {
-		// abort if layout destroyed or browser does not need this check
-		if (inst.destroyed) return;
-		var o	= inst.options
-		,	s	= inst.state
-		//	don't need check if inst has parentLayout, but check occassionally in case parent destroyed!
-		//	MINIMUM 100ms interval, for performance
-		,	ms	= inst.hasParentLayout ?  5000 : Math.max( o.browserZoomCheckInterval, 100 )
-		;
-		// set the timer
-		setTimeout(function(){
-			if (inst.destroyed || !o.resizeWithWindow) return;
-			var d = $.layout.browserZoom.ratio();
-			if (d !== s.browserZoom) {
-				s.browserZoom = d;
-				inst.resizeAll();
-			}
-			// set a NEW timeout
-			$.layout.browserZoom._setTimer(inst);
-		}
-		,	ms );
-	}
-
-,	ratio: function () {
-		var w	= window
-		,	s	= screen
-		,	d	= document
-		,	dE	= d.documentElement || d.body
-		,	b	= $.layout.browser
-		,	v	= b.version
-		,	r, sW, cW
-		;
-		// we can ignore all browsers that fire window.resize event onZoom
-		if ((b.msie && v > 8)
-		||	!b.msie
-		) return false; // don't need to track zoom
-
-		if (s.deviceXDPI && s.systemXDPI) // syntax compiler hack
-			return calc(s.deviceXDPI, s.systemXDPI);
-		// everything below is just for future reference!
-		if (b.webkit && (r = d.body.getBoundingClientRect))
-			return calc((r.left - r.right), d.body.offsetWidth);
-		if (b.webkit && (sW = w.outerWidth))
-			return calc(sW, w.innerWidth);
-		if ((sW = s.width) && (cW = dE.clientWidth))
-			return calc(sW, cW);
-		return false; // no match, so cannot - or don't need to - track zoom
-
-		function calc (x,y) { return (parseInt(x,10) / parseInt(y,10) * 100).toFixed(); }
-	}
-
-};
-// add initialization method to Layout's onLoad array of functions
-$.layout.onReady.push( $.layout.browserZoom._init );
-
-
-})( jQuery );
\ No newline at end of file
diff --git a/src/main/webapp/static/js/jquery/uilayout/jquery.layout-latest.min.js b/src/main/webapp/static/js/jquery/uilayout/jquery.layout-latest.min.js
deleted file mode 100644
index 452c9fc8c75b9253e81a57c5c7b4ed06c074003e..0000000000000000000000000000000000000000
--- a/src/main/webapp/static/js/jquery/uilayout/jquery.layout-latest.min.js
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-
- jquery.layout 1.3.0 - Release Candidate 30.79
- $Date: 2013-01-01 08:00:00 (Tue, 1 Jan 2013) $
- $Rev: 303007 $
-
- Copyright (c) 2012 
-   Fabrizio Balliano (http://www.fabrizioballiano.net)
-   Kevin Dalman (http://allpro.net)
-
- Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
-
- Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.79
-
- Docs: http://layout.jquery-dev.net/documentation.html
- Tips: http://layout.jquery-dev.net/tips.html
- Help: http://groups.google.com/group/jquery-ui-layout
-*/
-(function(b){var a=Math.min,d=Math.max,c=Math.floor,f=function(a){return"string"===b.type(a)},j=function(a,d){if(b.isArray(d))for(var c=0,j=d.length;c<j;c++){var h=d[c];try{f(h)&&(h=eval(h)),b.isFunction(h)&&h(a)}catch(k){}}};b.layout={version:"1.3.rc30.79",revision:0.033007,browser:{},effects:{slide:{all:{duration:"fast"},north:{direction:"up"},south:{direction:"down"},east:{direction:"right"},west:{direction:"left"}},drop:{all:{duration:"slow"},north:{direction:"up"},south:{direction:"down"},east:{direction:"right"},
-west:{direction:"left"}},scale:{all:{duration:"fast"}},blind:{},clip:{},explode:{},fade:{},fold:{},puff:{},size:{all:{easing:"swing"}}},config:{optionRootKeys:"effects panes north south west east center".split(" "),allPanes:["north","south","west","east","center"],borderPanes:["north","south","west","east"],oppositeEdge:{north:"south",south:"north",east:"west",west:"east"},offscreenCSS:{left:"-99999px",right:"auto"},offscreenReset:"offscreenReset",hidden:{visibility:"hidden"},visible:{visibility:"visible"},
-resizers:{cssReq:{position:"absolute",padding:0,margin:0,fontSize:"1px",textAlign:"left",overflow:"hidden"},cssDemo:{background:"#DDD",border:"none"}},togglers:{cssReq:{position:"absolute",display:"block",padding:0,margin:0,overflow:"hidden",textAlign:"center",fontSize:"1px",cursor:"pointer",zIndex:1},cssDemo:{background:"#AAA"}},content:{cssReq:{position:"relative"},cssDemo:{overflow:"auto",padding:"10px"},cssDemoPane:{overflow:"hidden",padding:0}},panes:{cssReq:{position:"absolute",margin:0},cssDemo:{padding:"10px",
-background:"#FFF",border:"1px solid #BBB",overflow:"auto"}},north:{side:"top",sizeType:"Height",dir:"horz",cssReq:{top:0,bottom:"auto",left:0,right:0,width:"auto"}},south:{side:"bottom",sizeType:"Height",dir:"horz",cssReq:{top:"auto",bottom:0,left:0,right:0,width:"auto"}},east:{side:"right",sizeType:"Width",dir:"vert",cssReq:{left:"auto",right:0,top:"auto",bottom:"auto",height:"auto"}},west:{side:"left",sizeType:"Width",dir:"vert",cssReq:{left:0,right:"auto",top:"auto",bottom:"auto",height:"auto"}},
-center:{dir:"center",cssReq:{left:"auto",right:"auto",top:"auto",bottom:"auto",height:"auto",width:"auto"}}},callbacks:{},getParentPaneElem:function(a){a=b(a);if(a=a.data("layout")||a.data("parentLayout")){a=a.container;if(a.data("layoutPane"))return a;a=a.closest("."+b.layout.defaults.panes.paneClass);if(a.data("layoutPane"))return a}return null},getParentPaneInstance:function(a){return(a=b.layout.getParentPaneElem(a))?a.data("layoutPane"):null},getParentLayoutInstance:function(a){return(a=b.layout.getParentPaneElem(a))?
-a.data("parentLayout"):null},getEventObject:function(b){return"object"===typeof b&&b.stopPropagation?b:null},parsePaneName:function(a){var d=b.layout.getEventObject(a);d&&(d.stopPropagation(),a=b(this).data("layoutEdge"));a&&!/^(west|east|north|south|center)$/.test(a)&&(b.layout.msg('LAYOUT ERROR - Invalid pane-name: "'+a+'"'),a="error");return a},plugins:{draggable:!!b.fn.draggable,effects:{core:!!b.effects,slide:b.effects&&(b.effects.slide||b.effects.effect&&b.effects.effect.slide)}},onCreate:[],
-onLoad:[],onReady:[],onDestroy:[],onUnload:[],afterOpen:[],afterClose:[],scrollbarWidth:function(){return window.scrollbarWidth||b.layout.getScrollbarSize("width")},scrollbarHeight:function(){return window.scrollbarHeight||b.layout.getScrollbarSize("height")},getScrollbarSize:function(a){var d=b('<div style="position: absolute; top: -10000px; left: -10000px; width: 100px; height: 100px; overflow: scroll;"></div>').appendTo("body"),c={width:d.css("width")-d[0].clientWidth,height:d.height()-d[0].clientHeight};
-d.remove();window.scrollbarWidth=c.width;window.scrollbarHeight=c.height;return a.match(/^(width|height)$/)?c[a]:c},showInvisibly:function(b,a){if(b&&b.length&&(a||"none"===b.css("display"))){var d=b[0].style,d={display:d.display||"",visibility:d.visibility||""};b.css({display:"block",visibility:"hidden"});return d}return{}},getElementDimensions:function(a,c){var f={css:{},inset:{}},j=f.css,h={bottom:0},k=b.layout.cssNum,p=a.offset(),O,R,D;f.offsetLeft=p.left;f.offsetTop=p.top;c||(c={});b.each(["Left",
-"Right","Top","Bottom"],function(d,k){O=j["border"+k]=b.layout.borderWidth(a,k);R=j["padding"+k]=b.layout.cssNum(a,"padding"+k);D=k.toLowerCase();f.inset[D]=0<=c[D]?c[D]:R;h[D]=f.inset[D]+O});j.width=a.width();j.height=a.height();j.top=k(a,"top",!0);j.bottom=k(a,"bottom",!0);j.left=k(a,"left",!0);j.right=k(a,"right",!0);f.outerWidth=a.outerWidth();f.outerHeight=a.outerHeight();f.innerWidth=d(0,f.outerWidth-h.left-h.right);f.innerHeight=d(0,f.outerHeight-h.top-h.bottom);f.layoutWidth=a.innerWidth();
-f.layoutHeight=a.innerHeight();return f},getElementStyles:function(b,a){var d={},c=b[0].style,f=a.split(","),k=["Top","Bottom","Left","Right"],j=["Color","Style","Width"],h,p,D,x,A,r;for(x=0;x<f.length;x++)if(h=f[x],h.match(/(border|padding|margin)$/))for(A=0;4>A;A++)if(p=k[A],"border"===h)for(r=0;3>r;r++)D=j[r],d[h+p+D]=c[h+p+D];else d[h+p]=c[h+p];else d[h]=c[h];return d},cssWidth:function(a,c){if(0>=c)return 0;var f=!b.layout.browser.boxModel?"border-box":b.support.boxSizing?a.css("boxSizing"):
-"content-box",j=b.layout.borderWidth,h=b.layout.cssNum,k=c;"border-box"!==f&&(k-=j(a,"Left")+j(a,"Right"));"content-box"===f&&(k-=h(a,"paddingLeft")+h(a,"paddingRight"));return d(0,k)},cssHeight:function(a,c){if(0>=c)return 0;var f=!b.layout.browser.boxModel?"border-box":b.support.boxSizing?a.css("boxSizing"):"content-box",j=b.layout.borderWidth,h=b.layout.cssNum,k=c;"border-box"!==f&&(k-=j(a,"Top")+j(a,"Bottom"));"content-box"===f&&(k-=h(a,"paddingTop")+h(a,"paddingBottom"));return d(0,k)},cssNum:function(a,
-d,c){a.jquery||(a=b(a));var f=b.layout.showInvisibly(a);d=b.css(a[0],d,!0);c=c&&"auto"==d?d:Math.round(parseFloat(d)||0);a.css(f);return c},borderWidth:function(a,d){a.jquery&&(a=a[0]);var c="border"+d.substr(0,1).toUpperCase()+d.substr(1);return"none"===b.css(a,c+"Style",!0)?0:Math.round(parseFloat(b.css(a,c+"Width",!0))||0)},isMouseOverElem:function(a,d){var c=b(d||this),f=c.offset(),j=f.top,f=f.left,k=f+c.outerWidth(),c=j+c.outerHeight(),h=a.pageX,p=a.pageY;return b.layout.browser.msie&&0>h&&0>
-p||h>=f&&h<=k&&p>=j&&p<=c},msg:function(a,d,c,f){b.isPlainObject(a)&&window.debugData?("string"===typeof d?(f=c,c=d):"object"===typeof c&&(f=c,c=null),c=c||"log( <object> )",f=b.extend({sort:!1,returnHTML:!1,display:!1},f),!0===d||f.display?debugData(a,c,f):window.console&&console.log(debugData(a,c,f))):d?alert(a):window.console?console.log(a):(d=b("#layoutLogger"),d.length||(d=b('<div id="layoutLogger" style="position: '+(b.support.fixedPosition?"fixed":"absolute")+'; top: 5px; z-index: 999999; max-width: 25%; overflow: hidden; border: 1px solid #000; border-radius: 5px; background: #FBFBFB; box-shadow: 0 2px 10px rgba(0,0,0,0.3);"><div style="font-size: 13px; font-weight: bold; padding: 5px 10px; background: #F6F6F6; border-radius: 5px 5px 0 0; cursor: move;"><span style="float: right; padding-left: 7px; cursor: pointer;" title="Remove Console" onclick="$(this).closest(\'#layoutLogger\').remove()">X</span>Layout console.log</div><ul style="font-size: 13px; font-weight: none; list-style: none; margin: 0; padding: 0 0 2px;"></ul></div>').appendTo("body"),
-d.css("left",b(window).width()-d.outerWidth()-5),b.ui.draggable&&d.draggable({handle:":first-child"})),d.children("ul").append('<li style="padding: 4px 10px; margin: 0; border-top: 1px solid #CCC;">'+a.replace(/\</g,"&lt;").replace(/\>/g,"&gt;")+"</li>"))}};var h=navigator.userAgent.toLowerCase(),p=/(chrome)[ \/]([\w.]+)/.exec(h)||/(webkit)[ \/]([\w.]+)/.exec(h)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(h)||/(msie) ([\w.]+)/.exec(h)||0>h.indexOf("compatible")&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(h)||
-[],h=p[1]||"",p=p[2]||0,x="msie"===h;b.layout.browser={version:p,safari:"webkit"===h,webkit:"chrome"===h,msie:x,isIE6:x&&6==p,boxModel:!x||!1!==b.support.boxModel};h&&(b.layout.browser[h]=!0);x&&b(function(){b.layout.browser.boxModel=b.support.boxModel});b.layout.defaults={name:"",containerClass:"ui-layout-container",inset:null,scrollToBookmarkOnLoad:!0,resizeWithWindow:!0,resizeWithWindowDelay:200,resizeWithWindowMaxDelay:0,maskPanesEarly:!1,onresizeall_start:null,onresizeall_end:null,onload_start:null,
-onload_end:null,onunload_start:null,onunload_end:null,initPanes:!0,showErrorMessages:!0,showDebugMessages:!1,zIndex:null,zIndexes:{pane_normal:0,content_mask:1,resizer_normal:2,pane_sliding:100,pane_animate:1E3,resizer_drag:1E4},errors:{pane:"pane",selector:"selector",addButtonError:"Error Adding Button\nInvalid ",containerMissing:"UI Layout Initialization Error\nThe specified layout-container does not exist.",centerPaneMissing:"UI Layout Initialization Error\nThe center-pane element does not exist.\nThe center-pane is a required element.",
-noContainerHeight:"UI Layout Initialization Warning\nThe layout-container \"CONTAINER\" has no height.\nTherefore the layout is 0-height and hence 'invisible'!",callbackError:"UI Layout Callback Error\nThe EVENT callback is not a valid function."},panes:{applyDemoStyles:!1,closable:!0,resizable:!0,slidable:!0,initClosed:!1,initHidden:!1,contentSelector:".ui-layout-content",contentIgnoreSelector:".ui-layout-ignore",findNestedContent:!1,paneClass:"ui-layout-pane",resizerClass:"ui-layout-resizer",togglerClass:"ui-layout-toggler",
-buttonClass:"ui-layout-button",minSize:0,maxSize:0,spacing_open:6,spacing_closed:6,togglerLength_open:50,togglerLength_closed:50,togglerAlign_open:"center",togglerAlign_closed:"center",togglerContent_open:"",togglerContent_closed:"",resizerDblClickToggle:!0,autoResize:!0,autoReopen:!0,resizerDragOpacity:1,maskContents:!1,maskObjects:!1,maskZindex:null,resizingGrid:!1,livePaneResizing:!1,liveContentResizing:!1,liveResizingTolerance:1,sliderCursor:"pointer",slideTrigger_open:"click",slideTrigger_close:"mouseleave",
-slideDelay_open:300,slideDelay_close:300,hideTogglerOnSlide:!1,preventQuickSlideClose:b.layout.browser.webkit,preventPrematureSlideClose:!1,tips:{Open:"Open",Close:"Close",Resize:"Resize",Slide:"Slide Open",Pin:"Pin",Unpin:"Un-Pin",noRoomToOpen:"Not enough room to show this panel.",minSizeWarning:"Panel has reached its minimum size",maxSizeWarning:"Panel has reached its maximum size"},showOverflowOnHover:!1,enableCursorHotkey:!0,customHotkeyModifier:"SHIFT",fxName:"slide",fxSpeed:null,fxSettings:{},
-fxOpacityFix:!0,animatePaneSizing:!1,children:null,containerSelector:"",initChildren:!0,destroyChildren:!0,resizeChildren:!0,triggerEventsOnLoad:!1,triggerEventsDuringLiveResize:!0,onshow_start:null,onshow_end:null,onhide_start:null,onhide_end:null,onopen_start:null,onopen_end:null,onclose_start:null,onclose_end:null,onresize_start:null,onresize_end:null,onsizecontent_start:null,onsizecontent_end:null,onswap_start:null,onswap_end:null,ondrag_start:null,ondrag_end:null},north:{paneSelector:".ui-layout-north",
-size:"auto",resizerCursor:"n-resize",customHotkey:""},south:{paneSelector:".ui-layout-south",size:"auto",resizerCursor:"s-resize",customHotkey:""},east:{paneSelector:".ui-layout-east",size:200,resizerCursor:"e-resize",customHotkey:""},west:{paneSelector:".ui-layout-west",size:200,resizerCursor:"w-resize",customHotkey:""},center:{paneSelector:".ui-layout-center",minWidth:0,minHeight:0}};b.layout.optionsMap={layout:"name instanceKey stateManagement effects inset zIndexes errors zIndex scrollToBookmarkOnLoad showErrorMessages maskPanesEarly outset resizeWithWindow resizeWithWindowDelay resizeWithWindowMaxDelay onresizeall onresizeall_start onresizeall_end onload onload_start onload_end onunload onunload_start onunload_end".split(" "),
-center:"paneClass contentSelector contentIgnoreSelector findNestedContent applyDemoStyles triggerEventsOnLoad showOverflowOnHover maskContents maskObjects liveContentResizing containerSelector children initChildren resizeChildren destroyChildren onresize onresize_start onresize_end onsizecontent onsizecontent_start onsizecontent_end".split(" "),noDefault:["paneSelector","resizerCursor","customHotkey"]};b.layout.transformData=function(a,d){var c=d?{panes:{},center:{}}:{},f,j,k,h,p,x,D;if("object"!==
-typeof a)return c;for(j in a){f=c;p=a[j];k=j.split("__");D=k.length-1;for(x=0;x<=D;x++)h=k[x],x===D?f[h]=b.isPlainObject(p)?b.layout.transformData(p):p:(f[h]||(f[h]={}),f=f[h])}return c};b.layout.backwardCompatibility={map:{applyDefaultStyles:"applyDemoStyles",childOptions:"children",initChildLayout:"initChildren",destroyChildLayout:"destroyChildren",resizeChildLayout:"resizeChildren",resizeNestedLayout:"resizeChildren",resizeWhileDragging:"livePaneResizing",resizeContentWhileDragging:"liveContentResizing",
-triggerEventsWhileDragging:"triggerEventsDuringLiveResize",maskIframesOnResize:"maskContents",useStateCookie:"stateManagement.enabled","cookie.autoLoad":"stateManagement.autoLoad","cookie.autoSave":"stateManagement.autoSave","cookie.keys":"stateManagement.stateKeys","cookie.name":"stateManagement.cookie.name","cookie.domain":"stateManagement.cookie.domain","cookie.path":"stateManagement.cookie.path","cookie.expires":"stateManagement.cookie.expires","cookie.secure":"stateManagement.cookie.secure",
-noRoomToOpenTip:"tips.noRoomToOpen",togglerTip_open:"tips.Close",togglerTip_closed:"tips.Open",resizerTip:"tips.Resize",sliderTip:"tips.Slide"},renameOptions:function(a){function d(b,c){for(var f=b.split("."),k=f.length-1,j={branch:a,key:f[k]},r=0,q;r<k;r++)q=f[r],j.branch=void 0==j.branch[q]?c?j.branch[q]={}:{}:j.branch[q];return j}var c=b.layout.backwardCompatibility.map,f,j,k,h;for(h in c)f=d(h),k=f.branch[f.key],void 0!==k&&(j=d(c[h],!0),j.branch[j.key]=k,delete f.branch[f.key])},renameAllOptions:function(a){var d=
-b.layout.backwardCompatibility.renameOptions;d(a);a.defaults&&("object"!==typeof a.panes&&(a.panes={}),b.extend(!0,a.panes,a.defaults),delete a.defaults);a.panes&&d(a.panes);b.each(b.layout.config.allPanes,function(b,c){a[c]&&d(a[c])});return a}};b.fn.layout=function(h){function p(e){if(!e)return!0;var w=e.keyCode;if(33>w)return!0;var m={38:"north",40:"south",37:"west",39:"east"},a=e.shiftKey,g=e.ctrlKey,t,n,d,c;g&&(37<=w&&40>=w)&&r[m[w]].enableCursorHotkey?c=m[w]:(g||a)&&b.each(k.borderPanes,function(e,
-b){t=r[b];n=t.customHotkey;d=t.customHotkeyModifier;if(a&&"SHIFT"==d||g&&"CTRL"==d||g&&a)if(n&&w===(isNaN(n)||9>=n?n.toUpperCase().charCodeAt(0):n))return c=b,!1});if(!c||!y[c]||!r[c].closable||q[c].isHidden)return!0;na(c);e.stopPropagation();return e.returnValue=!1}function x(e){if(H()){this&&this.tagName&&(e=this);var w;f(e)?w=y[e]:b(e).data("layoutRole")?w=b(e):b(e).parents().each(function(){if(b(this).data("layoutRole"))return w=b(this),!1});if(w&&w.length){var m=w.data("layoutEdge");e=q[m];e.cssSaved&&
-X(m);if(e.isSliding||e.isResizing||e.isClosed)e.cssSaved=!1;else{var a={zIndex:r.zIndexes.resizer_normal+1},g={},t=w.css("overflow"),n=w.css("overflowX"),d=w.css("overflowY");"visible"!=t&&(g.overflow=t,a.overflow="visible");n&&!n.match(/(visible|auto)/)&&(g.overflowX=n,a.overflowX="visible");d&&!d.match(/(visible|auto)/)&&(g.overflowY=n,a.overflowY="visible");e.cssSaved=g;w.css(a);b.each(k.allPanes,function(e,b){b!=m&&X(b)})}}}}function X(e){if(H()){this&&this.tagName&&(e=this);var w;f(e)?w=y[e]:
-b(e).data("layoutRole")?w=b(e):b(e).parents().each(function(){if(b(this).data("layoutRole"))return w=b(this),!1});if(w&&w.length){e=w.data("layoutEdge");e=q[e];var m=e.cssSaved||{};!e.isSliding&&!e.isResizing&&w.css("zIndex",r.zIndexes.pane_normal);w.css(m);e.cssSaved=!1}}}var G=b.layout.browser,k=b.layout.config,Q=b.layout.cssWidth,O=b.layout.cssHeight,R=b.layout.getElementDimensions,D=b.layout.getElementStyles,Ma=b.layout.getEventObject,A=b.layout.parsePaneName,r=b.extend(!0,{},b.layout.defaults);
-r.effects=b.extend(!0,{},b.layout.effects);var q={id:"layout"+b.now(),initialized:!1,paneResizing:!1,panesSliding:{},container:{innerWidth:0,innerHeight:0,outerWidth:0,outerHeight:0,layoutWidth:0,layoutHeight:0},north:{childIdx:0},south:{childIdx:0},east:{childIdx:0},west:{childIdx:0},center:{childIdx:0}},ba={north:null,south:null,east:null,west:null,center:null},M={data:{},set:function(e,b,m){M.clear(e);M.data[e]=setTimeout(b,m)},clear:function(e){var b=M.data;b[e]&&(clearTimeout(b[e]),delete b[e])}},
-ca=function(e,w,m){var a=r;(a.showErrorMessages&&!m||m&&a.showDebugMessages)&&b.layout.msg(a.name+" / "+e,!1!==w);return!1},C=function(e,w,m){var a=w&&f(w),g=a?q[w]:q,t=a?r[w]:r,n=r.name,d=e+(e.match(/_/)?"":"_end"),c=d.match(/_end$/)?d.substr(0,d.length-4):"",l=t[d]||t[c],h="NC",k=[];!a&&"boolean"===b.type(w)&&(m=w,w="");if(l)try{f(l)&&(l.match(/,/)?(k=l.split(","),l=eval(k[0])):l=eval(l)),b.isFunction(l)&&(h=k.length?l(k[1]):a?l(w,y[w],g,t,n):l(z,g,t,n))}catch(j){ca(r.errors.callbackError.replace(/EVENT/,
-b.trim((w||"")+" "+d)),!1),"string"===b.type(j)&&string.length&&ca("Exception:  "+j,!1)}!m&&!1!==h&&(a?(m=y[w],t=r[w],g=q[w],m.triggerHandler("layoutpane"+d,[w,m,g,t,n]),c&&m.triggerHandler("layoutpane"+c,[w,m,g,t,n])):(u.triggerHandler("layout"+d,[z,g,t,n]),c&&u.triggerHandler("layout"+c,[z,g,t,n])));a&&"onresize_end"===e&&db(w+"",!0);return h},eb=function(e){if(!G.mozilla){var b=y[e];"IFRAME"===q[e].tagName?b.css(k.hidden).css(k.visible):b.find("IFRAME").css(k.hidden).css(k.visible)}},ya=function(e){var b=
-y[e];e=k[e].dir;b={minWidth:1001-Q(b,1E3),minHeight:1001-O(b,1E3)};"horz"===e&&(b.minSize=b.minHeight);"vert"===e&&(b.minSize=b.minWidth);return b},fa=function(e,w,m){m||(m=k[e].dir);f(w)&&w.match(/%/)&&(w="100%"===w?-1:parseInt(w,10)/100);if(0===w)return 0;if(1<=w)return parseInt(w,10);var a=r,g=0;"horz"==m?g=v.innerHeight-(y.north?a.north.spacing_open:0)-(y.south?a.south.spacing_open:0):"vert"==m&&(g=v.innerWidth-(y.west?a.west.spacing_open:0)-(y.east?a.east.spacing_open:0));if(-1===w)return g;
-if(0<w)return c(g*w);if("center"==e)return 0;m="horz"===m?"height":"width";a=y[e];e="height"===m?U[e]:!1;var g=b.layout.showInvisibly(a),t=a.css(m),n=e?e.css(m):0;a.css(m,"auto");e&&e.css(m,"auto");w="height"===m?a.outerHeight():a.outerWidth();a.css(m,t).css(g);e&&e.css(m,n);return w},ga=function(e,b){var a=y[e],E=r[e],g=q[e],t=b?E.spacing_open:0,E=b?E.spacing_closed:0;return!a||g.isHidden?0:g.isClosed||g.isSliding&&b?E:"horz"===k[e].dir?a.outerHeight()+t:a.outerWidth()+t},Y=function(e,b){if(H()){var m=
-r[e],E=q[e],g=k[e],t=g.dir;g.sizeType.toLowerCase();var g=void 0!=b?b:E.isSliding,n=m.spacing_open,c=k.oppositeEdge[e],f=q[c],l=y[c],h=!l||!1===f.isVisible||f.isSliding?0:"horz"==t?l.outerHeight():l.outerWidth(),c=(!l||f.isHidden?0:r[c][!1!==f.isClosed?"spacing_closed":"spacing_open"])||0,f="horz"==t?v.innerHeight:v.innerWidth,l=ya("center"),l="horz"==t?d(r.center.minHeight,l.minHeight):d(r.center.minWidth,l.minWidth),g=f-n-(g?0:fa("center",l,t)+h+c),t=E.minSize=d(fa(e,m.minSize),ya(e).minSize),g=
-E.maxSize=a(m.maxSize?fa(e,m.maxSize):1E5,g),E=E.resizerPosition={},n=v.inset.top,h=v.inset.left,c=v.innerWidth,f=v.innerHeight,m=m.spacing_open;switch(e){case "north":E.min=n+t;E.max=n+g;break;case "west":E.min=h+t;E.max=h+g;break;case "south":E.min=n+f-g-m;E.max=n+f-t-m;break;case "east":E.min=h+c-g-m,E.max=h+c-t-m}}},Na=function(e,a){var m=b(e),E=m.data("layoutRole"),g=m.data("layoutEdge"),t=r[g][E+"Class"],g="-"+g,n=m.hasClass(t+"-closed")?"-closed":"-open",d="-closed"===n?"-open":"-closed",n=
-t+"-hover "+(t+g+"-hover ")+(t+n+"-hover ")+(t+g+n+"-hover ");a&&(n+=t+d+"-hover "+(t+g+d+"-hover "));"resizer"==E&&m.hasClass(t+"-sliding")&&(n+=t+"-sliding-hover "+(t+g+"-sliding-hover "));return b.trim(n)},Oa=function(e,a){var m=b(a||this);e&&"toggler"===m.data("layoutRole")&&e.stopPropagation();m.addClass(Na(m))},da=function(e,a){var m=b(a||this);m.removeClass(Na(m,!0))},fb=function(){var e=b(this).data("layoutEdge"),a=q[e];!a.isClosed&&(!a.isResizing&&!q.paneResizing)&&(b.fn.disableSelection&&
-b("body").disableSelection(),r.maskPanesEarly&&va(e,{resizing:!0}))},gb=function(e,a){var m=a||this,E=b(m).data("layoutEdge"),g=E+"ResizerLeave";M.clear(E+"_openSlider");M.clear(g);a?q.paneResizing||(b.fn.enableSelection&&b("body").enableSelection(),r.maskPanesEarly&&za()):M.set(g,function(){gb(e,m)},200)},H=function(){return q.initialized||q.creatingLayout?!0:Aa()},Aa=function(e){var a=r;if(!u.is(":visible"))return!e&&(G.webkit&&"BODY"===u[0].tagName)&&setTimeout(function(){Aa(!0)},50),!1;if(!hb("center").length)return ca(a.errors.centerPaneMissing);
-q.creatingLayout=!0;b.extend(v,R(u,a.inset));A(void 0);b.each(k.allPanes,function(e,b){ib(b,!0)});Pa();b.each(k.borderPanes,function(e,b){y[b]&&q[b].isVisible&&(Y(b),ha(b))});ia("center");b.each(k.allPanes,function(e,b){jb(b)});a.scrollToBookmarkOnLoad&&(e=self.location,e.hash&&e.replace(e.hash));z.hasParentLayout?a.resizeWithWindow=!1:a.resizeWithWindow&&b(window).bind("resize."+K,Ab);delete q.creatingLayout;q.initialized=!0;j(z,b.layout.onReady);C("onload_end");return!0},Qa=function(e,a){var m=
-A.call(this,e),d=y[m];if(d){var g=U[m],t=q[m],n=r[m],c=r.stateManagement||{},n=a?n.children=a:n.children;if(b.isPlainObject(n))n=[n];else if(!n||!b.isArray(n))return;b.each(n,function(e,a){b.isPlainObject(a)&&(a.containerSelector?d.find(a.containerSelector):g||d).each(function(){var e=b(this),g=e.data("layout");if(!g){kb({container:e,options:a},t);if(c.includeChildren&&q.stateData[m]){var g=(q.stateData[m].children||{})[a.instanceKey],w=a.stateManagement||(a.stateManagement={autoLoad:!0});!0===w.autoLoad&&
-g&&(w.autoSave=!1,w.includeChildren=!0,w.autoLoad=b.extend(!0,{},g))}(g=e.layout(a))&&Ba(m,g)}})})}},kb=function(e,b){var a=e.container,d=e.options,g=d.stateManagement,t=d.instanceKey||a.data("layoutInstanceKey");t||(t=(g&&g.cookie?g.cookie.name:"")||d.name);t=t?t.replace(/[^\w-]/gi,"_").replace(/_{2,}/g,"_"):"layout"+ ++b.childIdx;d.instanceKey=t;a.data("layoutInstanceKey",t);return t},Ba=function(e,a){var m=y[e],d=ba[e],g=q[e];b.isPlainObject(d)&&(b.each(d,function(e,b){b.destroyed&&delete d[e]}),
-b.isEmptyObject(d)&&(d=ba[e]=null));!a&&!d&&(a=m.data("layout"));a&&(a.hasParentLayout=!0,m=a.options,kb(a,g),d||(d=ba[e]={}),d[m.instanceKey]=a.container.data("layout"));z[e].children=ba[e];a||Qa(e)},Ab=function(){var e=r,b=Number(e.resizeWithWindowDelay);10>b&&(b=100);M.clear("winResize");M.set("winResize",function(){M.clear("winResize");M.clear("winResizeRepeater");var b=R(u,e.inset);(b.innerWidth!==v.innerWidth||b.innerHeight!==v.innerHeight)&&oa()},b);M.data.winResizeRepeater||lb()},lb=function(){var e=
-Number(r.resizeWithWindowMaxDelay);0<e&&M.set("winResizeRepeater",function(){lb();oa()},e)},mb=function(){C("onunload_start");j(z,b.layout.onUnload);C("onunload_end")},nb=function(e){e=e?e.split(","):k.borderPanes;b.each(e,function(e,a){var d=r[a];if(d.enableCursorHotkey||d.customHotkey)return b(document).bind("keydown."+K,p),!1})},hb=function(e){e=r[e].paneSelector;if("#"===e.substr(0,1))return u.find(e).eq(0);var b=u.children(e).eq(0);return b.length?b:u.children("form:first").children(e).eq(0)},
-ib=function(e,b){if(b||H()){var m=r[e],c=q[e],g=k[e],t=g.dir,n="center"===e,f={},h=y[e],l,j;h?Ra(e,!1,!0,!1):U[e]=!1;h=y[e]=hb(e);if(h.length){h.data("layoutCSS")||h.data("layoutCSS",D(h,"position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border"));z[e]={name:e,pane:y[e],content:U[e],options:r[e],state:q[e],children:ba[e]};h.data({parentLayout:z,layoutPane:z[e],layoutEdge:e,layoutRole:"pane"}).css(g.cssReq).css("zIndex",r.zIndexes.pane_normal).css(m.applyDemoStyles?
-g.cssDemo:{}).addClass(m.paneClass+" "+m.paneClass+"-"+e).bind("mouseenter."+K,Oa).bind("mouseleave."+K,da);g={hide:"",show:"",toggle:"",close:"",open:"",slideOpen:"",slideClose:"",slideToggle:"",size:"sizePane",sizePane:"sizePane",sizeContent:"",sizeHandles:"",enableClosable:"",disableClosable:"",enableSlideable:"",disableSlideable:"",enableResizable:"",disableResizable:"",swapPanes:"swapPanes",swap:"swapPanes",move:"swapPanes",removePane:"removePane",remove:"removePane",createChildren:"",resizeChildren:"",
-resizeAll:"resizeAll",resizeLayout:"resizeAll"};for(j in g)h.bind("layoutpane"+j.toLowerCase()+"."+K,z[g[j]||j]);Sa(e,!1);n||(l=c.size=fa(e,m.size),n=fa(e,m.minSize)||1,j=fa(e,m.maxSize)||1E5,0<l&&(l=d(a(l,j),n)),c.autoResize=m.autoResize,c.isClosed=!1,c.isSliding=!1,c.isResizing=!1,c.isHidden=!1,c.pins||(c.pins=[]));c.tagName=h[0].tagName;c.edge=e;c.noRoom=!1;c.isVisible=!0;ob(e);"horz"===t?f.height=O(h,l):"vert"===t&&(f.width=Q(h,l));h.css(f);"horz"!=t&&ia(e,!0);q.initialized&&(Pa(e),nb(e));m.initClosed&&
-m.closable&&!m.initHidden?ja(e,!0,!0):m.initHidden||m.initClosed?Ta(e):c.noRoom||h.css("display","block");h.css("visibility","visible");m.showOverflowOnHover&&h.hover(x,X);q.initialized&&jb(e)}else y[e]=!1}},jb=function(e){var b=y[e],a=q[e],d=r[e];b&&(b.data("layout")&&Ba(e,b.data("layout")),a.isVisible&&(q.initialized?oa():pa(e),d.triggerEventsOnLoad?C("onresize_end",e):db(e,!0)),d.initChildren&&d.children&&Qa(e))},ob=function(e){e=e?e.split(","):k.borderPanes;b.each(e,function(e,b){var a=y[b],g=
-F[b],d=q[b],c=k[b].side,f={};if(a){switch(b){case "north":f.top=v.inset.top;f.left=v.inset.left;f.right=v.inset.right;break;case "south":f.bottom=v.inset.bottom;f.left=v.inset.left;f.right=v.inset.right;break;case "west":f.left=v.inset.left;break;case "east":f.right=v.inset.right}a.css(f);g&&d.isClosed?g.css(c,v.inset[c]):g&&!d.isHidden&&g.css(c,v.inset[c]+ga(b))}})},Pa=function(e){e=e?e.split(","):k.borderPanes;b.each(e,function(e,a){var d=y[a];F[a]=!1;P[a]=!1;if(d){var g=r[a],d=q[a],c="#"===g.paneSelector.substr(0,
-1)?g.paneSelector.substr(1):"",n=g.resizerClass,f=g.togglerClass,h="-"+a,l=z[a],j=l.resizer=F[a]=b("<div></div>"),l=l.toggler=g.closable?P[a]=b("<div></div>"):!1;!d.isVisible&&g.slidable&&j.attr("title",g.tips.Slide).css("cursor",g.sliderCursor);j.attr("id",c?c+"-resizer":"").data({parentLayout:z,layoutPane:z[a],layoutEdge:a,layoutRole:"resizer"}).css(k.resizers.cssReq).css("zIndex",r.zIndexes.resizer_normal).css(g.applyDemoStyles?k.resizers.cssDemo:{}).addClass(n+" "+n+h).hover(Oa,da).hover(fb,gb).appendTo(u);
-g.resizerDblClickToggle&&j.bind("dblclick."+K,na);l&&(l.attr("id",c?c+"-toggler":"").data({parentLayout:z,layoutPane:z[a],layoutEdge:a,layoutRole:"toggler"}).css(k.togglers.cssReq).css(g.applyDemoStyles?k.togglers.cssDemo:{}).addClass(f+" "+f+h).hover(Oa,da).bind("mouseenter",fb).appendTo(j),g.togglerContent_open&&b("<span>"+g.togglerContent_open+"</span>").data({layoutEdge:a,layoutRole:"togglerContent"}).data("layoutRole","togglerContent").data("layoutEdge",a).addClass("content content-open").css("display",
-"none").appendTo(l),g.togglerContent_closed&&b("<span>"+g.togglerContent_closed+"</span>").data({layoutEdge:a,layoutRole:"togglerContent"}).addClass("content content-closed").css("display","none").appendTo(l),pb(a));var g=a,B=b.layout.plugins.draggable,g=g?g.split(","):k.borderPanes;b.each(g,function(e,a){var g=r[a];if(!B||!y[a]||!g.resizable)return g.resizable=!1,!0;var m=q[a],w=r.zIndexes,d=k[a],c="horz"==d.dir?"top":"left",t=F[a],n=g.resizerClass,f=0,l,h,E=n+"-drag",j=n+"-"+a+"-drag",J=n+"-dragging",
-zb=n+"-"+a+"-dragging",cb=n+"-dragging-limit",v=n+"-"+a+"-dragging-limit",x=!1;m.isClosed||t.attr("title",g.tips.Resize).css("cursor",g.resizerCursor);t.draggable({containment:u[0],axis:"horz"==d.dir?"y":"x",delay:0,distance:1,grid:g.resizingGrid,helper:"clone",opacity:g.resizerDragOpacity,addClasses:!1,zIndex:w.resizer_drag,start:function(e,w){g=r[a];m=q[a];h=g.livePaneResizing;if(!1===C("ondrag_start",a))return!1;m.isResizing=!0;q.paneResizing=a;M.clear(a+"_closeSlider");Y(a);l=m.resizerPosition;
-f=w.position[c];t.addClass(E+" "+j);x=!1;b("body").disableSelection();va(a,{resizing:!0})},drag:function(e,b){x||(b.helper.addClass(J+" "+zb).css({right:"auto",bottom:"auto"}).children().css("visibility","hidden"),x=!0,m.isSliding&&y[a].css("zIndex",w.pane_sliding));var d=0;b.position[c]<l.min?(b.position[c]=l.min,d=-1):b.position[c]>l.max&&(b.position[c]=l.max,d=1);d?(b.helper.addClass(cb+" "+v),window.defaultStatus=0<d&&a.match(/(north|west)/)||0>d&&a.match(/(south|east)/)?g.tips.maxSizeWarning:
-g.tips.minSizeWarning):(b.helper.removeClass(cb+" "+v),window.defaultStatus="");h&&Math.abs(b.position[c]-f)>=g.liveResizingTolerance&&(f=b.position[c],p(e,b,a))},stop:function(e,g){b("body").enableSelection();window.defaultStatus="";t.removeClass(E+" "+j);m.isResizing=!1;q.paneResizing=!1;p(e,g,a,!0)}})});var p=function(b,e,a,g){var m=e.position,w=k[a];b=r[a];e=q[a];var d;switch(a){case "north":d=m.top;break;case "west":d=m.left;break;case "south":d=v.layoutHeight-m.top-b.spacing_open;break;case "east":d=
-v.layoutWidth-m.left-b.spacing_open}d-=v.inset[w.side];g?(!1!==C("ondrag_end",a)&&Ca(a,d,!1,!0),za(!0),e.isSliding&&va(a,{resizing:!0})):Math.abs(d-e.size)<b.liveResizingTolerance||(Ca(a,d,!1,!0),ea.each(qb))};d.isVisible?Ua(a):(Da(a),ma(a,!0))}});qa()},Sa=function(b,a){if(H()){var m=r[b],d=m.contentSelector,g=z[b],c=y[b],n;d&&(n=g.content=U[b]=m.findNestedContent?c.find(d).eq(0):c.children(d).eq(0));n&&n.length?(n.data("layoutRole","content"),n.data("layoutCSS")||n.data("layoutCSS",D(n,"height")),
-n.css(k.content.cssReq),m.applyDemoStyles&&(n.css(k.content.cssDemo),c.css(k.content.cssDemoPane)),c.css("overflowX").match(/(scroll|auto)/)&&c.css("overflow","hidden"),q[b].content={},!1!==a&&pa(b)):g.content=U[b]=!1}},qb=function(){var e=b(this),a=e.data("layoutMask"),a=q[a];"IFRAME"==a.tagName&&a.isVisible&&e.css({top:a.offsetTop,left:a.offsetLeft,width:a.outerWidth,height:a.outerHeight})},va=function(e,a){var m=k[e],d=["center"],g=r.zIndexes,c=b.extend({objectsOnly:!1,animation:!1,resizing:!0,
-sliding:q[e].isSliding},a),n,f;c.resizing&&d.push(e);c.sliding&&d.push(k.oppositeEdge[e]);"horz"===m.dir&&(d.push("west"),d.push("east"));b.each(d,function(e,a){f=q[a];n=r[a];if(f.isVisible&&(n.maskObjects||!c.objectsOnly&&n.maskContents)){for(var m=b([]),d,w=0,h=ea.length;w<h;w++)d=ea.eq(w),d.data("layoutMask")===a&&(m=m.add(d));if(!m.length){m=y[a];d=q[a];var w=r[a],h=r.zIndexes,j=b([]),E,k,v,p,x;if(w.maskContents||w.maskObjects)for(x=0;x<(w.maskObjects?2:1);x++)E=w.maskObjects&&0==x,k=document.createElement(E?
-"iframe":"div"),v=b(k).data("layoutMask",a),k.className="ui-layout-mask ui-layout-mask-"+a,p=k.style,p.display="block",p.position="absolute",p.background="#FFF",E&&(k.frameborder=0,k.src="about:blank",p.opacity=0,p.filter="Alpha(Opacity='0')",p.border=0),"IFRAME"==d.tagName?(p.zIndex=h.pane_normal+1,u.append(k)):(v.addClass("ui-layout-mask-inside-pane"),p.zIndex=w.maskZindex||h.content_mask,p.top=0,p.left=0,p.width="100%",p.height="100%",m.append(k)),j=j.add(k),ea=ea.add(k);m=j}m.each(function(){qb.call(this);
-this.style.zIndex=f.isSliding?g.pane_sliding+1:g.pane_normal+1;this.style.display="block"})}})},za=function(a){if(a||!q.paneResizing)ea.hide();else if(!a&&!b.isEmptyObject(q.panesSliding)){a=ea.length-1;for(var d,m;0<=a;a--)m=ea.eq(a),d=m.data("layoutMask"),r[d].maskObjects||m.hide()}},Ra=function(a,d,m,c){if(H()){a=A.call(this,a);var g=y[a],t=U[a],n=F[a],f=P[a];g&&b.isEmptyObject(g.data())&&(g=!1);t&&b.isEmptyObject(t.data())&&(t=!1);n&&b.isEmptyObject(n.data())&&(n=!1);f&&b.isEmptyObject(f.data())&&
-(f=!1);g&&g.stop(!0,!0);var h=r[a],l=ba[a],j=b.isPlainObject(l)&&!b.isEmptyObject(l);c=void 0!==c?c:h.destroyChildren;j&&c&&(b.each(l,function(a,b){b.destroyed||b.destroy(!0);b.destroyed&&delete l[a]}),b.isEmptyObject(l)&&(l=ba[a]=null,j=!1));g&&d&&!j?g.remove():g&&g[0]&&(d=h.paneClass,c=d+"-"+a,d=[d,d+"-open",d+"-closed",d+"-sliding",c,c+"-open",c+"-closed",c+"-sliding"],b.merge(d,Na(g,!0)),g.removeClass(d.join(" ")).removeData("parentLayout").removeData("layoutPane").removeData("layoutRole").removeData("layoutEdge").removeData("autoHidden").unbind("."+
-K),j&&t?(t.width(t.width()),b.each(l,function(a,b){b.resizeAll()})):t&&t.css(t.data("layoutCSS")).removeData("layoutCSS").removeData("layoutRole"),g.data("layout")||g.css(g.data("layoutCSS")).removeData("layoutCSS"));f&&f.remove();n&&n.remove();z[a]=y[a]=U[a]=F[a]=P[a]=!1;m||oa()}},Ea=function(a){var b=y[a],d=b[0].style;r[a].useOffscreenClose?(b.data(k.offscreenReset)||b.data(k.offscreenReset,{left:d.left,right:d.right}),b.css(k.offscreenCSS)):b.hide().removeData(k.offscreenReset)},rb=function(a){var b=
-y[a];a=r[a];var d=k.offscreenCSS,c=b.data(k.offscreenReset),g=b[0].style;b.show().removeData(k.offscreenReset);a.useOffscreenClose&&c&&(g.left==d.left&&(g.left=c.left),g.right==d.right&&(g.right=c.right))},Ta=function(a,b){if(H()){var d=A.call(this,a),c=r[d],g=q[d],t=F[d];y[d]&&!g.isHidden&&!(q.initialized&&!1===C("onhide_start",d))&&(g.isSliding=!1,delete q.panesSliding[d],t&&t.hide(),!q.initialized||g.isClosed?(g.isClosed=!0,g.isHidden=!0,g.isVisible=!1,q.initialized||Ea(d),ia("horz"===k[d].dir?
-"":"center"),(q.initialized||c.triggerEventsOnLoad)&&C("onhide_end",d)):(g.isHiding=!0,ja(d,!1,b)))}},Fa=function(a,b,d,c){if(H()){a=A.call(this,a);var g=q[a];y[a]&&g.isHidden&&!1!==C("onshow_start",a)&&(g.isShowing=!0,g.isSliding=!1,delete q.panesSliding[a],!1===b?ja(a,!0):ra(a,!1,d,c))}},na=function(a,b){if(H()){var d=Ma(a),c=A.call(this,a),g=q[c];d&&d.stopImmediatePropagation();g.isHidden?Fa(c):g.isClosed?ra(c,!!b):ja(c)}},ja=function(a,b,d,c){function g(){l.isMoving=!1;ma(t,!0);var a=k.oppositeEdge[t];
-q[a].noRoom&&(Y(a),ha(a));if(!c&&(q.initialized||h.triggerEventsOnLoad))p||C("onclose_end",t),p&&C("onshow_end",t),v&&C("onhide_end",t)}var t=A.call(this,a);if(!q.initialized&&y[t]){a=t;var n=q[a];Ea(a);n.isClosed=!0;n.isVisible=!1;Da(a)}else if(H()){var f=y[t],h=r[t],l=q[t],j,p,v;u.queue(function(a){if(!f||!h.closable&&!l.isShowing&&!l.isHiding||!b&&l.isClosed&&!l.isShowing)return a();var e=!l.isShowing&&!1===C("onclose_start",t);p=l.isShowing;v=l.isHiding;delete l.isShowing;delete l.isHiding;if(e)return a();
-j=!d&&!l.isClosed&&"none"!=h.fxName_close;l.isMoving=!0;l.isClosed=!0;l.isVisible=!1;v?l.isHidden=!0:p&&(l.isHidden=!1);l.isSliding?wa(t,!1):ia("horz"===k[t].dir?"":"center",!1);Da(t);j?(Ga(t,!0),f.hide(h.fxName_close,h.fxSettings_close,h.fxSpeed_close,function(){Ga(t,!1);l.isClosed&&g();a()})):(Ea(t),g(),a())})}},Da=function(a){if(F[a]){var d=F[a],c=P[a],f=r[a],g=k[a].side,t=f.resizerClass,n=f.togglerClass,h="-"+a;d.css(g,v.inset[g]).removeClass(t+"-open "+t+h+"-open").removeClass(t+"-sliding "+
-t+h+"-sliding").addClass(t+"-closed "+t+h+"-closed");f.resizable&&b.layout.plugins.draggable&&d.draggable("disable").removeClass("ui-state-disabled").css("cursor","default").attr("title","");c&&(c.removeClass(n+"-open "+n+h+"-open").addClass(n+"-closed "+n+h+"-closed").attr("title",f.tips.Open),c.children(".content-open").hide(),c.children(".content-closed").css("display","block"));Va(a,!1);q.initialized&&qa()}},ra=function(a,b,d,c){function g(){j.isMoving=!1;eb(f);j.isSliding||ia("vert"==k[f].dir?
-"center":"",!1);Ua(f)}if(H()){var f=A.call(this,a),n=y[f],h=r[f],j=q[f],l,p;u.queue(function(a){if(!n||!h.resizable&&!h.closable&&!j.isShowing||j.isVisible&&!j.isSliding)return a();if(j.isHidden&&!j.isShowing)a(),Fa(f,!0);else{j.autoResize&&j.size!=h.size?ka(f,h.size,!0,!0,!0):Y(f,b);var e=C("onopen_start",f);if("abort"===e)return a();"NC"!==e&&Y(f,b);if(j.minSize>j.maxSize)return Va(f,!1),!c&&h.tips.noRoomToOpen&&alert(h.tips.noRoomToOpen),a();b?wa(f,!0):j.isSliding?wa(f,!1):h.slidable&&ma(f,!1);
-j.noRoom=!1;ha(f);p=j.isShowing;delete j.isShowing;l=!d&&j.isClosed&&"none"!=h.fxName_open;j.isMoving=!0;j.isVisible=!0;j.isClosed=!1;p&&(j.isHidden=!1);l?(Ga(f,!0),n.show(h.fxName_open,h.fxSettings_open,h.fxSpeed_open,function(){Ga(f,!1);j.isVisible&&g();a()})):(rb(f),g(),a())}})}},Ua=function(a,d){var c=y[a],f=F[a],g=P[a],h=r[a],n=q[a],j=k[a].side,p=h.resizerClass,l=h.togglerClass,u="-"+a;f.css(j,v.inset[j]+ga(a)).removeClass(p+"-closed "+p+u+"-closed").addClass(p+"-open "+p+u+"-open");n.isSliding?
-f.addClass(p+"-sliding "+p+u+"-sliding"):f.removeClass(p+"-sliding "+p+u+"-sliding");da(0,f);h.resizable&&b.layout.plugins.draggable?f.draggable("enable").css("cursor",h.resizerCursor).attr("title",h.tips.Resize):n.isSliding||f.css("cursor","default");g&&(g.removeClass(l+"-closed "+l+u+"-closed").addClass(l+"-open "+l+u+"-open").attr("title",h.tips.Close),da(0,g),g.children(".content-closed").hide(),g.children(".content-open").css("display","block"));Va(a,!n.isSliding);b.extend(n,R(c));q.initialized&&
-(qa(),pa(a,!0));if(!d&&(q.initialized||h.triggerEventsOnLoad)&&c.is(":visible"))C("onopen_end",a),n.isShowing&&C("onshow_end",a),q.initialized&&C("onresize_end",a)},sb=function(a){function b(){g.isClosed?g.isMoving||ra(c,!0):wa(c,!0)}if(H()){var d=Ma(a),c=A.call(this,a),g=q[c];a=r[c].slideDelay_open;d&&d.stopImmediatePropagation();g.isClosed&&d&&"mouseenter"===d.type&&0<a?M.set(c+"_openSlider",b,a):b()}},Wa=function(a){function c(){g.isClosed?wa(f,!1):g.isMoving||ja(f)}if(H()){var m=Ma(a),f=A.call(this,
-a);a=r[f];var g=q[f],h=g.isMoving?1E3:300;!g.isClosed&&!g.isResizing&&("click"===a.slideTrigger_close?c():a.preventQuickSlideClose&&g.isMoving||a.preventPrematureSlideClose&&m&&b.layout.isMouseOverElem(m,y[f])||(m?M.set(f+"_closeSlider",c,d(a.slideDelay_close,h)):c()))}},Ga=function(a,b){var d=y[a],c=q[a],g=r[a],f=r.zIndexes;b?(va(a,{animation:!0,objectsOnly:!0}),d.css({zIndex:f.pane_animate}),"south"==a?d.css({top:v.inset.top+v.innerHeight-d.outerHeight()}):"east"==a&&d.css({left:v.inset.left+v.innerWidth-
-d.outerWidth()})):(za(),d.css({zIndex:c.isSliding?f.pane_sliding:f.pane_normal}),"south"==a?d.css({top:"auto"}):"east"==a&&!d.css("left").match(/\-99999/)&&d.css({left:"auto"}),G.msie&&(g.fxOpacityFix&&"slide"!=g.fxName_open&&d.css("filter")&&1==d.css("opacity"))&&d[0].style.removeAttribute("filter"))},ma=function(a,b){var d=r[a],c=F[a],g=d.slideTrigger_open.toLowerCase();if(c&&(!b||d.slidable)){g.match(/mouseover/)?g=d.slideTrigger_open="mouseenter":g.match(/(click|dblclick|mouseenter)/)||(g=d.slideTrigger_open=
-"click");if(d.resizerDblClickToggle&&g.match(/click/))c[b?"unbind":"bind"]("dblclick."+K,na);c[b?"bind":"unbind"](g+"."+K,sb).css("cursor",b?d.sliderCursor:"default").attr("title",b?d.tips.Slide:"")}},wa=function(a,b){function d(b){M.clear(a+"_closeSlider");b.stopPropagation()}var c=r[a],g=q[a],f=r.zIndexes,h=c.slideTrigger_close.toLowerCase(),j=b?"bind":"unbind",k=y[a],l=F[a];M.clear(a+"_closeSlider");b?(g.isSliding=!0,q.panesSliding[a]=!0,ma(a,!1)):(g.isSliding=!1,delete q.panesSliding[a]);k.css("zIndex",
-b?f.pane_sliding:f.pane_normal);l.css("zIndex",b?f.pane_sliding+2:f.resizer_normal);h.match(/(click|mouseleave)/)||(h=c.slideTrigger_close="mouseleave");l[j](h,Wa);"mouseleave"===h&&(k[j]("mouseleave."+K,Wa),l[j]("mouseenter."+K,d),k[j]("mouseenter."+K,d));b?"click"===h&&!c.resizable&&(l.css("cursor",b?c.sliderCursor:"default"),l.attr("title",b?c.tips.Close:"")):M.clear(a+"_closeSlider")},ha=function(a,d,c,f){d=r[a];var g=q[a],h=k[a],n=y[a],j=F[a],p="vert"===h.dir,l=!1;if("center"===a||p&&g.noVerticalRoom)(l=
-0<=g.maxHeight)&&g.noRoom?(rb(a),j&&j.show(),g.isVisible=!0,g.noRoom=!1,p&&(g.noVerticalRoom=!1),eb(a)):!l&&!g.noRoom&&(Ea(a),j&&j.hide(),g.isVisible=!1,g.noRoom=!0);"center"!==a&&(g.minSize<=g.maxSize?(g.size>g.maxSize?ka(a,g.maxSize,c,!0,f):g.size<g.minSize?ka(a,g.minSize,c,!0,f):j&&(g.isVisible&&n.is(":visible"))&&(c=g.size+v.inset[h.side],b.layout.cssNum(j,h.side)!=c&&j.css(h.side,c)),g.noRoom&&(g.wasOpen&&d.closable?d.autoReopen?ra(a,!1,!0,!0):g.noRoom=!1:Fa(a,g.wasOpen,!0,!0))):g.noRoom||(g.noRoom=
-!0,g.wasOpen=!g.isClosed&&!g.isSliding,g.isClosed||(d.closable?ja(a,!0,!0):Ta(a,!0))))},Ca=function(a,b,d,c,g){if(H()){a=A.call(this,a);var f=r[a],h=q[a];g=g||f.livePaneResizing&&!h.isResizing;h.autoResize=!1;ka(a,b,d,c,g)}},ka=function(e,c,f,h,g){function j(){for(var a="width"===ua?l.outerWidth():l.outerHeight(),a=[{pane:n,count:1,target:c,actual:a,correct:c===a,attempt:c,cssSize:D}],e=a[0],h={},t="Inaccurate size after resizing the "+n+"-pane.";!e.correct;){h={pane:n,count:e.count+1,target:c};h.attempt=
-e.actual>c?d(0,e.attempt-(e.actual-c)):d(0,e.attempt+(c-e.actual));h.cssSize=("horz"==k[n].dir?O:Q)(y[n],h.attempt);l.css(ua,h.cssSize);h.actual="width"==ua?l.outerWidth():l.outerHeight();h.correct=c===h.actual;1===a.length&&(ca(t,!1,!0),ca(e,!1,!0));ca(h,!1,!0);if(3<a.length)break;a.push(h);e=a[a.length-1]}J.size=c;b.extend(J,R(l));J.isVisible&&l.is(":visible")&&(x&&x.css(B,c+v.inset[B]),pa(n));!f&&(!Z&&q.initialized&&J.isVisible)&&C("onresize_end",n);f||(J.isSliding||ia("horz"==k[n].dir?"":"center",
-Z,g),qa());e=k.oppositeEdge[n];c<G&&q[e].noRoom&&(Y(e),ha(e,!1,f));1<a.length&&ca(t+"\nSee the Error Console for details.",!0,!0)}if(H()){var n=A.call(this,e),p=r[n],J=q[n],l=y[n],x=F[n],B=k[n].side,ua=k[n].sizeType.toLowerCase(),Z=J.isResizing&&!p.triggerEventsDuringLiveResize,z=!0!==h&&p.animatePaneSizing,G,D;u.queue(function(e){Y(n);G=J.size;c=fa(n,c);c=d(c,fa(n,p.minSize));c=a(c,J.maxSize);if(c<J.minSize)e(),ha(n,!1,f);else{if(!g&&c===G)return e();J.newSize=c;!f&&(q.initialized&&J.isVisible)&&
-C("onresize_start",n);D=("horz"==k[n].dir?O:Q)(y[n],c);if(z&&l.is(":visible")){var h=b.layout.effects.size[n]||b.layout.effects.size.all,h=p.fxSettings_size.easing||h.easing,v=r.zIndexes,u={};u[ua]=D+"px";J.isMoving=!0;l.css({zIndex:v.pane_animate}).show().animate(u,p.fxSpeed_size,h,function(){l.css({zIndex:J.isSliding?v.pane_sliding:v.pane_normal});J.isMoving=!1;delete J.newSize;j();e()})}else l.css(ua,D),delete J.newSize,l.is(":visible")?j():(J.size=c,b.extend(J,R(l))),e()}})}},ia=function(a,c,
-f){a=(a?a:"east,west,center").split(",");b.each(a,function(a,e){if(y[e]){var h=r[e],j=q[e],k=y[e],p=!0,l={},u=b.layout.showInvisibly(k),B={top:ga("north",!0),bottom:ga("south",!0),left:ga("west",!0),right:ga("east",!0),width:0,height:0};B.width=v.innerWidth-B.left-B.right;B.height=v.innerHeight-B.bottom-B.top;B.top+=v.inset.top;B.bottom+=v.inset.bottom;B.left+=v.inset.left;B.right+=v.inset.right;b.extend(j,R(k));if("center"===e){if(!f&&j.isVisible&&B.width===j.outerWidth&&B.height===j.outerHeight)return k.css(u),
-!0;b.extend(j,ya(e),{maxWidth:B.width,maxHeight:B.height});l=B;j.newWidth=l.width;j.newHeight=l.height;l.width=Q(k,l.width);l.height=O(k,l.height);p=0<=l.width&&0<=l.height;if(!q.initialized&&h.minWidth>B.width){var h=h.minWidth-j.outerWidth,B=r.east.minSize||0,x=r.west.minSize||0,Z=q.east.size,z=q.west.size,A=Z,D=z;0<h&&(q.east.isVisible&&Z>B)&&(A=d(Z-B,Z-h),h-=Z-A);0<h&&(q.west.isVisible&&z>x)&&(D=d(z-x,z-h),h-=z-D);if(0===h){Z&&Z!=B&&ka("east",A,!0,!0,f);z&&z!=x&&ka("west",D,!0,!0,f);ia("center",
-c,f);k.css(u);return}}}else{j.isVisible&&!j.noVerticalRoom&&b.extend(j,R(k),ya(e));if(!f&&!j.noVerticalRoom&&B.height===j.outerHeight)return k.css(u),!0;l.top=B.top;l.bottom=B.bottom;j.newSize=B.height;l.height=O(k,B.height);j.maxHeight=l.height;p=0<=j.maxHeight;p||(j.noVerticalRoom=!0)}p?(!c&&q.initialized&&C("onresize_start",e),k.css(l),"center"!==e&&qa(e),j.noRoom&&(!j.isClosed&&!j.isHidden)&&ha(e),j.isVisible&&(b.extend(j,R(k)),q.initialized&&pa(e))):!j.noRoom&&j.isVisible&&ha(e);k.css(u);delete j.newSize;
-delete j.newWidth;delete j.newHeight;if(!j.isVisible)return!0;"center"===e&&(j=G.isIE6||!G.boxModel,y.north&&(j||"IFRAME"==q.north.tagName)&&y.north.css("width",Q(y.north,v.innerWidth)),y.south&&(j||"IFRAME"==q.south.tagName)&&y.south.css("width",Q(y.south,v.innerWidth)));!c&&q.initialized&&C("onresize_end",e)}})},oa=function(a){A(a);if(u.is(":visible"))if(q.initialized){if(!0===a&&b.isPlainObject(r.outset)&&u.css(r.outset),b.extend(v,R(u,r.inset)),v.outerHeight){!0===a&&ob();if(!1===C("onresizeall_start"))return!1;
-var d,c,f;b.each(["south","north","east","west"],function(a,b){y[b]&&(c=r[b],f=q[b],f.autoResize&&f.size!=c.size?ka(b,c.size,!0,!0,!0):(Y(b),ha(b,!1,!0,!0)))});ia("",!0,!0);qa();b.each(k.allPanes,function(a,b){(d=y[b])&&q[b].isVisible&&C("onresize_end",b)});C("onresizeall_end")}}else Aa()},db=function(a,d){var c=A.call(this,a);r[c].resizeChildren&&(d||Ba(c),c=ba[c],b.isPlainObject(c)&&b.each(c,function(a,b){b.destroyed||b.resizeAll()}))},pa=function(a,c){if(H()){var h=A.call(this,a),h=h?h.split(","):
-k.allPanes;b.each(h,function(a,e){function h(a){return d(u.css.paddingBottom,parseInt(a.css("marginBottom"),10)||0)}function j(){var a=r[e].contentIgnoreSelector,a=p.nextAll().not(".ui-layout-mask").not(a||":lt(0)"),b=a.filter(":visible"),d=b.filter(":last");v={top:p[0].offsetTop,height:p.outerHeight(),numFooters:a.length,hiddenFooters:a.length-b.length,spaceBelow:0};v.spaceAbove=v.top;v.bottom=v.top+v.height;v.spaceBelow=d.length?d[0].offsetTop+d.outerHeight()-v.bottom+h(d):h(p)}var m=y[e],p=U[e],
-l=r[e],u=q[e],v=u.content;if(!m||!p||!m.is(":visible"))return!0;if(!p.length&&(Sa(e,!1),!p))return;if(!1!==C("onsizecontent_start",e)){if(!u.isMoving&&!u.isResizing||l.liveContentResizing||c||void 0==v.top)j(),0<v.hiddenFooters&&"hidden"===m.css("overflow")&&(m.css("overflow","visible"),j(),m.css("overflow","hidden"));m=u.innerHeight-(v.spaceAbove-u.css.paddingTop)-(v.spaceBelow-u.css.paddingBottom);if(!p.is(":visible")||v.height!=m){var x=p,l=x;f(x)?l=y[x]:x.jquery||(l=b(x));x=O(l,m);l.css({height:x,
-visibility:"visible"});0<x&&0<l.innerWidth()?l.data("autoHidden")&&(l.show().data("autoHidden",!1),G.mozilla||l.css(k.hidden).css(k.visible)):l.data("autoHidden")||l.hide().data("autoHidden",!0);v.height=m}q.initialized&&C("onsizecontent_end",e)}})}},qa=function(a){a=(a=A.call(this,a))?a.split(","):k.borderPanes;b.each(a,function(a,d){var e=r[d],g=q[d],h=y[d],j=F[d],p=P[d],u;if(h&&j){var l=k[d].dir,x=g.isClosed?"_closed":"_open",B=e["spacing"+x],z=e["togglerAlign"+x],x=e["togglerLength"+x],A;if(0===
-B)j.hide();else{!g.noRoom&&!g.isHidden&&j.show();"horz"===l?(A=v.innerWidth,g.resizerLength=A,h=b.layout.cssNum(h,"left"),j.css({width:Q(j,A),height:O(j,B),left:-9999<h?h:v.inset.left})):(A=h.outerHeight(),g.resizerLength=A,j.css({height:O(j,A),width:Q(j,B),top:v.inset.top+ga("north",!0)}));da(e,j);if(p){if(0===x||g.isSliding&&e.hideTogglerOnSlide){p.hide();return}p.show();if(!(0<x)||"100%"===x||x>A)x=A,z=0;else if(f(z))switch(z){case "top":case "left":z=0;break;case "bottom":case "right":z=A-x;break;
-default:z=c((A-x)/2)}else h=parseInt(z,10),z=0<=z?h:A-x+h;if("horz"===l){var D=Q(p,x);p.css({width:D,height:O(p,B),left:z,top:0});p.children(".content").each(function(){u=b(this);u.css("marginLeft",c((D-u.outerWidth())/2))})}else{var C=O(p,x);p.css({height:C,width:Q(p,B),top:z,left:0});p.children(".content").each(function(){u=b(this);u.css("marginTop",c((C-u.outerHeight())/2))})}da(0,p)}if(!q.initialized&&(e.initHidden||g.isHidden))j.hide(),p&&p.hide()}}})},pb=function(a){if(H()){var b=A.call(this,
-a);a=P[b];var d=r[b];a&&(d.closable=!0,a.bind("click."+K,function(a){a.stopPropagation();na(b)}).css("visibility","visible").css("cursor","pointer").attr("title",q[b].isClosed?d.tips.Open:d.tips.Close).show())}},Va=function(a,d){b.layout.plugins.buttons&&b.each(q[a].pins,function(c,f){b.layout.buttons.setPinState(z,b(f),a,d)})},u=b(this).eq(0);if(!u.length)return ca(r.errors.containerMissing);if(u.data("layoutContainer")&&u.data("layout"))return u.data("layout");var y={},U={},F={},P={},ea=b([]),v=
-q.container,K=q.id,z={options:r,state:q,container:u,panes:y,contents:U,resizers:F,togglers:P,hide:Ta,show:Fa,toggle:na,open:ra,close:ja,slideOpen:sb,slideClose:Wa,slideToggle:function(a){a=A.call(this,a);na(a,!0)},setSizeLimits:Y,_sizePane:ka,sizePane:Ca,sizeContent:pa,swapPanes:function(a,c){function f(a){var d=y[a],c=U[a];return!d?!1:{pane:a,P:d?d[0]:!1,C:c?c[0]:!1,state:b.extend(!0,{},q[a]),options:b.extend(!0,{},r[a])}}function h(a,c){if(a){var e=a.P,f=a.C,g=a.pane,j=k[c],m=b.extend(!0,{},q[c]),
-n=r[c],w={resizerCursor:n.resizerCursor};b.each(["fxName","fxSpeed","fxSettings"],function(a,b){w[b+"_open"]=n[b+"_open"];w[b+"_close"]=n[b+"_close"];w[b+"_size"]=n[b+"_size"]});y[c]=b(e).data({layoutPane:z[c],layoutEdge:c}).css(k.hidden).css(j.cssReq);U[c]=f?b(f):!1;r[c]=b.extend(!0,{},a.options,w);q[c]=b.extend(!0,{},a.state);e.className=e.className.replace(RegExp(n.paneClass+"-"+g,"g"),n.paneClass+"-"+c);Pa(c);j.dir!=k[g].dir?(e=p[c]||0,Y(c),e=d(e,q[c].minSize),Ca(c,e,!0,!0)):F[c].css(j.side,v.inset[j.side]+
-(q[c].isVisible?ga(c):0));a.state.isVisible&&!m.isVisible?Ua(c,!0):(Da(c),ma(c,!0));a=null}}if(H()){var g=A.call(this,a);q[g].edge=c;q[c].edge=g;if(!1===C("onswap_start",g)||!1===C("onswap_start",c))q[g].edge=g,q[c].edge=c;else{var j=f(g),n=f(c),p={};p[g]=j?j.state.size:0;p[c]=n?n.state.size:0;y[g]=!1;y[c]=!1;q[g]={};q[c]={};P[g]&&P[g].remove();P[c]&&P[c].remove();F[g]&&F[g].remove();F[c]&&F[c].remove();F[g]=F[c]=P[g]=P[c]=!1;h(j,c);h(n,g);j=n=p=null;y[g]&&y[g].css(k.visible);y[c]&&y[c].css(k.visible);
-oa();C("onswap_end",g);C("onswap_end",c)}}},showMasks:va,hideMasks:za,initContent:Sa,addPane:ib,removePane:Ra,createChildren:Qa,refreshChildren:Ba,enableClosable:pb,disableClosable:function(a,b){if(H()){var c=A.call(this,a),d=P[c];d&&(r[c].closable=!1,q[c].isClosed&&ra(c,!1,!0),d.unbind("."+K).css("visibility",b?"hidden":"visible").css("cursor","default").attr("title",""))}},enableSlidable:function(a){if(H()){a=A.call(this,a);var b=F[a];b&&b.data("draggable")&&(r[a].slidable=!0,q[a].isClosed&&ma(a,
-!0))}},disableSlidable:function(a){if(H()){a=A.call(this,a);var b=F[a];b&&(r[a].slidable=!1,q[a].isSliding?ja(a,!1,!0):(ma(a,!1),b.css("cursor","default").attr("title",""),da(null,b[0])))}},enableResizable:function(a){if(H()){a=A.call(this,a);var b=F[a],c=r[a];b&&b.data("draggable")&&(c.resizable=!0,b.draggable("enable"),q[a].isClosed||b.css("cursor",c.resizerCursor).attr("title",c.tips.Resize))}},disableResizable:function(a){if(H()){a=A.call(this,a);var b=F[a];b&&b.data("draggable")&&(r[a].resizable=
-!1,b.draggable("disable").css("cursor","default").attr("title",""),da(null,b[0]))}},allowOverflow:x,resetOverflow:X,destroy:function(a,c){b(window).unbind("."+K);b(document).unbind("."+K);"object"===typeof a?A(a):c=a;u.clearQueue().removeData("layout").removeData("layoutContainer").removeClass(r.containerClass).unbind("."+K);ea.remove();b.each(k.allPanes,function(a,b){Ra(b,!1,!0,c)});u.data("layoutCSS")&&!u.data("layoutRole")&&u.css(u.data("layoutCSS")).removeData("layoutCSS");"BODY"===v.tagName&&
-(u=b("html")).data("layoutCSS")&&u.css(u.data("layoutCSS")).removeData("layoutCSS");j(z,b.layout.onDestroy);mb();for(var d in z)d.match(/^(container|options)$/)||delete z[d];z.destroyed=!0;return z},initPanes:H,resizeAll:oa,runCallbacks:C,hasParentLayout:!1,children:ba,north:!1,south:!1,west:!1,east:!1,center:!1},Xa;var V,Ya,N,Ha,la,sa,W;h=b.layout.transformData(h,!0);h=b.layout.backwardCompatibility.renameAllOptions(h);if(!b.isEmptyObject(h.panes)){V=b.layout.optionsMap.noDefault;la=0;for(sa=V.length;la<
-sa;la++)N=V[la],delete h.panes[N];V=b.layout.optionsMap.layout;la=0;for(sa=V.length;la<sa;la++)N=V[la],delete h.panes[N]}V=b.layout.optionsMap.layout;var Bb=b.layout.config.optionRootKeys;for(N in h)Ha=h[N],0>b.inArray(N,Bb)&&0>b.inArray(N,V)&&(h.panes[N]||(h.panes[N]=b.isPlainObject(Ha)?b.extend(!0,{},Ha):Ha),delete h[N]);b.extend(!0,r,h);b.each(k.allPanes,function(a,c){k[c]=b.extend(!0,{},k.panes,k[c]);Ya=r.panes;W=r[c];if("center"===c){V=b.layout.optionsMap.center;a=0;for(sa=V.length;a<sa;a++)if(N=
-V[a],!h.center[N]&&(h.panes[N]||!W[N]))W[N]=Ya[N]}else{W=r[c]=b.extend(!0,{},Ya,W);var d=r[c],f=r.panes;d.fxSettings||(d.fxSettings={});f.fxSettings||(f.fxSettings={});b.each(["_open","_close","_size"],function(a,e){var h="fxName"+e,j="fxSpeed"+e,k="fxSettings"+e,l=d[h]=d[h]||f[h]||d.fxName||f.fxName||"none",p=b.effects&&(b.effects[l]||b.effects.effect&&b.effects.effect[l]);if("none"===l||!r.effects[l]||!p)l=d[h]="none";l=r.effects[l]||{};h=l.all||null;l=l[c]||null;d[j]=d[j]||f[j]||d.fxSpeed||f.fxSpeed||
-null;d[k]=b.extend(!0,{},h,l,f.fxSettings,d.fxSettings,f[k],d[k])});delete d.fxName;delete d.fxSpeed;delete d.fxSettings;W.resizerClass||(W.resizerClass="ui-layout-resizer");W.togglerClass||(W.togglerClass="ui-layout-toggler")}W.paneClass||(W.paneClass="ui-layout-pane")});var Ia=h.zIndex,xa=r.zIndexes;0<Ia&&(xa.pane_normal=Ia,xa.content_mask=d(Ia+1,xa.content_mask),xa.resizer_normal=d(Ia+2,xa.resizer_normal));delete r.panes;var Cb=r,tb=q;tb.creatingLayout=!0;j(z,b.layout.onCreate);if(!1===C("onload_start"))Xa=
-"cancel";else{var Za=u[0],$=b("html"),ub=v.tagName=Za.tagName,vb=v.id=Za.id,wb=v.className=Za.className,L=r,Ja=L.name,$a={},Ka=u.data("parentLayout"),La=u.data("layoutEdge"),ab=Ka&&La,ta=b.layout.cssNum,bb,aa;v.selector=u.selector.split(".slice")[0];v.ref=(L.name?L.name+" layout / ":"")+ub+(vb?"#"+vb:wb?".["+wb+"]":"");v.isBody="BODY"===ub;!ab&&!v.isBody&&(bb=u.closest("."+b.layout.defaults.panes.paneClass),Ka=bb.data("parentLayout"),La=bb.data("layoutEdge"),ab=Ka&&La);u.data({layout:z,layoutContainer:K}).addClass(L.containerClass);
-var xb={destroy:"",initPanes:"",resizeAll:"resizeAll",resize:"resizeAll"};for(Ja in xb)u.bind("layout"+Ja.toLowerCase()+"."+K,z[xb[Ja]||Ja]);ab&&(z.hasParentLayout=!0,Ka.refreshChildren(La,z));u.data("layoutCSS")||(v.isBody?(u.data("layoutCSS",b.extend(D(u,"position,margin,padding,border"),{height:u.css("height"),overflow:u.css("overflow"),overflowX:u.css("overflowX"),overflowY:u.css("overflowY")})),$.data("layoutCSS",b.extend(D($,"padding"),{height:"auto",overflow:$.css("overflow"),overflowX:$.css("overflowX"),
-overflowY:$.css("overflowY")}))):u.data("layoutCSS",D(u,"position,margin,padding,border,top,bottom,left,right,width,height,overflow,overflowX,overflowY")));try{$a={overflow:"hidden",overflowX:"hidden",overflowY:"hidden"};u.css($a);L.inset&&!b.isPlainObject(L.inset)&&(aa=parseInt(L.inset,10)||0,L.inset={top:aa,bottom:aa,left:aa,right:aa});if(v.isBody)L.outset?b.isPlainObject(L.outset)||(aa=parseInt(L.outset,10)||0,L.outset={top:aa,bottom:aa,left:aa,right:aa}):L.outset={top:ta($,"paddingTop"),bottom:ta($,
-"paddingBottom"),left:ta($,"paddingLeft"),right:ta($,"paddingRight")},$.css($a).css({height:"100%",border:"none",padding:0,margin:0}),G.isIE6?(u.css({width:"100%",height:"100%",border:"none",padding:0,margin:0,position:"relative"}),L.inset||(L.inset=R(u).inset)):(u.css({width:"auto",height:"auto",margin:0,position:"absolute"}),u.css(L.outset)),b.extend(v,R(u,L.inset));else{var yb=u.css("position");(!yb||!yb.match(/(fixed|absolute|relative)/))&&u.css("position","relative");u.is(":visible")&&(b.extend(v,
-R(u,L.inset)),1>v.innerHeight&&ca(L.errors.noContainerHeight.replace(/CONTAINER/,v.ref)))}ta(u,"minWidth")&&u.parent().css("overflowX","auto");ta(u,"minHeight")&&u.parent().css("overflowY","auto")}catch(Db){}nb();b(window).bind("unload."+K,mb);j(z,b.layout.onLoad);Cb.initPanes&&Aa();delete tb.creatingLayout;Xa=q.initialized}return"cancel"===Xa?null:z}})(jQuery);
-(function(b){b.ui||(b.ui={});b.ui.cookie={acceptsCookies:!!navigator.cookieEnabled,read:function(a){for(var d=document.cookie,d=d?d.split(";"):[],c,f=0,j=d.length;f<j;f++)if(c=b.trim(d[f]).split("="),c[0]==a)return decodeURIComponent(c[1]);return null},write:function(a,d,c){var f="",j="",h=!1;c=c||{};var p=c.expires||null,x=b.type(p);"date"===x?j=p:"string"===x&&0<p&&(p=parseInt(p,10),x="number");"number"===x&&(j=new Date,0<p?j.setDate(j.getDate()+p):(j.setFullYear(1970),h=!0));j&&(f+=";expires="+
-j.toUTCString());c.path&&(f+=";path="+c.path);c.domain&&(f+=";domain="+c.domain);c.secure&&(f+=";secure");document.cookie=a+"="+(h?"":encodeURIComponent(d))+f},clear:function(a){b.ui.cookie.write(a,"",{expires:-1})}};b.cookie||(b.cookie=function(a,d,c){var f=b.ui.cookie;if(null===d)f.clear(a);else{if(void 0===d)return f.read(a);f.write(a,d,c)}});b.layout.plugins.stateManagement=!0;b.layout.config.optionRootKeys.push("stateManagement");b.layout.defaults.stateManagement={enabled:!1,autoSave:!0,autoLoad:!0,
-animateLoad:!0,includeChildren:!0,stateKeys:"north.size,south.size,east.size,west.size,north.isClosed,south.isClosed,east.isClosed,west.isClosed,north.isHidden,south.isHidden,east.isHidden,west.isHidden",cookie:{name:"",domain:"",path:"",expires:"",secure:!1}};b.layout.optionsMap.layout.push("stateManagement");b.layout.state={saveCookie:function(a,d,c){var f=a.options,j=f.stateManagement;c=b.extend(!0,{},j.cookie,c||null);a=a.state.stateData=a.readState(d||j.stateKeys);b.ui.cookie.write(c.name||f.name||
-"Layout",b.layout.state.encodeJSON(a),c);return b.extend(!0,{},a)},deleteCookie:function(a){a=a.options;b.ui.cookie.clear(a.stateManagement.cookie.name||a.name||"Layout")},readCookie:function(a){a=a.options;return(a=b.ui.cookie.read(a.stateManagement.cookie.name||a.name||"Layout"))?b.layout.state.decodeJSON(a):{}},loadCookie:function(a){var d=b.layout.state.readCookie(a);d&&(a.state.stateData=b.extend(!0,{},d),a.loadState(d));return d},loadState:function(a,d,c){if(b.isPlainObject(d)&&!b.isEmptyObject(d))if(d=
-a.state.stateData=b.layout.transformData(d),c=b.extend({animateLoad:!1,includeChildren:a.options.stateManagement.includeChildren},c),a.state.initialized){var f=!c.animateLoad,j,h,p,x;b.each(b.layout.config.borderPanes,function(c,G){S=d[G];b.isPlainObject(S)&&(s=S.size,j=S.initClosed,h=S.initHidden,ar=S.autoResize,p=a.state[G],x=p.isVisible,ar&&(p.autoResize=ar),x||a._sizePane(G,s,!1,!1,!1),!0===h?a.hide(G,f):!0===j?a.close(G,!1,f):!1===j?a.open(G,!1,f):!1===h&&a.show(G,!1,f),x&&a._sizePane(G,s,!1,
-!1,f))});if(c.includeChildren){var I,T;b.each(a.children,function(a,c){(I=d[a]?d[a].children:0)&&c&&b.each(c,function(a,b){T=I[a];b&&T&&b.loadState(T)})})}}else{var S=b.extend(!0,{},d);b.each(b.layout.config.allPanes,function(a,b){S[b]&&delete S[b].children});b.extend(!0,a.options,S)}},readState:function(a,d){"string"===b.type(d)&&(d={keys:d});d||(d={});var c=a.options.stateManagement,f=d.includeChildren,f=void 0!==f?f:c.includeChildren,c=d.stateKeys||c.stateKeys,j={isClosed:"initClosed",isHidden:"initHidden"},
-h=a.state,p=b.layout.config.allPanes,x={},I,T,S,X,G,k;b.isArray(c)&&(c=c.join(","));for(var c=c.replace(/__/g,".").split(","),Q=0,O=c.length;Q<O;Q++)I=c[Q].split("."),T=I[0],I=I[1],0>b.inArray(T,p)||(S=h[T][I],void 0!=S&&("isClosed"==I&&h[T].isSliding&&(S=!0),(x[T]||(x[T]={}))[j[I]?j[I]:I]=S));f&&b.each(p,function(c,d){G=a.children[d];X=h.stateData[d];b.isPlainObject(G)&&!b.isEmptyObject(G)&&(k=x[d]||(x[d]={}),k.children||(k.children={}),b.each(G,function(a,c){c.state.initialized?k.children[a]=b.layout.state.readState(c):
-X&&(X.children&&X.children[a])&&(k.children[a]=b.extend(!0,{},X.children[a]))}))});return x},encodeJSON:function(a){function d(a){var f=[],j=0,h,p,x,I=b.isArray(a);for(h in a)p=a[h],x=typeof p,"string"==x?p='"'+p+'"':"object"==x&&(p=d(p)),f[j++]=(!I?'"'+h+'":':"")+p;return(I?"[":"{")+f.join(",")+(I?"]":"}")}return d(a)},decodeJSON:function(a){try{return b.parseJSON?b.parseJSON(a):window.eval("("+a+")")||{}}catch(d){return{}}},_create:function(a){var d=b.layout.state,c=a.options.stateManagement;b.extend(a,
-{readCookie:function(){return d.readCookie(a)},deleteCookie:function(){d.deleteCookie(a)},saveCookie:function(b,c){return d.saveCookie(a,b,c)},loadCookie:function(){return d.loadCookie(a)},loadState:function(b,c){d.loadState(a,b,c)},readState:function(b){return d.readState(a,b)},encodeJSON:d.encodeJSON,decodeJSON:d.decodeJSON});a.state.stateData={};if(c.autoLoad)if(b.isPlainObject(c.autoLoad))b.isEmptyObject(c.autoLoad)||a.loadState(c.autoLoad);else if(c.enabled)if(b.isFunction(c.autoLoad)){var f=
-{};try{f=c.autoLoad(a,a.state,a.options,a.options.name||"")}catch(j){}f&&(b.isPlainObject(f)&&!b.isEmptyObject(f))&&a.loadState(f)}else a.loadCookie()},_unload:function(a){var d=a.options.stateManagement;if(d.enabled&&d.autoSave)if(b.isFunction(d.autoSave))try{d.autoSave(a,a.state,a.options,a.options.name||"")}catch(c){}else a.saveCookie()}};b.layout.onCreate.push(b.layout.state._create);b.layout.onUnload.push(b.layout.state._unload);b.layout.plugins.buttons=!0;b.layout.defaults.autoBindCustomButtons=
-!1;b.layout.optionsMap.layout.push("autoBindCustomButtons");b.layout.buttons={init:function(a){var d=a.options.name||"",c;b.each("toggle open close pin toggle-slide open-slide".split(" "),function(f,j){b.each(b.layout.config.borderPanes,function(f,p){b(".ui-layout-button-"+j+"-"+p).each(function(){c=b(this).data("layoutName")||b(this).attr("layoutName");(void 0==c||c===d)&&a.bindButton(this,j,p)})})})},get:function(a,d,c,f){var j=b(d);a=a.options;var h=a.errors.addButtonError;j.length?0>b.inArray(c,
-b.layout.config.borderPanes)?(b.layout.msg(h+" "+a.errors.pane+": "+c,!0),j=b("")):(d=a[c].buttonClass+"-"+f,j.addClass(d+" "+d+"-"+c).data("layoutName",a.name)):b.layout.msg(h+" "+a.errors.selector+": "+d,!0);return j},bind:function(a,d,c,f){var j=b.layout.buttons;switch(c.toLowerCase()){case "toggle":j.addToggle(a,d,f);break;case "open":j.addOpen(a,d,f);break;case "close":j.addClose(a,d,f);break;case "pin":j.addPin(a,d,f);break;case "toggle-slide":j.addToggle(a,d,f,!0);break;case "open-slide":j.addOpen(a,
-d,f,!0)}return a},addToggle:function(a,d,c,f){b.layout.buttons.get(a,d,c,"toggle").click(function(b){a.toggle(c,!!f);b.stopPropagation()});return a},addOpen:function(a,d,c,f){b.layout.buttons.get(a,d,c,"open").attr("title",a.options[c].tips.Open).click(function(b){a.open(c,!!f);b.stopPropagation()});return a},addClose:function(a,d,c){b.layout.buttons.get(a,d,c,"close").attr("title",a.options[c].tips.Close).click(function(b){a.close(c);b.stopPropagation()});return a},addPin:function(a,d,c){var f=b.layout.buttons,
-j=f.get(a,d,c,"pin");if(j.length){var h=a.state[c];j.click(function(d){f.setPinState(a,b(this),c,h.isSliding||h.isClosed);h.isSliding||h.isClosed?a.open(c):a.close(c);d.stopPropagation()});f.setPinState(a,j,c,!h.isClosed&&!h.isSliding);h.pins.push(d)}return a},setPinState:function(a,b,c,f){var j=b.attr("pin");if(!(j&&f===("down"==j))){a=a.options[c];var j=a.buttonClass+"-pin",h=j+"-"+c;c=j+"-up "+h+"-up";j=j+"-down "+h+"-down";b.attr("pin",f?"down":"up").attr("title",f?a.tips.Unpin:a.tips.Pin).removeClass(f?
-c:j).addClass(f?j:c)}},syncPinBtns:function(a,d,c){b.each(a.state[d].pins,function(f,j){b.layout.buttons.setPinState(a,b(j),d,c)})},_load:function(a){var d=b.layout.buttons;b.extend(a,{bindButton:function(b,c,h){return d.bind(a,b,c,h)},addToggleBtn:function(b,c,h){return d.addToggle(a,b,c,h)},addOpenBtn:function(b,c,h){return d.addOpen(a,b,c,h)},addCloseBtn:function(b,c){return d.addClose(a,b,c)},addPinBtn:function(b,c){return d.addPin(a,b,c)}});for(var c=0;4>c;c++)a.state[b.layout.config.borderPanes[c]].pins=
-[];a.options.autoBindCustomButtons&&d.init(a)},_unload:function(){}};b.layout.onLoad.push(b.layout.buttons._load);b.layout.plugins.browserZoom=!0;b.layout.defaults.browserZoomCheckInterval=1E3;b.layout.optionsMap.layout.push("browserZoomCheckInterval");b.layout.browserZoom={_init:function(a){!1!==b.layout.browserZoom.ratio()&&b.layout.browserZoom._setTimer(a)},_setTimer:function(a){if(!a.destroyed){var d=a.options,c=a.state,f=a.hasParentLayout?5E3:Math.max(d.browserZoomCheckInterval,100);setTimeout(function(){if(!a.destroyed&&
-d.resizeWithWindow){var f=b.layout.browserZoom.ratio();f!==c.browserZoom&&(c.browserZoom=f,a.resizeAll());b.layout.browserZoom._setTimer(a)}},f)}},ratio:function(){function a(a,b){return(100*(parseInt(a,10)/parseInt(b,10))).toFixed()}var d=window,c=screen,f=document,j=f.documentElement||f.body,h=b.layout.browser,p=h.version,x,I,T;return h.msie&&8<p||!h.msie?!1:c.deviceXDPI&&c.systemXDPI?a(c.deviceXDPI,c.systemXDPI):h.webkit&&(x=f.body.getBoundingClientRect)?a(x.left-x.right,f.body.offsetWidth):h.webkit&&
-(I=d.outerWidth)?a(I,d.innerWidth):(I=c.width)&&(T=j.clientWidth)?a(I,T):!1}};b.layout.onReady.push(b.layout.browserZoom._init)})(jQuery);
\ No newline at end of file
diff --git a/src/main/webapp/static/js/jquery/uilayout/layout-default-latest.css b/src/main/webapp/static/js/jquery/uilayout/layout-default-latest.css
deleted file mode 100644
index 14e507b51d566b886b301f2c5f8b0cf8b68747da..0000000000000000000000000000000000000000
--- a/src/main/webapp/static/js/jquery/uilayout/layout-default-latest.css
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Default Layout Theme
- *
- * Created for jquery.layout 
- *
- * Copyright (c) 2010 
- *   Fabrizio Balliano (http://www.fabrizioballiano.net)
- *   Kevin Dalman (http://allpro.net)
- *
- * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
- * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
- *
- * Last Updated: 2010-02-10
- * NOTE: For best code readability, view this with a fixed-space font and tabs equal to 4-chars
- */
-
-/*
- *	DEFAULT FONT
- *	Just to make demo-pages look better - not actually relevant to Layout!
- */
-body {
-	font-family: Geneva, Arial, Helvetica, sans-serif;
-	font-size:   100%;
-	*font-size:  80%;
-}
-
-/*
- *	PANES & CONTENT-DIVs
- */
-.ui-layout-pane { /* all 'panes' */
-	background:	#FFF; 
-	border:		1px solid #BBB;
-	padding:	10px; 
-	overflow:	auto;
-	/* DO NOT add scrolling (or padding) to 'panes' that have a content-div,
-	   otherwise you may get double-scrollbars - on the pane AND on the content-div
-	   - use ui-layout-wrapper class if pane has a content-div
-	   - use ui-layout-container if pane has an inner-layout
-	*/
-	}
-	/* (scrolling) content-div inside pane allows for fixed header(s) and/or footer(s) */
-	.ui-layout-content {
-		padding:	10px;
-		position:	relative; /* contain floated or positioned elements */
-		overflow:	auto; /* add scrolling to content-div */
-	}
-
-/*
- *	UTILITY CLASSES
- *	Must come AFTER pane-class above so will override
- *	These classes are NOT auto-generated and are NOT used by Layout
- */
-.layout-child-container,
-.layout-content-container {
-	padding:	0;
-	overflow:	hidden;
-}
-.layout-child-container {
-	border:		0; /* remove border because inner-layout-panes probably have borders */
-}
-.layout-scroll {
-	overflow:	auto;
-}
-.layout-hide {
-	display:	none;
-}
-
-/*
- *	RESIZER-BARS
- */
-.ui-layout-resizer	{ /* all 'resizer-bars' */
-	background:		#DDD;
-	border:			1px solid #BBB;
-	border-width:	0;
-	}
-	.ui-layout-resizer-drag {		/* REAL resizer while resize in progress */
-	}
-	.ui-layout-resizer-hover	{	/* affects both open and closed states */
-	}
-	/* NOTE: It looks best when 'hover' and 'dragging' are set to the same color,
-		otherwise color shifts while dragging when bar can't keep up with mouse */
-	.ui-layout-resizer-open-hover ,	/* hover-color to 'resize' */
-	.ui-layout-resizer-dragging {	/* resizer beging 'dragging' */
-		background: #C4E1A4;
-	}
-	.ui-layout-resizer-dragging {	/* CLONED resizer being dragged */
-		border: 	 1px solid #BBB;
-	}
-	.ui-layout-resizer-north-dragging,
-	.ui-layout-resizer-south-dragging {
-		border-width:	1px 0;
-	}
-	.ui-layout-resizer-west-dragging,
-	.ui-layout-resizer-east-dragging {
-		border-width:	0 1px;
-	}
-	/* NOTE: Add a 'dragging-limit' color to provide visual feedback when resizer hits min/max size limits */
-	.ui-layout-resizer-dragging-limit {	/* CLONED resizer at min or max size-limit */
-		background: #E1A4A4; /* red */
-	}
-
-	.ui-layout-resizer-closed-hover	{ /* hover-color to 'slide open' */
-		background: #EBD5AA;
-	}
-	.ui-layout-resizer-sliding {	/* resizer when pane is 'slid open' */
-		opacity: .10; /* show only a slight shadow */
-		filter:  alpha(opacity=10);
-		}
-		.ui-layout-resizer-sliding-hover {	/* sliding resizer - hover */
-			opacity: 1.00; /* on-hover, show the resizer-bar normally */
-			filter:  alpha(opacity=100);
-		}
-		/* sliding resizer - add 'outside-border' to resizer on-hover 
-		 * this sample illustrates how to target specific panes and states */
-		.ui-layout-resizer-north-sliding-hover	{ border-bottom-width:	1px; }
-		.ui-layout-resizer-south-sliding-hover	{ border-top-width:		1px; }
-		.ui-layout-resizer-west-sliding-hover	{ border-right-width:	1px; }
-		.ui-layout-resizer-east-sliding-hover	{ border-left-width:	1px; }
-
-/*
- *	TOGGLER-BUTTONS
- */
-.ui-layout-toggler {
-	border: 1px solid #BBB; /* match pane-border */
-	background-color: #BBB;
-	}
-	.ui-layout-resizer-hover .ui-layout-toggler {
-		opacity: .60;
-		filter:  alpha(opacity=60);
-	}
-	.ui-layout-toggler-hover , /* need when NOT resizable */
-	.ui-layout-resizer-hover .ui-layout-toggler-hover { /* need specificity when IS resizable */
-		background-color: #FC6;
-		opacity: 1.00;
-		filter:  alpha(opacity=100);
-	}
-	.ui-layout-toggler-north ,
-	.ui-layout-toggler-south {
-		border-width: 0 1px; /* left/right borders */
-	}
-	.ui-layout-toggler-west ,
-	.ui-layout-toggler-east {
-		border-width: 1px 0; /* top/bottom borders */
-	}
-	/* hide the toggler-button when the pane is 'slid open' */
-	.ui-layout-resizer-sliding  .ui-layout-toggler {
-		display: none;
-	}
-	/*
-	 *	style the text we put INSIDE the togglers
-	 */
-	.ui-layout-toggler .content {
-		color:			#666;
-		font-size:		12px;
-		font-weight:	bold;
-		width:			100%;
-		padding-bottom:	0.35ex; /* to 'vertically center' text inside text-span */
-	}
-
-/*
- *	PANE-MASKS
- *	these styles are hard-coded on mask elems, but are also 
- *	included here as !important to ensure will overrides any generic styles
- */
-.ui-layout-mask {
-	border:		none !important;
-	padding:	0 !important;
-	margin:		0 !important;
-	overflow:	hidden !important;
-	position:	absolute !important;
-	opacity:	0 !important;
-	filter:		Alpha(Opacity="0") !important;
-}
-.ui-layout-mask-inside-pane { /* masks always inside pane EXCEPT when pane is an iframe */
-	top:		0 !important;
-	left:		0 !important;
-	width:		100% !important;
-	height:		100% !important;
-}
-div.ui-layout-mask {}		/* standard mask for iframes */
-iframe.ui-layout-mask {}	/* extra mask for objects/applets */
-
-/*
- *	Default printing styles
- */
-@media print {
-	/*
-	 *	Unless you want to print the layout as it appears onscreen,
-	 *	these html/body styles are needed to allow the content to 'flow'
-	 */
-	html {
-		height:		auto !important;
-		overflow:	visible !important;
-	}
-	body.ui-layout-container {
-		position:	static !important;
-		top:		auto !important;
-		bottom:		auto !important;
-		left:		auto !important;
-		right:		auto !important;
-		/* only IE6 has container width & height set by Layout */
-		_width:		auto !important;
-		_height:	auto !important;
-	}
-	.ui-layout-resizer, .ui-layout-toggler {
-		display:	none !important;
-	}
-	/*
-	 *	Default pane print styles disables positioning, borders and backgrounds.
-	 *	You can modify these styles however it suit your needs.
-	 */
-	.ui-layout-pane {
-		border:		none !important;
-		background:	 transparent !important;
-		position:	relative !important;
-		top:		auto !important;
-		bottom:		auto !important;
-		left:		auto !important;
-		right:		auto !important;
-		width:		auto !important;
-		height:		auto !important;
-		overflow:	visible !important;
-	}
-}
\ No newline at end of file
diff --git a/src/main/webapp/static/themes/light/modules/_qpool.scss b/src/main/webapp/static/themes/light/modules/_qpool.scss
index 3a85a541c489bfaeac3bedd557b34960c16bd479..540bed38591385b57a32818d40611ea03ed2874b 100644
--- a/src/main/webapp/static/themes/light/modules/_qpool.scss
+++ b/src/main/webapp/static/themes/light/modules/_qpool.scss
@@ -7,3 +7,4 @@
 .o_sel_qpool_pool { @extend .o_sel_qpool_pool }
 .o_icon_private_pool { @extend .o_icon-times; }
 .o_icon_public_pool { @extend .o_icon-check; }
+
diff --git a/src/main/webapp/static/themes/light/modules/_table.scss b/src/main/webapp/static/themes/light/modules/_table.scss
index 82291545525cb46061c235602d3586c9ee77cd01..89bcb6aa9f8b581bb6d7f70e15147c4dea5e73e9 100644
--- a/src/main/webapp/static/themes/light/modules/_table.scss
+++ b/src/main/webapp/static/themes/light/modules/_table.scss
@@ -50,10 +50,6 @@
 	.o_table {
 		margin-bottom: 0;
 	}
-	
-	.dataTables_info {
-		padding: 5px 10px 5px 0;
-	}
 }
 
 .o_table_buttons {
diff --git a/src/main/webapp/static/themes/light/modules/_thirdparty.scss b/src/main/webapp/static/themes/light/modules/_thirdparty.scss
index c9b94e400e3a8ef13eb8830d4461b48cd4a5fca2..57d78626bb4720b6ccc13b67164a43f707a65ed7 100644
--- a/src/main/webapp/static/themes/light/modules/_thirdparty.scss
+++ b/src/main/webapp/static/themes/light/modules/_thirdparty.scss
@@ -52,38 +52,6 @@
 	display:none;
 }
 
-/*
- * autocomplete
- */
-.ui-autocomplete-input {
-	line-height: 1.5em;
-	font-size: 98%;
-}
-.ui-autocomplete {
-	z-index: 10000;
-	&.ui-menu {
-		padding: 1px;
-	}
-	&.ui-corner-all {
-		border: 1px solid $basecolor;
-		border-top: none;
-		@include o-border-radius-all(0,0,$di_border_radius,$di_border_radius);
-		@include o-box-shadow(0px,3px,6px,rgba(0,0,0,0.3));
-	}
-	a.ui-corner-all {
-		border: none;
-		margin: -1px;
-		@include o-border-radius(0);
-		&.ui-state-focus {
-			background: $selectcolor_ultra_light;
-		}
-	}	
-	.b_error_icon { 
-		color: $nokcolor; 
-		font-style: italic;
-	}
-}
-
 /*
  * datepicker
  */
@@ -122,42 +90,6 @@
 	border-color: $basecolor;
 }
 
-/*
- * tooltip
- */
-.ui-tooltip {
-	@include o-box-shadow(0px,0px,6px,rgba(0,0,0,0.3));
-}
- 
-.ui-tooltip.ui-corner-all {
-	@include o-border-radius($di_border_radius);
-}
-
-.ui-tooltip.ui-widget-content {
-	border: 1px solid $basecolor;
-}
-
-//overwrite uilayout
-.ui-layout-pane {
-	border:none;
-}
-
-.ui-layout-resizer {
-	background: none;
-	border-width: 1px;
-	border-style: dotted;
-}
-
-.ui-layout-toggler-hover, .ui-layout-resizer-hover .ui-layout-toggler-hover {
-	background-color: $basecolor;
-}
-
-.ui-layout-resizer-open-hover, .ui-layout-resizer-dragging {
-	background: $basecolor_ultra_light;
-}
-
-//overwrite datatables -> see _tables.scss
-
 /* calendar */
 .fc-state-highlight {
 	background: $selectcolor_ultra_light;
diff --git a/src/main/webapp/static/themes/light/theme.css b/src/main/webapp/static/themes/light/theme.css
index 888f36e68dbac8e2c33745a59815dfcd3e9b6d53..b2bb5ea5b6671f3e128df8e65bc8947e4531d32a 100644
--- a/src/main/webapp/static/themes/light/theme.css
+++ b/src/main/webapp/static/themes/light/theme.css
@@ -46,7 +46,7 @@ small,.small,.o_comments .o_comment_wrapper h5,.o_comments .o_comment_wrapper .o
 #o_footer_wrapper{position:absolute;bottom:0;width:100%;z-index:2;min-height:60px;background-color:#f5f5f5;color:#999;line-height:16px}#o_footer_wrapper a{color:#999}#o_footer_wrapper a:hover{color:#000}#o_footer_wrapper #o_footer_container{position:relative;padding-top:10px;min-height:60px;background:#f5f5f5}#o_footer_wrapper #o_footer_container #o_footer_user #o_counter{white-space:nowrap}#o_footer_wrapper #o_footer_container #o_footer_user #o_username{white-space:nowrap;margin-right:1em}#o_footer_wrapper #o_footer_container #o_footer_version{text-align:right}@media (max-width: 767px){#o_footer_wrapper #o_footer_container #o_footer_version{padding-top:10px;text-align:left}}#o_footer_wrapper #o_footer_container #o_footer_powered{text-align:center}#o_footer_wrapper #o_footer_container #o_footer_powered img{zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=60);-moz-opacity:0.6;-khtml-opacity:0.6;opacity:0.6}#o_footer_wrapper #o_footer_container #o_footer_powered img:hover{zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=100);-moz-opacity:1;-khtml-opacity:1;opacity:1}@media (max-width: 767px){#o_footer_wrapper #o_footer_container #o_footer_powered{display:none}}
 #o_share{margin-top:10px;width:250px}#o_share a{margin:0 5px 0 0;float:left;zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=60);-moz-opacity:0.6;-khtml-opacity:0.6;opacity:0.6}#o_share a:hover{zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=100);-moz-opacity:1;-khtml-opacity:1;opacity:1}#o_navbar_wrapper{z-index:4}#o_navbar_wrapper #o_navbar_container{position:relative}#o_navbar_wrapper #o_navbar_container a.o_navbar-brand{font-size:40px;vertical-align:top;font-weight:bold;color:#31729B}#o_navbar_wrapper #o_navbar_container a.o_navbar-brand:after{content:"\221E"}.o_navbar .o_navbar_tabs li a{padding-right:30px}.o_navbar .o_navbar_tabs .o_navbar_tab_close{position:absolute;top:15px;right:0.5em;padding:0;width:1em;height:1em}.o_navbar .o_navbar_tabs .o_navbar_tab_close i:before{color:#A87E7E}.o_navbar .o_navbar_tabs .o_navbar_tab_close:hover i:before{color:#CC0000}.o_navbar #o_navbar_tools_permanent #o_navbar_langchooser{color:#777;padding:7px 15px}.o_navbar #o_navbar_tools_permanent #o_navbar_langchooser form span+div{display:inline}.o_navbar #o_navbar_tools_permanent #o_navbar_help a i{margin-right:0.4em}.o_navbar #o_navbar_tools_personal .o_navbar_tool a{padding-right:5px}.o_navbar #o_navbar_tools_personal #o_navbar_my_menu .dropdown-toggle{padding-left:45px}.o_navbar #o_navbar_tools_personal #o_navbar_my_menu img{position:absolute;left:7px;top:10px;height:30px;width:30px}.o_navbar #o_navbar_tools_personal .o_logout{color:#d9534f}.o_navbar.o_navbar-offcanvas .o_navbar_tab_close{top:10px}.o_navbar.o_navbar-offcanvas .o_navbar_tool{display:none}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu a{color:#999}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu a:hover,.o_navbar.o_navbar-offcanvas #o_navbar_my_menu a:focus{color:#fff;background-color:transparent}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu a.o_logout{color:#d9534f}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu a.o_logout:hover,.o_navbar.o_navbar-offcanvas #o_navbar_my_menu a.o_logout:focus{color:#d9534f}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu .dropdown-header{padding-left:15px}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu .dropdown-toggle{display:none}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu .dropdown-menu{box-shadow:none;position:relative;top:0;left:0;display:block;float:none;background-color:#222;color:#999;font-size:14px}.o_navbar.o_navbar-offcanvas #o_navbar_my_menu .dropdown-menu .divider{background:none}.o_navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}.o_navbar:before,.o_navbar:after{content:" ";display:table}.o_navbar:after{clear:both}.o_navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.o_navbar-collapse:before,.o_navbar-collapse:after{content:" ";display:table}.o_navbar-collapse:after{clear:both}.o_navbar-collapse.o_collapse{display:block !important;height:auto !important;padding-bottom:0;overflow:visible !important}.o_navbar-offcanvas .o_navbar-collapse{width:auto;border-top:0;box-shadow:none;margin-top:10px;margin-right:-15px;margin-left:-15px}.o_navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}.o_navbar-brand:hover,.o_navbar-brand:focus{text-decoration:none}.o_navbar-toggle{position:relative;margin-right:15px;margin-left:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.o_navbar-toggle:focus{outline:none}.o_navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.o_navbar-toggle .icon-bar+.icon-bar{margin-top:4px}#o_navbar_left-toggle{float:left}#o_navbar_right-toggle{float:right}.o_navbar-nav{margin:7.5px -15px}.o_navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}.o_collapse .o_navbar-nav{float:left;margin:0}.o_collapse .o_navbar-nav>li{float:left}.o_collapse .o_navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.o_collapse .o_navbar-nav.o_navbar-right:last-child{margin-right:-15px}.o_collapse.o_navbar-collapse .o_navbar-left{float:left !important}.o_collapse.o_navbar-collapse .o_navbar-right{float:right !important}.o_navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);margin-top:8px;margin-bottom:8px}@media (max-width: 767px){.o_navbar-form .form-group{margin-bottom:5px}}
 .o_collapse .o_navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.o_collapse .o_navbar-form.o_navbar-right:last-child{margin-right:-15px}.o_navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.o_navbar-fixed-bottom .o_navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.o_navbar-btn{margin-top:8px;margin-bottom:8px}.o_navbar-btn.btn-sm,.btn-group-sm>.o_navbar-btn.btn,.btn-group-sm>a.o_navbar-btn.o_chelp{margin-top:10px;margin-bottom:10px}.o_navbar-btn.btn-xs,.btn-group-xs>.o_navbar-btn.btn,.btn-group-xs>a.o_navbar-btn.o_chelp{margin-top:14px;margin-bottom:14px}.o_navbar-text{margin-top:15px;margin-bottom:15px}.o_collapse .o_navbar-text{float:left;margin-left:15px;margin-right:15px}.o_collapse .o_navbar-text.o_navbar-right:last-child{margin-right:0}.o_navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.o_navbar-default .o_navbar-brand{color:#777}.o_navbar-default .o_navbar-brand:hover,.o_navbar-default .o_navbar-brand:focus{color:#5e5e5e;background-color:transparent}.o_navbar-default .o_navbar-text{color:#777}.o_navbar-default .o_navbar-nav>li>a{color:#777}.o_navbar-default .o_navbar-nav>li>a:hover,.o_navbar-default .o_navbar-nav>li>a:focus{color:#333;background-color:transparent}.o_navbar-default .o_navbar-nav>.active>a,.o_navbar-default .o_navbar-nav>.active>a:hover,.o_navbar-default .o_navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.o_navbar-default .o_navbar-nav>.disabled>a,.o_navbar-default .o_navbar-nav>.disabled>a:hover,.o_navbar-default .o_navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.o_navbar-default .o_navbar-toggle{border-color:#ddd}.o_navbar-default .o_navbar-toggle:hover,.o_navbar-default .o_navbar-toggle:focus{background-color:#ddd}.o_navbar-default .o_navbar-toggle .icon-bar{background-color:#888}.o_navbar-default .o_navbar-collapse,.o_navbar-default .o_navbar-form{border-color:#e7e7e7}.o_navbar-default .o_navbar-nav>.open>a,.o_navbar-default .o_navbar-nav>.open>a:hover,.o_navbar-default .o_navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}.o_navbar-default .o_navbar-link{color:#777}.o_navbar-default .o_navbar-link:hover{color:#333}.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>li>a{color:#777}.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>li>a:hover,.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>.active>a,.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>.active>a:hover,.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>.disabled>a,.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>.disabled>a:hover,.o_navbar-offcanvas.o_navbar-default .o_navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}.o_navbar-inverse{background-color:#222;border-color:#090909}.o_navbar-inverse .o_navbar-brand{color:#999}.o_navbar-inverse .o_navbar-brand:hover,.o_navbar-inverse .o_navbar-brand:focus{color:#fff;background-color:transparent}.o_navbar-inverse .o_navbar-text{color:#999}.o_navbar-inverse .o_navbar-nav>li>a{color:#999}.o_navbar-inverse .o_navbar-nav>li>a:hover,.o_navbar-inverse .o_navbar-nav>li>a:focus{color:#fff;background-color:transparent}.o_navbar-inverse .o_navbar-nav>.active>a,.o_navbar-inverse .o_navbar-nav>.active>a:hover,.o_navbar-inverse .o_navbar-nav>.active>a:focus{color:#fff;background-color:#090909}.o_navbar-inverse .o_navbar-nav>.disabled>a,.o_navbar-inverse .o_navbar-nav>.disabled>a:hover,.o_navbar-inverse .o_navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.o_navbar-inverse .o_navbar-toggle{border-color:#333}.o_navbar-inverse .o_navbar-toggle:hover,.o_navbar-inverse .o_navbar-toggle:focus{background-color:#333}.o_navbar-inverse .o_navbar-toggle .icon-bar{background-color:#fff}.o_navbar-inverse .o_navbar-collapse,.o_navbar-inverse .o_navbar-form{border-color:#101010}.o_navbar-inverse .o_navbar-nav>.open>a,.o_navbar-inverse .o_navbar-nav>.open>a:hover,.o_navbar-inverse .o_navbar-nav>.open>a:focus{background-color:#090909;color:#fff}.o_navbar-inverse .o_navbar-nav .o_navbar-link{color:#999}.o_navbar-inverse .o_navbar-nav .o_navbar-link:hover{color:#fff}.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#090909}.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu .divider{background-color:#090909}.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>li>a{color:#999}.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>li>a:hover,.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.active>a,.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.active>a:hover,.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#090909}.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.disabled>a,.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.disabled>a:hover,.o_navbar-inverse .o_navbar-offcanvas.o_navbar-inverse .o_navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}.o_toolbar{text-align:center;min-height:30px}.o_toolbar .o_breadcrumb{margin-top:4px;margin-bottom:2px;padding-right:5px;padding-left:5px;padding-top:3px;border-right:1px solid #e7e7e7;margin-right:15px;margin-left:-15px}.o_toolbar .o_breadcrumb i{font-size:18px}.o_toolbar .o_breadcrumb .o_history.o_tool_dropdown i{font-size:14px}@media (min-width: 767px) and (max-width: 991px){.o_toolbar .o_breadcrumb{margin-top:3px;margin-bottom:2px;padding-top:3px}.o_toolbar .o_breadcrumb i{font-size:16px}.o_toolbar .o_breadcrumb .o_history.o_tool_dropdown i{font-size:12px}}@media (max-width: 767px){.o_toolbar .o_breadcrumb{margin-top:6px;margin-bottom:4px;padding-top:0}.o_toolbar .o_breadcrumb i{font-size:20px}.o_toolbar .o_breadcrumb .o_history{display:none}}.o_toolbar .o_tools{margin-top:8px;margin-bottom:5px}.o_toolbar .o_tool,.o_toolbar .o_text{position:relative;margin:0 10px}.o_toolbar .o_tool a i,.o_toolbar .o_tool .o_disabled i,.o_toolbar .o_text a i,.o_toolbar .o_text .o_disabled i{font-size:18px}.o_toolbar .o_tool a span,.o_toolbar .o_tool .o_disabled span,.o_toolbar .o_text a span,.o_toolbar .o_text .o_disabled span{display:block;font-size:12px}.o_toolbar .o_tool a span.badge,.o_toolbar .o_tool .o_disabled span.badge,.o_toolbar .o_text a span.badge,.o_toolbar .o_text .o_disabled span.badge{position:absolute;right:50%;top:-24px;margin-right:-12px;font-size:13px}@media (min-width: 767px) and (max-width: 991px){.o_toolbar .o_tool a i,.o_toolbar .o_tool .o_disabled i,.o_toolbar .o_text a i,.o_toolbar .o_text .o_disabled i{font-size:16px}.o_toolbar .o_tool a span,.o_toolbar .o_tool .o_disabled span,.o_toolbar .o_text a span,.o_toolbar .o_text .o_disabled span{font-size:11px}.o_toolbar .o_tool a span.badge,.o_toolbar .o_tool .o_disabled span.badge,.o_toolbar .o_text a span.badge,.o_toolbar .o_text .o_disabled span.badge{top:-22px;margin-right:-11px;font-size:12px}}@media (max-width: 767px){.o_toolbar .o_tool a i,.o_toolbar .o_tool .o_disabled i,.o_toolbar .o_text a i,.o_toolbar .o_text .o_disabled i{font-size:20px}.o_toolbar .o_tool a span,.o_toolbar .o_tool .o_disabled span,.o_toolbar .o_text a span,.o_toolbar .o_text .o_disabled span{display:none}.o_toolbar .o_tool a span.badge,.o_toolbar .o_tool .o_disabled span.badge,.o_toolbar .o_text a span.badge,.o_toolbar .o_text .o_disabled span.badge{display:block;position:relative;top:0;left:0}}.o_toolbar .o_tool_dropdown{position:relative}.o_toolbar .o_tool_dropdown a.dropdown-toggle i{font-size:18px}.o_toolbar .o_tool_dropdown a.dropdown-toggle span{display:block;font-size:12px}.o_toolbar .o_tool_dropdown a.dropdown-toggle .o_icon_caret{position:absolute;right:50%;top:4px;margin-right:-20px;font-size:14px}@media (min-width: 767px) and (max-width: 991px){.o_toolbar .o_tool_dropdown a.dropdown-toggle i{font-size:16px}.o_toolbar .o_tool_dropdown a.dropdown-toggle span,.o_toolbar .o_tool_dropdown a.dropdown-toggle .o_icon_caret{font-size:11px}.o_toolbar .o_tool_dropdown a.dropdown-toggle .o_icon_caret{top:4px;margin-right:-18px;font-size:12px}}@media (max-width: 767px){.o_toolbar .o_tool_dropdown a.dropdown-toggle i{font-size:20px}.o_toolbar .o_tool_dropdown a.dropdown-toggle span,.o_toolbar .o_tool_dropdown a.dropdown-toggle .o_icon_caret{display:none}}.o_toolbar .o_tool_dropdown .dropdown-menu{text-align:left}@media (max-width: 991px){.o_toolbar{min-height:23px}.o_toolbar .o_tools{margin-top:6px;margin-bottom:4px}}@media (max-width: 767px){.o_toolbar{min-height:20px;text-align:left}.o_toolbar .o_tools{margin-top:6px;margin-bottom:4px}}
-body{overflow-x:hidden}.o_container_offcanvas{position:relative;max-width:1324px;-webkit-transition:all .25s ease-in-out;-moz-transition:all .25s ease-in-out;-o-transition:all .25s ease-in-out;-m-transition:all .25s ease-in-out;transition:all .25s ease-in-out}@media screen and (min-width: 1324px) and (max-width: 1574px){body.o_offcanvas_right_visible .o_container_offcanvas{left:-125px;max-width:1074px}}@media screen and (min-width: 1574px) and (max-width: 1824px){body.o_offcanvas_right_visible .o_container_offcanvas{left:-125px}}#o_offcanvas_right{position:absolute;top:0;right:-250px;width:250px;padding:15px 15px;background-color:#222;color:#999;border:1px solid #090909;-webkit-box-shadow:0px 0px 4px 3px rgba(0,0,0,0.25);box-shadow:0px 0px 4px 3px rgba(0,0,0,0.25);min-height:100%;z-index:10;display:none}#o_offcanvas_right:before,#o_offcanvas_right:after{content:" ";display:table}#o_offcanvas_right:after{clear:both}@media screen and (max-width: 767px){.row-offcanvas{position:relative;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;transition:all .25s ease-out}.row-offcanvas-right{right:0}.row-offcanvas-right .sidebar-offcanvas{right:-50%}.row-offcanvas-right.active{right:50%}.row-offcanvas-left{left:0}.row-offcanvas-left .sidebar-offcanvas{left:-50%}.row-offcanvas-left.active{left:50%}.sidebar-offcanvas{position:absolute;top:0;width:50%}}div.o_callout_overlay{position:fixed;top:0;left:0;width:100%;height:100%;zoom:1;background:#000;zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=1);-moz-opacity:0.01;-khtml-opacity:0.01;opacity:0.01}.o_alert_info{position:fixed;top:-100%;left:0;display:none;z-index:2000;width:100%;text-align:center}.o_alert_info .alert{margin:0px auto;text-align:left;-webkit-box-shadow:0px 1px 5px -1px rgba(0,0,0,0.15);box-shadow:0px 1px 5px -1px rgba(0,0,0,0.15)}.o_alert_info .alert .o_icon_close{float:right;color:#999}.o_alert_info .alert .o_icon_close:hover{color:#555}.o_tree{position:relative;display:block;background-color:none;border:1px solid #ddd;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;overflow:hidden;font-size:14px}.o_tree a{color:#777;background-color:none}.o_tree a:hover,.o_tree a:focus{color:#333;background-color:#f8f8f8}.o_tree ul{margin:0;padding:0;list-style-type:none}.o_tree ul li{margin:0;padding:0;white-space:nowrap}.o_tree ul li div{position:relative;margin-bottom:-1px;border-bottom:1px solid #ddd}.o_tree ul li div a.o_tree_oc_l0{position:absolute;top:10px;left:-4px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l0,.o_tree ul .o_tree_level_close.b_tree_oc_l0{z-index:10}.o_tree ul li div a.o_tree_oc_l1{position:absolute;top:10px;left:11px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l1,.o_tree ul .o_tree_level_close.b_tree_oc_l1{z-index:10}.o_tree ul li div a.o_tree_oc_l2{position:absolute;top:10px;left:26px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l2,.o_tree ul .o_tree_level_close.b_tree_oc_l2{z-index:10}.o_tree ul li div a.o_tree_oc_l3{position:absolute;top:10px;left:41px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l3,.o_tree ul .o_tree_level_close.b_tree_oc_l3{z-index:10}.o_tree ul li div a.o_tree_oc_l4{position:absolute;top:10px;left:56px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l4,.o_tree ul .o_tree_level_close.b_tree_oc_l4{z-index:10}.o_tree ul li div a.o_tree_oc_l5{position:absolute;top:10px;left:71px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l5,.o_tree ul .o_tree_level_close.b_tree_oc_l5{z-index:10}.o_tree ul li div a.o_tree_oc_l6{position:absolute;top:10px;left:86px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l6,.o_tree ul .o_tree_level_close.b_tree_oc_l6{z-index:10}.o_tree ul li div a.o_tree_oc_l7{position:absolute;top:10px;left:101px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l7,.o_tree ul .o_tree_level_close.b_tree_oc_l7{z-index:10}.o_tree ul li div a.o_tree_oc_l8{position:absolute;top:10px;left:116px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l8,.o_tree ul .o_tree_level_close.b_tree_oc_l8{z-index:10}.o_tree ul li div a.o_tree_oc_l9{position:absolute;top:10px;left:131px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l9,.o_tree ul .o_tree_level_close.b_tree_oc_l9{z-index:10}.o_tree ul li div a.o_tree_oc_l10{position:absolute;top:10px;left:146px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l10,.o_tree ul .o_tree_level_close.b_tree_oc_l10{z-index:10}.o_tree ul li div a.o_tree_oc_l11{position:absolute;top:10px;left:161px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l11,.o_tree ul .o_tree_level_close.b_tree_oc_l11{z-index:10}.o_tree ul li div a.o_tree_l0{display:block;padding:10px 2px 10px 10px;z-index:9}.o_tree ul li div a.o_tree_l1{display:block;padding:10px 2px 10px 25px;z-index:9}.o_tree ul li div a.o_tree_l2{display:block;padding:10px 2px 10px 40px;z-index:9}.o_tree ul li div a.o_tree_l3{display:block;padding:10px 2px 10px 55px;z-index:9}.o_tree ul li div a.o_tree_l4{display:block;padding:10px 2px 10px 70px;z-index:9}.o_tree ul li div a.o_tree_l5{display:block;padding:10px 2px 10px 85px;z-index:9}.o_tree ul li div a.o_tree_l6{display:block;padding:10px 2px 10px 100px;z-index:9}.o_tree ul li div a.o_tree_l7{display:block;padding:10px 2px 10px 115px;z-index:9}.o_tree ul li div a.o_tree_l8{display:block;padding:10px 2px 10px 130px;z-index:9}.o_tree ul li div a.o_tree_l9{display:block;padding:10px 2px 10px 145px;z-index:9}.o_tree ul li div a.o_tree_l10{display:block;padding:10px 2px 10px 160px;z-index:9}.o_tree ul li div a.o_tree_l11{display:block;padding:10px 2px 10px 175px;z-index:9}.o_tree ul span.o_tree_leaf{display:none}.o_tree ul li .badge{float:right;font-size:70%}.o_tree ul li div.o_dnd_sibling{margin:0;padding:0;border-bottom:none}.o_tree ul li a.active{color:#428bca;background-color:none;font-weight:bold}.o_tree ul li a.active:hover,.o_tree ul li a.active:focus{color:#2a6496;background-color:#eee}.o_tree ul li a.active_parent{color:#777;font-weight:bold}.o_tree ul li a.active_parent:hover,.o_tree ul li a.active_parent:focus{color:#333}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l0{left:6px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l1{left:21px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l2{left:36px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l3{left:51px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l4{left:66px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l5{left:81px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l6{left:96px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l7{left:111px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l8{left:126px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l9{left:141px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l10{left:156px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l11{left:171px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l0{padding:10px 2px 10px 20px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l1{padding:10px 2px 10px 35px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l2{padding:10px 2px 10px 50px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l3{padding:10px 2px 10px 65px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l4{padding:10px 2px 10px 80px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l5{padding:10px 2px 10px 95px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l6{padding:10px 2px 10px 110px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l7{padding:10px 2px 10px 125px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l8{padding:10px 2px 10px 140px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l9{padding:10px 2px 10px 155px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l10{padding:10px 2px 10px 170px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l11{padding:10px 2px 10px 185px}.o_tree .o_dnd_item{cursor:move;z-index:100}.o_tree .o_dnd_proxy{zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=40);-moz-opacity:0.4;-khtml-opacity:0.4;opacity:0.4;background-color:yellow}.o_tree .o_dnd_item.o_dnd_over{background-color:#ffff60}.o_tree .o_dnd_sibling{height:3px;width:100%}.o_tree .o_dnd_sibling.o_dnd_over{background:transparent url(../openolat/images/arrow_dd.png) top left no-repeat}.o_tree .o_dnd_l1{margin-left:0 !important}.o_tree .o_dnd_l2{margin-left:1em !important}.o_tree .o_dnd_l3{margin-left:2em !important}.o_tree .o_dnd_l4{margin-left:3em !important}.o_tree .o_dnd_l5{margin-left:4em !important}.o_tree .o_dnd_l6{margin-left:5em !important}.o_tree .o_dnd_l7{margin-left:6em !important}.o_tree .o_dnd_l8{margin-left:7em !important}.o_tree .o_dnd_l9{margin-left:8em !important}.o_tree .o_dnd_l10{margin-left:9em !important}.o_tree .o_dnd_l11{margin-left:10em !important}.o_offcanvas .o_tree{border:0}.o_breadcrumb{position:relative}.o_breadcrumb .o_breadcrumb_close{float:right}.o_form .o_icon_mandatory{position:absolute;right:-0.25em;line-height:1.5em}.o_form.form-horizontal .o_icon_mandatory{position:relative;right:0;line-height:inherit;margin-left:0.25em}.o_form .o_error{margin-top:1px;margin-bottom:0;padding:10px}.o_form .o_picker_wrapper{position:absolute;top:0;right:0;height:34px;width:34px;text-align:right;vertical-align:middle;line-height:34px;font-size:22px;color:#428bca}.o_form .o_picker_wrapper:hover{color:#2a6496}.o_form .o_date{position:relative;padding-right:34px}.o_form input.o_date_ms{width:3em}.o_form .o_date_ms.form-group{margin-left:25px}.o_form .input-group.o_date_picker{width:16em}.o_form .o_filepreview{margin-bottom:10px}.o_form .o_fileinput{cursor:pointer;position:relative}.o_form .o_fileinput .o_fakechooser{position:relative;padding-right:34px;z-index:1}.o_form .o_fileinput .o_realchooser{position:absolute;top:0;left:0;z-index:2;zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity:0;opacity:0}.o_catalog .o_catalog_delete_img{position:relative;top:-0.5em}.o_button_toggle{border:1px solid #999;border-top-right-radius:9px;border-top-left-radius:9px;border-bottom-right-radius:9px;border-bottom-left-radius:9px;background:#eee;display:inline-block;height:18px;line-height:16px;font-size:16px;text-align:left;padding:0 0.5em 0 0;margin:0}.o_button_toggle i{color:#999;text-shadow:1px 0 2px rgba(0,0,0,0.25)}.o_button_toggle span{line-height:16px;vertical-align:top;font-size:60%;text-transform:uppercase}.o_button_toggle.o_on{text-align:right;padding:0 0 0 0.5em}.o_button_toggle.o_on i{color:#428bca;text-shadow:-1px 0 2px rgba(0,0,0,0.25)}.o_table_wrapper.o_table_flexi .o_table_body{margin-top:20px}.o_table_wrapper.o_table_flexi .table{margin-top:20px}.o_table_wrapper.o_table_flexi .table td ul{margin:0}.o_table_wrapper .o_table_search{max-width:50em}.o_table_wrapper .o_table_footer .o_table_pagination{text-align:center}.o_table_wrapper .o_row_selected td{background-color:pink !important}.o_table_wrapper a.b_sorting{padding:0 20px 0 0;text-decoration:none;background:url("../openolat/images/arrow-resize-090.png") no-repeat center right}.o_table_wrapper a.b_sorting_asc{padding:0 20px 0 0;text-decoration:none;background:url("../openolat/images/arrow_up.png") no-repeat center right}.o_table_wrapper a.b_sorting_desc{padding:0 20px 0 0;text-decoration:none;background:url("../openolat/images/arrow_down.png") no-repeat center right}.o_table_wrapper .o_table{margin-bottom:0}.o_table_wrapper .dataTables_info{padding:5px 10px 5px 0}.o_table_buttons{text-align:center}.o_table_buttons input{margin-right:1em}.o_table_buttons input:last-child{margin-right:0}.o_table_tools{margin-left:0.5em}.o_table_count{max-width:20em;float:left;padding:0 15px}.o_info .table-bordered td,.o_note .table-bordered td,.o_form .o_desc .table-bordered td,.o_course_run .o_statusinfo .table-bordered td,.o_course_stats .o_desc .table-bordered td,.o_important .table-bordered td,.o_bc_empty .table-bordered td,.o_course_run .o_no_scoreinfo .table-bordered td,.o_success .table-bordered td,.o_warning .table-bordered td,.o_error .table-bordered td,.o_togglebox_wrapper div.o_togglebox_content .table-bordered td,div.o_qti_item_itemfeedback .table-bordered td,o_note .table-bordered td,o_important .table-bordered td,o_warning .table-bordered td,o_error .table-bordered td{border-color:#333}.panel .o_table_layout{border-top:1px solid #ddd;padding-top:6px}.panel .o_table_count{padding:0 15px}#o_navbar_imclient #o_im_message,#o_navbar_imclient #o_im_status,#o_navbar_imclient #o_im_summary{position:relative;padding:15px 3px}#o_navbar_imclient #o_im_summary{padding-right:15px}#o_navbar_imclient #o_im_status div.o_chelp_wrapper{right:0.5em}.o_flag{position:relative;top:1px;display:inline-block;line-height:1;width:16px;height:16px;background-repeat:no-repeat;background-position:0 100%}option.o_with_flag{padding-left:23px;min-height:16px;background-repeat:no-repeat;background-position:2px 50%}.o_flag_en{background-image:url("../light/images/flags/gb.png")}.o_flag_de{background-image:url("../light/images/flags/de.png")}.o_flag_fr{background-image:url("../light/images/flags/fr.png")}.o_flag_it{background-image:url("../light/images/flags/it.png")}.o_flag_es{background-image:url("../light/images/flags/es.png")}.o_flag_da{background-image:url("../light/images/flags/dk.png")}.o_flag_cs{background-image:url("../light/images/flags/cz.png")}.o_flag_el{background-image:url("../light/images/flags/gr.png")}.o_flag_ee{background-image:url("../light/images/flags/ee.png")}.o_flag_ru{background-image:url("../light/images/flags/ru.png")}.o_flag_pl{background-image:url("../light/images/flags/pl.png")}.o_flag_zh_CN{background-image:url("../light/images/flags/cn.png")}.o_flag_zh_TW{background-image:url("../light/images/flags/tw.png")}.o_flag_lt{background-image:url("../light/images/flags/lt.png")}.o_flag_fa{background-image:url("../light/images/flags/ir.png")}.o_flag_pt_PT{background-image:url("../light/images/flags/pt.png")}.o_flag_pt_BR{background-image:url("../light/images/flags/br.png")}.o_flag_tr{background-image:url("../light/images/flags/tr.png")}.o_flag_hu{background-image:url("../light/images/flags/hu.png")}.o_flag_sq{background-image:url("../light/images/flags/al.png")}.o_flag_in{background-image:url("../light/images/flags/id.png")}.o_flag_ar{background-image:url("../light/images/flags/eg.png")}.o_flag_rm{background-image:url("../light/images/flags/rm.png")}.o_flag_af{background-image:url("../light/images/flags/za.png")}.o_flag_vi{background-image:url("../light/images/flags/vn.png")}.o_flag_mn{background-image:url("../light/images/flags/mn.png")}.o_flag_iw{background-image:url("../light/images/flags/il.png")}.o_flag_ko{background-image:url("../light/images/flags/kr.png")}.o_flag_nl_NL{background-image:url("../light/images/flags/nl.png")}.o_flag_jp{background-image:url("../light/images/flags/jp.png")}.o_flag_nb_NO{background-image:url("../light/images/flags/no.png")}.o_flag_et_EE{background-image:url("../light/images/flags/ee.png")}.o_flag_bg{background-image:url("../light/images/flags/bg.png")}.o_flag_hi_IN_ASIA{background-image:url("../light/images/flags/in.png")}.o_flag_ar_LB{background-image:url("../light/images/flags/lb.png")}.o_flag_gl_ES{background-image:url("../light/images/flags/galicia.png")}.o_rating .o_rating_title{font-size:12px}.o_rating .o_rating_items{white-space:nowrap}.o_rating .o_rating_items .o_icon,.o_rating .o_rating_items a.o_link_extern,.o_rating .o_rating_items a.o_link_mailto{color:#f0ad4e}.o_rating .o_rating_items .o_icon:hover,.o_rating .o_rating_items a.o_link_extern:hover,.o_rating .o_rating_items a.o_link_mailto:hover{color:#428bca}.o_rating .o_rating_items .o_legend{margin-left:1em;font-size:12px;line-height:1em}.o_rating .o_rating_explanation{font-size:12px}@media (max-width: 991px){.o_rating .o_rating_title,.o_rating .o_rating_explanation{display:none}}
+body{overflow-x:hidden}.o_container_offcanvas{position:relative;max-width:1324px;-webkit-transition:all .25s ease-in-out;-moz-transition:all .25s ease-in-out;-o-transition:all .25s ease-in-out;-m-transition:all .25s ease-in-out;transition:all .25s ease-in-out}@media screen and (min-width: 1324px) and (max-width: 1574px){body.o_offcanvas_right_visible .o_container_offcanvas{left:-125px;max-width:1074px}}@media screen and (min-width: 1574px) and (max-width: 1824px){body.o_offcanvas_right_visible .o_container_offcanvas{left:-125px}}#o_offcanvas_right{position:absolute;top:0;right:-250px;width:250px;padding:15px 15px;background-color:#222;color:#999;border:1px solid #090909;-webkit-box-shadow:0px 0px 4px 3px rgba(0,0,0,0.25);box-shadow:0px 0px 4px 3px rgba(0,0,0,0.25);min-height:100%;z-index:10;display:none}#o_offcanvas_right:before,#o_offcanvas_right:after{content:" ";display:table}#o_offcanvas_right:after{clear:both}@media screen and (max-width: 767px){.row-offcanvas{position:relative;-webkit-transition:all .25s ease-out;-moz-transition:all .25s ease-out;transition:all .25s ease-out}.row-offcanvas-right{right:0}.row-offcanvas-right .sidebar-offcanvas{right:-50%}.row-offcanvas-right.active{right:50%}.row-offcanvas-left{left:0}.row-offcanvas-left .sidebar-offcanvas{left:-50%}.row-offcanvas-left.active{left:50%}.sidebar-offcanvas{position:absolute;top:0;width:50%}}div.o_callout_overlay{position:fixed;top:0;left:0;width:100%;height:100%;zoom:1;background:#000;zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=1);-moz-opacity:0.01;-khtml-opacity:0.01;opacity:0.01}.o_alert_info{position:fixed;top:-100%;left:0;display:none;z-index:2000;width:100%;text-align:center}.o_alert_info .alert{margin:0px auto;text-align:left;-webkit-box-shadow:0px 1px 5px -1px rgba(0,0,0,0.15);box-shadow:0px 1px 5px -1px rgba(0,0,0,0.15)}.o_alert_info .alert .o_icon_close{float:right;color:#999}.o_alert_info .alert .o_icon_close:hover{color:#555}.o_tree{position:relative;display:block;background-color:none;border:1px solid #ddd;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;overflow:hidden;font-size:14px}.o_tree a{color:#777;background-color:none}.o_tree a:hover,.o_tree a:focus{color:#333;background-color:#f8f8f8}.o_tree ul{margin:0;padding:0;list-style-type:none}.o_tree ul li{margin:0;padding:0;white-space:nowrap}.o_tree ul li div{position:relative;margin-bottom:-1px;border-bottom:1px solid #ddd}.o_tree ul li div a.o_tree_oc_l0{position:absolute;top:10px;left:-4px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l0,.o_tree ul .o_tree_level_close.b_tree_oc_l0{z-index:10}.o_tree ul li div a.o_tree_oc_l1{position:absolute;top:10px;left:11px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l1,.o_tree ul .o_tree_level_close.b_tree_oc_l1{z-index:10}.o_tree ul li div a.o_tree_oc_l2{position:absolute;top:10px;left:26px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l2,.o_tree ul .o_tree_level_close.b_tree_oc_l2{z-index:10}.o_tree ul li div a.o_tree_oc_l3{position:absolute;top:10px;left:41px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l3,.o_tree ul .o_tree_level_close.b_tree_oc_l3{z-index:10}.o_tree ul li div a.o_tree_oc_l4{position:absolute;top:10px;left:56px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l4,.o_tree ul .o_tree_level_close.b_tree_oc_l4{z-index:10}.o_tree ul li div a.o_tree_oc_l5{position:absolute;top:10px;left:71px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l5,.o_tree ul .o_tree_level_close.b_tree_oc_l5{z-index:10}.o_tree ul li div a.o_tree_oc_l6{position:absolute;top:10px;left:86px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l6,.o_tree ul .o_tree_level_close.b_tree_oc_l6{z-index:10}.o_tree ul li div a.o_tree_oc_l7{position:absolute;top:10px;left:101px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l7,.o_tree ul .o_tree_level_close.b_tree_oc_l7{z-index:10}.o_tree ul li div a.o_tree_oc_l8{position:absolute;top:10px;left:116px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l8,.o_tree ul .o_tree_level_close.b_tree_oc_l8{z-index:10}.o_tree ul li div a.o_tree_oc_l9{position:absolute;top:10px;left:131px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l9,.o_tree ul .o_tree_level_close.b_tree_oc_l9{z-index:10}.o_tree ul li div a.o_tree_oc_l10{position:absolute;top:10px;left:146px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l10,.o_tree ul .o_tree_level_close.b_tree_oc_l10{z-index:10}.o_tree ul li div a.o_tree_oc_l11{position:absolute;top:10px;left:161px;z-index:9}.o_tree ul .o_tree_level_open.b_tree_oc_l11,.o_tree ul .o_tree_level_close.b_tree_oc_l11{z-index:10}.o_tree ul li div a.o_tree_l0{display:block;padding:10px 2px 10px 10px;z-index:9}.o_tree ul li div a.o_tree_l1{display:block;padding:10px 2px 10px 25px;z-index:9}.o_tree ul li div a.o_tree_l2{display:block;padding:10px 2px 10px 40px;z-index:9}.o_tree ul li div a.o_tree_l3{display:block;padding:10px 2px 10px 55px;z-index:9}.o_tree ul li div a.o_tree_l4{display:block;padding:10px 2px 10px 70px;z-index:9}.o_tree ul li div a.o_tree_l5{display:block;padding:10px 2px 10px 85px;z-index:9}.o_tree ul li div a.o_tree_l6{display:block;padding:10px 2px 10px 100px;z-index:9}.o_tree ul li div a.o_tree_l7{display:block;padding:10px 2px 10px 115px;z-index:9}.o_tree ul li div a.o_tree_l8{display:block;padding:10px 2px 10px 130px;z-index:9}.o_tree ul li div a.o_tree_l9{display:block;padding:10px 2px 10px 145px;z-index:9}.o_tree ul li div a.o_tree_l10{display:block;padding:10px 2px 10px 160px;z-index:9}.o_tree ul li div a.o_tree_l11{display:block;padding:10px 2px 10px 175px;z-index:9}.o_tree ul span.o_tree_leaf{display:none}.o_tree ul li .badge{float:right;font-size:70%}.o_tree ul li div.o_dnd_sibling{margin:0;padding:0;border-bottom:none}.o_tree ul li a.active{color:#428bca;background-color:none;font-weight:bold}.o_tree ul li a.active:hover,.o_tree ul li a.active:focus{color:#2a6496;background-color:#eee}.o_tree ul li a.active_parent{color:#777;font-weight:bold}.o_tree ul li a.active_parent:hover,.o_tree ul li a.active_parent:focus{color:#333}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l0{left:6px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l1{left:21px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l2{left:36px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l3{left:51px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l4{left:66px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l5{left:81px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l6{left:96px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l7{left:111px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l8{left:126px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l9{left:141px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l10{left:156px}.o_tree.o_tree_root_hidden ul li div a.o_tree_oc_l11{left:171px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l0{padding:10px 2px 10px 20px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l1{padding:10px 2px 10px 35px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l2{padding:10px 2px 10px 50px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l3{padding:10px 2px 10px 65px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l4{padding:10px 2px 10px 80px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l5{padding:10px 2px 10px 95px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l6{padding:10px 2px 10px 110px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l7{padding:10px 2px 10px 125px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l8{padding:10px 2px 10px 140px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l9{padding:10px 2px 10px 155px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l10{padding:10px 2px 10px 170px}.o_tree.o_tree_root_hidden ul li div a.o_tree_l11{padding:10px 2px 10px 185px}.o_tree .o_dnd_item{cursor:move;z-index:100}.o_tree .o_dnd_proxy{zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=40);-moz-opacity:0.4;-khtml-opacity:0.4;opacity:0.4;background-color:yellow}.o_tree .o_dnd_item.o_dnd_over{background-color:#ffff60}.o_tree .o_dnd_sibling{height:3px;width:100%}.o_tree .o_dnd_sibling.o_dnd_over{background:transparent url(../openolat/images/arrow_dd.png) top left no-repeat}.o_tree .o_dnd_l1{margin-left:0 !important}.o_tree .o_dnd_l2{margin-left:1em !important}.o_tree .o_dnd_l3{margin-left:2em !important}.o_tree .o_dnd_l4{margin-left:3em !important}.o_tree .o_dnd_l5{margin-left:4em !important}.o_tree .o_dnd_l6{margin-left:5em !important}.o_tree .o_dnd_l7{margin-left:6em !important}.o_tree .o_dnd_l8{margin-left:7em !important}.o_tree .o_dnd_l9{margin-left:8em !important}.o_tree .o_dnd_l10{margin-left:9em !important}.o_tree .o_dnd_l11{margin-left:10em !important}.o_offcanvas .o_tree{border:0}.o_breadcrumb{position:relative}.o_breadcrumb .o_breadcrumb_close{float:right}.o_form .o_icon_mandatory{position:absolute;right:-0.25em;line-height:1.5em}.o_form.form-horizontal .o_icon_mandatory{position:relative;right:0;line-height:inherit;margin-left:0.25em}.o_form .o_error{margin-top:1px;margin-bottom:0;padding:10px}.o_form .o_picker_wrapper{position:absolute;top:0;right:0;height:34px;width:34px;text-align:right;vertical-align:middle;line-height:34px;font-size:22px;color:#428bca}.o_form .o_picker_wrapper:hover{color:#2a6496}.o_form .o_date{position:relative;padding-right:34px}.o_form input.o_date_ms{width:3em}.o_form .o_date_ms.form-group{margin-left:25px}.o_form .input-group.o_date_picker{width:16em}.o_form .o_filepreview{margin-bottom:10px}.o_form .o_fileinput{cursor:pointer;position:relative}.o_form .o_fileinput .o_fakechooser{position:relative;padding-right:34px;z-index:1}.o_form .o_fileinput .o_realchooser{position:absolute;top:0;left:0;z-index:2;zoom:1;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=$percent)";filter:alpha(opacity=0);-moz-opacity:0;-khtml-opacity:0;opacity:0}.o_catalog .o_catalog_delete_img{position:relative;top:-0.5em}.o_button_toggle{border:1px solid #999;border-top-right-radius:9px;border-top-left-radius:9px;border-bottom-right-radius:9px;border-bottom-left-radius:9px;background:#eee;display:inline-block;height:18px;line-height:16px;font-size:16px;text-align:left;padding:0 0.5em 0 0;margin:0}.o_button_toggle i{color:#999;text-shadow:1px 0 2px rgba(0,0,0,0.25)}.o_button_toggle span{line-height:16px;vertical-align:top;font-size:60%;text-transform:uppercase}.o_button_toggle.o_on{text-align:right;padding:0 0 0 0.5em}.o_button_toggle.o_on i{color:#428bca;text-shadow:-1px 0 2px rgba(0,0,0,0.25)}.o_table_wrapper.o_table_flexi .o_table_body{margin-top:20px}.o_table_wrapper.o_table_flexi .table{margin-top:20px}.o_table_wrapper.o_table_flexi .table td ul{margin:0}.o_table_wrapper .o_table_search{max-width:50em}.o_table_wrapper .o_table_footer .o_table_pagination{text-align:center}.o_table_wrapper .o_row_selected td{background-color:pink !important}.o_table_wrapper a.b_sorting{padding:0 20px 0 0;text-decoration:none;background:url("../openolat/images/arrow-resize-090.png") no-repeat center right}.o_table_wrapper a.b_sorting_asc{padding:0 20px 0 0;text-decoration:none;background:url("../openolat/images/arrow_up.png") no-repeat center right}.o_table_wrapper a.b_sorting_desc{padding:0 20px 0 0;text-decoration:none;background:url("../openolat/images/arrow_down.png") no-repeat center right}.o_table_wrapper .o_table{margin-bottom:0}.o_table_buttons{text-align:center}.o_table_buttons input{margin-right:1em}.o_table_buttons input:last-child{margin-right:0}.o_table_tools{margin-left:0.5em}.o_table_count{max-width:20em;float:left;padding:0 15px}.o_info .table-bordered td,.o_note .table-bordered td,.o_form .o_desc .table-bordered td,.o_course_run .o_statusinfo .table-bordered td,.o_course_stats .o_desc .table-bordered td,.o_important .table-bordered td,.o_bc_empty .table-bordered td,.o_course_run .o_no_scoreinfo .table-bordered td,.o_success .table-bordered td,.o_warning .table-bordered td,.o_error .table-bordered td,.o_togglebox_wrapper div.o_togglebox_content .table-bordered td,div.o_qti_item_itemfeedback .table-bordered td,o_note .table-bordered td,o_important .table-bordered td,o_warning .table-bordered td,o_error .table-bordered td{border-color:#333}.panel .o_table_layout{border-top:1px solid #ddd;padding-top:6px}.panel .o_table_count{padding:0 15px}#o_navbar_imclient #o_im_message,#o_navbar_imclient #o_im_status,#o_navbar_imclient #o_im_summary{position:relative;padding:15px 3px}#o_navbar_imclient #o_im_summary{padding-right:15px}#o_navbar_imclient #o_im_status div.o_chelp_wrapper{right:0.5em}.o_flag{position:relative;top:1px;display:inline-block;line-height:1;width:16px;height:16px;background-repeat:no-repeat;background-position:0 100%}option.o_with_flag{padding-left:23px;min-height:16px;background-repeat:no-repeat;background-position:2px 50%}.o_flag_en{background-image:url("../light/images/flags/gb.png")}.o_flag_de{background-image:url("../light/images/flags/de.png")}.o_flag_fr{background-image:url("../light/images/flags/fr.png")}.o_flag_it{background-image:url("../light/images/flags/it.png")}.o_flag_es{background-image:url("../light/images/flags/es.png")}.o_flag_da{background-image:url("../light/images/flags/dk.png")}.o_flag_cs{background-image:url("../light/images/flags/cz.png")}.o_flag_el{background-image:url("../light/images/flags/gr.png")}.o_flag_ee{background-image:url("../light/images/flags/ee.png")}.o_flag_ru{background-image:url("../light/images/flags/ru.png")}.o_flag_pl{background-image:url("../light/images/flags/pl.png")}.o_flag_zh_CN{background-image:url("../light/images/flags/cn.png")}.o_flag_zh_TW{background-image:url("../light/images/flags/tw.png")}.o_flag_lt{background-image:url("../light/images/flags/lt.png")}.o_flag_fa{background-image:url("../light/images/flags/ir.png")}.o_flag_pt_PT{background-image:url("../light/images/flags/pt.png")}.o_flag_pt_BR{background-image:url("../light/images/flags/br.png")}.o_flag_tr{background-image:url("../light/images/flags/tr.png")}.o_flag_hu{background-image:url("../light/images/flags/hu.png")}.o_flag_sq{background-image:url("../light/images/flags/al.png")}.o_flag_in{background-image:url("../light/images/flags/id.png")}.o_flag_ar{background-image:url("../light/images/flags/eg.png")}.o_flag_rm{background-image:url("../light/images/flags/rm.png")}.o_flag_af{background-image:url("../light/images/flags/za.png")}.o_flag_vi{background-image:url("../light/images/flags/vn.png")}.o_flag_mn{background-image:url("../light/images/flags/mn.png")}.o_flag_iw{background-image:url("../light/images/flags/il.png")}.o_flag_ko{background-image:url("../light/images/flags/kr.png")}.o_flag_nl_NL{background-image:url("../light/images/flags/nl.png")}.o_flag_jp{background-image:url("../light/images/flags/jp.png")}.o_flag_nb_NO{background-image:url("../light/images/flags/no.png")}.o_flag_et_EE{background-image:url("../light/images/flags/ee.png")}.o_flag_bg{background-image:url("../light/images/flags/bg.png")}.o_flag_hi_IN_ASIA{background-image:url("../light/images/flags/in.png")}.o_flag_ar_LB{background-image:url("../light/images/flags/lb.png")}.o_flag_gl_ES{background-image:url("../light/images/flags/galicia.png")}.o_rating .o_rating_title{font-size:12px}.o_rating .o_rating_items{white-space:nowrap}.o_rating .o_rating_items .o_icon,.o_rating .o_rating_items a.o_link_extern,.o_rating .o_rating_items a.o_link_mailto{color:#f0ad4e}.o_rating .o_rating_items .o_icon:hover,.o_rating .o_rating_items a.o_link_extern:hover,.o_rating .o_rating_items a.o_link_mailto:hover{color:#428bca}.o_rating .o_rating_items .o_legend{margin-left:1em;font-size:12px;line-height:1em}.o_rating .o_rating_explanation{font-size:12px}@media (max-width: 991px){.o_rating .o_rating_title,.o_rating .o_rating_explanation{display:none}}
 .o_comments .o_comment_wrapper .o_avatar{margin:0 1em 0 0}.o_ratings_and_comments .o_rating_wrapper{vertical-align:middle;display:inline-block}.o_ratings_and_comments a.o_comments{margin-left:10px;position:relative;top:0.1em}.d3chart .bar{shape-rendering:crispEdges}.d3chart .bar_default_light{fill:#7eb0db}.d3chart .bar_default{fill:#428bca}.d3chart .bar_default_dark{fill:#2a6496}.d3chart .axis{font:12px sans-serif}.d3chart .axis path,.d3chart .axis line{fill:none;stroke:#000;shape-rendering:crispEdges}.o_iframedisplay iframe{width:100%}.o_singlepage .o_edit{position:absolute;top:10px;right:37px}.o_content_popup{position:absolute;top:10px;right:12px}.o_module_cp_wrapper .o_tools{position:absolute;top:10px;right:12px;text-align:right;vertical-align:middle}.o_module_cp_wrapper .o_tools .o_search_wrapper{display:inline-block;position:relative;top:-2px}.o_bc_meta .o_thumbnail{width:200px;height:200px}#o_htmleditor_save{margin-top:10px;text-align:center}#o_htmleditor_save input{margin-right:1em}#o_htmleditor_save input:last-child{margin-right:0}.o_notifications_news_wrapper .o_notifications_news_subscription{margin:10px 0}.o_notifications_news_wrapper .o_notifications_news_subscription h4 i,.o_notifications_news_wrapper .o_notifications_news_subscription .o_cal .fc-header-title h2 i,.o_cal .fc-header-title .o_notifications_news_wrapper .o_notifications_news_subscription h2 i{display:none}.o_notifications_news_wrapper .o_notifications_news_subscription .o_notifications_news_content{margin-left:1.5em;position:relative}.o_notifications_news_wrapper .o_notifications_news_subscription .o_notifications_news_content .o_icon,.o_notifications_news_wrapper .o_notifications_news_subscription .o_notifications_news_content a.o_link_extern,.o_notifications_news_wrapper .o_notifications_news_subscription .o_notifications_news_content a.o_link_mailto{position:absolute;left:-1.5em;line-height:1.5em;top:0}.o_notifications_news_wrapper .o_notifications_news_subscription .o_notifications_news_url{margin-left:1.5em}.o_noti{margin:6px 0 6px 12px}.o_noti .o_label{cursor:help}@media (max-width: 767px){.o_noti .o_label span{display:none}}
 .panel-body .o_noti{margin:0}.o_datecomp{position:relative;width:40px;height:52px;border:1px solid #555;margin-right:12px;text-align:center;vertical-align:middle}.o_datecomp div.o_year{position:absolute;left:0;width:100%;top:-20px;height:20px;line-height:20px;font-size:10px}.o_datecomp div.o_month{height:20px;line-height:20px;font-size:12px}.o_datecomp div.o_day{height:30px;line-height:30px;font-size:18px;border-top:1px solid #555;background-color:#fff}.o_block_with_datecomp .o_head{position:relative;padding-left:52px}.o_block_with_datecomp .o_datecomp{position:absolute;top:0.2em;left:0}.o_block_with_datecomp .o_title{margin-top:0}.o_block_with_datecomp .o_content{border-left:5px solid #eee;padding:0 20px}.o_block_with_datecomp .o_block_footer{padding-left:25px}.o_cal_toptoolbar{margin-bottom:6px}.o_cal_toptoolbar .o_cal_toptoolbar_sub,.o_cal_toptoolbar .o_cal_toptoolbar_help{margin-right:12px}.o_feed .o_subscription a{margin-right:1.5em}.o_feed .o_subscription form{margin-top:6px}.o_feed .o_blog_posts .o_ratings_and_comments .o_rating_wrapper .o_rating_title,.o_feed .o_blog_posts .o_ratings_and_comments .o_rating_wrapper .o_rating_explanation,.o_feed .o_blog_posts .o_ratings_and_comments .o_rating_wrapper .o_legend{display:none}.o_feed .o_blog_posts .o_ratings_and_comments a.o_comments span{display:none}.o_togglebox_wrapper div.o_togglebox_content{position:relative;margin:0}.o_togglebox_wrapper div.o_togglebox_content .o_hide{position:absolute;bottom:0.5em;right:1em}.o_qrcode{width:256px;height:256px}#o_ajax_busy{position:absolute;left:50%;top:20em;margin-left:-2.5em;height:5em;width:5em;color:#fff;z-index:1201;display:none}.o_exception .o_visual{position:relative;background-image:url("../light/images/lion-500x333.jpg");filter:grayscale(50%);-webkit-filter:grayscale(50%);-moz-filter:grayscale(50%);-ms-filter:grayscale(50%);-o-filter:grayscale(50%);width:500px;height:333px;background-repeat:no-repeat;background-position:50% 50%;background-size:contain;margin:0 0 10px 16px}@media (min-width: 768px) and (max-width: 991px){.o_exception .o_visual{width:375px;height:249px}}@media (min-width: 500px) and (max-width: 767px){.o_exception .o_visual{width:250px;height:166px}}@media (max-width: 500px){.o_exception .o_visual{background-size:cover}}
 .typeahead,.tt-query,.tt-hint{width:396px;height:30px;padding:8px 12px;font-size:24px;line-height:30px;border:2px solid #ccc;-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px;outline:none}.typeahead{background-color:#fff}.typeahead:focus{border:2px solid #0097cf}.tt-query{-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.tt-hint{color:#999}.tt-dropdown-menu{width:422px;margin-top:12px;padding:8px 0;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:8px;-moz-border-radius:8px;border-radius:8px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2)}.tt-suggestion{padding:3px 20px;font-size:18px;line-height:24px}.tt-suggestion.tt-cursor{color:#fff;background-color:#0097cf}.tt-suggestion p{margin:0}.o_visual{position:absolute;top:0;left:0;overflow:hidden;height:120px;width:180px;vertical-align:middle}@media (min-width: 768px) and (max-width: 991px){.o_visual{height:80px;width:120px}}@media (max-width: 767px){.o_visual{height:50px;width:75px}}.o_visual img{width:100%;height:auto}.o_visual .o_visual_not_available{width:100%;height:100%;background-image:url("../light/images/no_preview.png");background-repeat:no-repeat;background-position:50% 50%;background-size:contain}.o_coursetable.o_rendertype_custom .o_table_row{position:relative;border:1px solid #428bca;margin-bottom:10px}.o_coursetable.o_rendertype_custom .o_table_row .o_visual{border-right:1px solid #428bca}.o_coursetable.o_rendertype_custom .o_table_row .o_access{position:absolute;top:0;right:0;height:120px;width:180px;overflow:hidden;border-left:1px solid #428bca;padding-top:0.25em}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_state,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_score{padding:0 1em;height:20px;line-height:20px;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_score{position:relative;left:2px}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_social{position:absolute;width:100%;bottom:32px;height:20px;padding-left:1em}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_social .o_rating .o_rating_title,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_social .o_rating o_rating_legend,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_social .o_rating .o_rating_explanation{display:none}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_bookings{padding:0 0 0 1em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_bookings .o_label{margin-bottom:1em}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_bookings .o_methods{color:#5bc0de}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_start,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_book,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_details{position:absolute;display:block;bottom:0;width:90px;height:30px;line-height:30px;text-align:center}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_start,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_book{right:0}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_details{right:90px}@media (min-width: 768px) and (max-width: 991px){.o_coursetable.o_rendertype_custom .o_table_row .o_access{height:80px;width:120px}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_score,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_comments,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_label{display:none}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_start,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_book,.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_details{width:60px}.o_coursetable.o_rendertype_custom .o_table_row .o_access .o_details{right:60px}}@media (max-width: 767px){.o_coursetable.o_rendertype_custom .o_table_row .o_access{display:none}}.o_coursetable.o_rendertype_custom .o_table_row .o_meta{height:120px;margin:0 180px 0 180px;position:relative;padding:1em 0.5em 0.25em 1em;overflow:hidden}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_title{margin:0;position:relative;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_title a{display:block}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_author{margin-top:0.5em;line-height:1em;font-size:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_lifecycle{position:absolute;top:5px;right:40px;font-size:90%;line-height:1em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_desc{margin-top:0.5em}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_bookmark{position:absolute;top:-1px;right:15px}@media (min-width: 768px) and (max-width: 991px){.o_coursetable.o_rendertype_custom .o_table_row .o_meta{height:80px;margin:0 120px}}@media (max-width: 767px){.o_coursetable.o_rendertype_custom .o_table_row .o_meta{height:50px;margin:0 0 0 75px;padding:0 0 0 1em}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_title{line-height:50px}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_author,.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_bookmark,.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_lifecycle,.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_desc{display:none}}.o_coursetable.o_rendertype_custom .o_table_row .o_meta .o_go_xs{position:absolute;top:0;right:0;padding:0 1em;height:50px;line-height:50px}.o_coursetable.o_rendertype_classic .o_rating_explanation{display:none}.o_coursetable.o_rendertype_classic .o_start,.o_coursetable.o_rendertype_classic .o_book{white-space:nowrap}.o_coursetable.o_rendertype_classic .o_repoentry_type{color:#555}.o_coursetable.o_rendertype_classic .o_repoentry_ac{color:#555}.o_catalog .o_level{position:relative;margin-bottom:10px;padding:0;border-top:1px solid #428bca;border-bottom:1px solid #428bca}.o_catalog .o_level .o_visual{height:180px}.o_catalog .o_level .o_meta{position:relative;min-height:180px;height:180px;overflow:hidden;margin:0 0 0 180px;padding:1em 0.5em 0.5em 2em}.o_catalog .o_level .o_meta .o_title{margin:0}.o_catalog .o_level .o_meta .o_title a{display:block}.o_catalog .o_level .o_meta .o_desc{padding:1em 0 0.5em 0}@media (min-width: 768px) and (max-width: 991px){.o_catalog .o_level .o_visual{height:120px}.o_catalog .o_level .o_meta{min-height:120px;height:120px;margin:0 0 0 120px}}@media (max-width: 767px){.o_catalog .o_level .o_visual{height:75px}.o_catalog .o_level .o_meta{min-height:75px;height:75px;margin:0 0 0 75px;padding:0 0 0 1em}.o_catalog .o_level .o_meta .o_title{line-height:75px}.o_catalog .o_level .o_meta .o_desc{display:none}}.o_catalog .o_sublevels{position:relative;margin-bottom:20px}.o_catalog .o_sublevels .o_sublevel{position:relative;margin:0 20px 20px 0;width:180px}.o_catalog .o_sublevels .o_sublevel:last-child{margin-right:0}.o_catalog .o_sublevels .o_sublevel .o_visual{border:1px solid #428bca;position:relative;height:180px}.o_catalog .o_sublevels .o_sublevel .o_meta{position:absolute;left:0;bottom:0;width:100%;border:1px solid #428bca;border-top:0;background-color:rgba(255,255,255,0.8)}.o_catalog .o_sublevels .o_sublevel .o_meta .o_title{margin:0;text-align:center;line-height:2em;height:2em;width:100%;overflow:hidden}.o_catalog .o_sublevels .o_sublevel .o_meta .o_title a{display:block}@media (min-width: 768px) and (max-width: 991px){.o_catalog .o_sublevels .o_sublevel{width:120px;margin:0 10px 10px 0}.o_catalog .o_sublevels .o_sublevel .o_visual{height:120px}.o_catalog .o_sublevels .o_sublevel .o_title{font-size:90%}}@media (max-width: 767px){.o_catalog .o_sublevels .o_sublevel{width:120px;margin:0 1px 1px 0}.o_catalog .o_sublevels .o_sublevel .o_visual{height:120px;width:120px}.o_catalog .o_sublevels .o_sublevel .o_title{font-size:90%}}