PageSourceSearch

https://emplois.truckstopquebec.com/wp-content/uploads/site-assets/fcb26537d19fb9c8627d73b0c1953346.js

js truckstopquebec.com collected 2026-10-02 06:38:59 UTC 596,926 bytes, 16,888 lines download raw bytes

vendor: 7,653 bytes, lines 1-15
1/**handles:wc-jquery-blockui,wc-add-to-cart,wc-js-cookie,woocommerce,vc_woocommerce-add-to-cart-js,vendor-dashicon-picker,noo-readmore,noo-jquery-confirm,noo-notify,location-picker,vendor-modernizr,noo-DataTables,noo-DataTables-Responsive**/
2/*!
3 * jQuery blockUI plugin
4 * Version 2.70.0-2014.11.23
5 * Requires jQuery v1.7 or later
6 *
7 * Examples at: http://malsup.com/jquery/block/
8 * Copyright (c) 2007-2013 M. Alsup
9 * Dual licensed under the MIT and GPL licenses:
10 * http://www.opensource.org/licenses/mit-license.php
11 * http://www.gnu.org/licenses/gpl.html
12 *
13 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
14 */
15!function(){"use strict";function e(e){e.fn._fadeIn=e.fn.fadeIn;var t=e.noop||function(){},o=/MSIE/.test(navigator.userAgent),n=/MSIE 6.0/.test(navigator.userAgent)&&!/MSIE 8.0/.test(navigator.userAgent),i=(document.documentMode,"function"==typeof document.createElement("div").style.setExpression&&document.createElement("div").style.setExpression);e.blockUI=function(e){d(window,e)},e.unblockUI=function(e){a(window,e)},e.growlUI=function(t,o,n,i){var s=e('<div class="growlUI"></div>');t&&s.append("<h1>"+t+"</h1>"),o&&s.append("<h2>"+o+"</h2>"),n===undefined&&(n=3e3);var l=function(t){t=t||{},e.blockUI({message:s,fadeIn:"undefined"!=typeof t.fadeIn?t.fadeIn:700,fadeOut:"undefined"!=typeof t.fadeOut?t.fadeOut:1e3,timeout:"undefined"!=typeof t.timeout?t.timeout:n,centerY:!1,showOverlay:!1,onUnblock:i,css:e.blockUI.defaults.growlCSS})};l();s.css("opacity");s.on("mouseover",function(){l({fadeIn:0,timeout:3e4});var t=e(".blockMsg");t.stop(),t.fadeTo(300,1)}).on("mouseout",function(){e(".blockMsg").fadeOut(1e3)})},e.fn.block=function(t){if(this[0]===window)return e.blockUI(t),this;var o=e.extend({},e.blockUI.defaults,t||{});return this.each(function(){var t=e(this);o.ignoreIfBlocked&&t.data("blockUI.isBlocked")||t.unblock({fadeOut:0})}),this.each(function(){"static"==e.css(this,"position")&&(this.style.position="relative",e(this).data("blockUI.static",!0)),this.style.zoom=1,d(this,t)})},e.fn.unblock=function(t){return this[0]===window?(e.unblockUI(t),this):this.each(function(){a(this,t)})},e.blockUI.version=2.7,e.blockUI.defaults={message:"<h1>Please wait...</h1>",title:null,draggable:!0,theme:!1,css:{padding:0,margin:0,width:"30%",top:"40%",left:"35%",textAlign:"center",color:"#000",border:"3px solid #aaa",backgroundColor:"#fff",cursor:"wait"},themedCSS:{width:"30%",top:"40%",left:"35%"},overlayCSS:{backgroundColor:"#000",opacity:.6,cursor:"wait"},cursorReset:"default",growlCSS:{width:"350px",top:"10px",left:"",right:"10px",border:"none",padding:"5px",opacity:.6,cursor:"default",color:"#fff",backgroundColor:"#000","-webkit-border-radius":"10px","-moz-border-radius":"10px","border-radius":"10px"},iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank",forceIframe:!1,baseZ:1e3,centerX:!0,centerY:!0,allowBodyStretch:!0,bindEvents:!0,constrainTabKey:!0,fadeIn:200,fadeOut:400,timeout:0,showOverlay:!0,focusInput:!0,focusableElements:":input:enabled:visible",onBlock:null,onUnblock:null,onOverlayClick:null,quirksmodeOffsetHack:4,blockMsgClass:"blockMsg",ignoreIfBlocked:!1};var s=null,l=[];function d(d,c){var u,b,h=d==window,k=c&&c.message!==undefined?c.message:undefined;if(!(c=e.extend({},e.blockUI.defaults,c||{})).ignoreIfBlocked||!e(d).data("blockUI.isBlocked")){if(c.overlayCSS=e.extend({},e.blockUI.defaults.overlayCSS,c.overlayCSS||{}),u=e.extend({},e.blockUI.defaults.css,c.css||{}),c.onOverlayClick&&(c.overlayCSS.cursor="pointer"),b=e.extend({},e.blockUI.defaults.themedCSS,c.themedCSS||{}),k=k===undefined?c.message:k,h&&s&&a(window,{fadeOut:0}),k&&"string"!=typeof k&&(k.parentNode||k.jquery)){var y=k.jquery?k[0]:k,m={};e(d).data("blockUI.history",m),m.el=y,m.parent=y.parentNode,m.display=y.style.display,m.position=y.style.position,m.parent&&m.parent.removeChild(y)}e(d).data("blockUI.onUnblock",c.onUnblock);var g,v,I,w,U=c.baseZ;g=o||c.forceIframe?e('<iframe class="blockUI" style="z-index:'+U+++';display:none;border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="'+c.iframeSrc+'"></iframe>'):e('<div class="blockUI" style="display:none"></div>'),v=c.theme?e('<div class="blockUI blockOverlay ui-widget-overlay" style="z-index:'+U+++';display:none"></div>'):e('<div class="blockUI blockOverlay" style="z-index:'+U+++';display:none;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>'),c.theme&&h?(w='<div class="blockUI '+c.blockMsgClass+' blockPage ui-dialog ui-widget ui-corner-all" style="z-index:'+(U+10)+';display:none;position:fixed">',c.title&&(w+='<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(c.title||"&nbsp;")+"</div>"),w+='<div class="ui-widget-content ui-dialog-content"></div>',w+="</div>"):c.theme?(w='<div class="blockUI '+c.blockMsgClass+' blockElement ui-dialog ui-widget ui-corner-all" style="z-index:'+(U+10)+';display:none;position:absolute">',c.title&&(w+='<div class="ui-widget-header ui-dialog-titlebar ui-corner-all blockTitle">'+(c.title||"&nbsp;")+"</div>"),w+='<div class="ui-widget-content ui-dialog-content"></div>',w+="</div>"):w=h?'<div class="blockUI '+c.blockMsgClass+' blockPage" style="z-index:'+(U+10)+';display:none;position:fixed"></div>':'<div class="blockUI '+c.blockMsgClass+' blockElement" style="z-index:'+(U+10)+';display:none;position:absolute"></div>',I=e(w),k&&(c.theme?(I.css(b),I.addClass("ui-widget-content")):I.css(u)),c.theme||v.css(c.overlayCSS),v.css("position",h?"fixed":"absolute"),(o||c.forceIframe)&&g.css("opacity",0);var x=[g,v,I],C=e(h?"body":d);e.each(x,function(){this.appendTo(C)}),c.theme&&c.draggable&&e.fn.draggable&&I.draggable({handle:".ui-dialog-titlebar",cancel:"li"});var S=i&&(!e.support.boxModel||e("object,embed",h?null:d).length>0);if(n||S){if(h&&c.allowBodyStretch&&e.support.boxModel&&e("html,body").css("height","100%"),(n||!e.support.boxModel)&&!h)var E=p(d,"borderTopWidth"),O=p(d,"borderLeftWidth"),T=E?"(0 - "+E+")":0,M=O?"(0 - "+O+")":0;e.each(x,function(e,t){var o=t[0].style;if(o.position="absolute",e<2)h?o.setExpression("height","Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.support.boxModel?0:"+c.quirksmodeOffsetHack+') + "px"'):o.setExpression("height",'this.parentNode.offsetHeight + "px"'),h?o.setExpression("width",'jQuery.support.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"'):o.setExpression("width",'this.parentNode.offsetWidth + "px"'),M&&o.setExpression("left",M),T&&o.setExpression("top",T);else if(c.centerY)h&&o.setExpression("top",'(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"'),o.marginTop=0;else if(!c.centerY&&h){var n="((document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "+(c.css&&c.css.top?parseInt(c.css.top,10):0)+') + "px"';o.setExpression("top",n)}})}if(k&&(c.theme?I.find(".ui-widget-content").append(k):I.append(k),(k.jquery||k.nodeType)&&e(k).show()),(o||c.forceIframe)&&c.showOverlay&&g.show(),c.fadeIn){var B=c.onBlock?c.onBlock:t,j=c.showOverlay&&!k?B:t,H=k?B:t;c.showOverlay&&v._fadeIn(c.fadeIn,j),k&&I._fadeIn(c.fadeIn,H)}else c.showOverlay&&v.show(),k&&I.show(),c.onBlock&&c.onBlock.bind(I)();if(r(1,d,c),h?(s=I[0],l=e(c.focusableElements,s),c.focusInput&&setTimeout(f,20)):function(e,t,o){var n=e.parentNode,i=e.style,s=(n.offsetWidth-e.offsetWidth)/2-p(n,"borderLeftWidth"),l=(n.offsetHeight-e.offsetHeight)/2-p(n,"borderTopWidth");
15t&&(i.left=s>0?s+"px":"0");o&&(i.top=l>0?l+"px":"0")}(I[0],c.centerX,c.centerY),c.timeout){var z=setTimeout(function(){h?e.unblockUI(c):e(d).unblock(c)},c.timeout);e(d).data("blockUI.timeout",z)}}}function a(t,o){var n,i,d=t==window,a=e(t),u=a.data("blockUI.history"),f=a.data("blockUI.timeout");f&&(clearTimeout(f),a.removeData("blockUI.timeout")),o=e.extend({},e.blockUI.defaults,o||{}),r(0,t,o),null===o.onUnblock&&(o.onUnblock=a.data("blockUI.onUnblock"),a.removeData("blockUI.onUnblock")),i=d?e(document.body).children().filter(".blockUI").add("body > .blockUI"):a.find(">.blockUI"),o.cursorReset&&(i.length>1&&(i[1].style.cursor=o.cursorReset),i.length>2&&(i[2].style.cursor=o.cursorReset)),d&&(s=l=null),o.fadeOut?(n=i.length,i.stop().fadeOut(o.fadeOut,function(){0==--n&&c(i,u,o,t)})):c(i,u,o,t)}function c(t,o,n,i){var s=e(i);if(!s.data("blockUI.isBlocked")){t.each(function(e,t){this.parentNode&&this.parentNode.removeChild(this)}),o&&o.el&&(o.el.style.display=o.display,o.el.style.position=o.position,o.el.style.cursor="default",o.parent&&o.parent.appendChild(o.el),s.removeData("blockUI.history")),s.data("blockUI.static")&&s.css("position","static"),"function"==typeof n.onUnblock&&n.onUnblock(i,n);var l=e(document.body),d=l.width(),a=l[0].style.width;l.width(d-1).width(d),l[0].style.width=a}}function r(t,o,n){var i=o==window,l=e(o);if((t||(!i||s)&&(i||l.data("blockUI.isBlocked")))&&(l.data("blockUI.isBlocked",t),i&&n.bindEvents&&(!t||n.showOverlay))){var d="mousedown mouseup keydown keypress keyup touchstart touchend touchmove";t?e(document).on(d,n,u):e(document).off(d,u)}}function u(t){if("keydown"===t.type&&t.keyCode&&9==t.keyCode&&s&&t.data.constrainTabKey){var o=l,n=!t.shiftKey&&t.target===o[o.length-1],i=t.shiftKey&&t.target===o[0];if(n||i)return setTimeout(function(){f(i)},10),!1}var d=t.data,a=e(t.target);return a.hasClass("blockOverlay")&&d.onOverlayClick&&d.onOverlayClick(t),a.parents("div."+d.blockMsgClass).length>0||0===a.parents().children().filter("div.blockUI").length}function f(e){if(l){var t=l[!0===e?l.length-1:0];t&&t.trigger("focus")}}function p(t,o){return parseInt(e.css(t,o),10)||0}}"function"==typeof define&&define.amd&&define.amd.jQuery?define(["jquery"],e):e(jQuery)}();
16jQuery(function(t){if("undefined"==typeof wc_add_to_cart_params)return!1;var a=function(){this.requests=[],this.addRequest=this.addRequest.bind(this),this.run=this.run.bind(this),this.$liveRegion=this.createLiveRegion(),t(document.body).on("click",".add_to_cart_button:not(.wc-interactive)",{addToCartHandler:this},this.onAddToCart).on("keydown",".add_to_cart_button:not(.wc-interactive)",{addToCartHandler:this},t=>{" "===t.key&&(t.preventDefault(),t.target.click())}).on("click",".remove_from_cart_button",{addToCartHandler:this},this.onRemoveFromCart).on("keydown",".remove_from_cart_button",this.onKeydownRemoveFromCart).on("added_to_cart",{addToCartHandler:this},this.onAddedToCart).on("removed_from_cart",{addToCartHandler:this},this.onRemovedFromCart).on("ajax_request_not_sent.adding_to_cart",this.updateButton)};a.prototype.addRequest=function(t){this.requests.push(t),1===this.requests.length&&this.run()},a.prototype.run=function(){var a=this,e=a.requests[0].complete;a.requests[0].complete=function(){"function"==typeof e&&e(),a.requests.shift(),a.requests.length>0&&a.run()},t.ajax(this.requests[0])},a.prototype.onAddToCart=function(a){var e=t(this);if(e.is(".ajax_add_to_cart")){if(!e.attr("data-product_id"))return!0;if(a.data.addToCartHandler.$liveRegion.text("").removeAttr("aria-relevant"),a.preventDefault(),e.removeClass("added"),e.addClass("loading"),!1===t(document.body).triggerHandler("should_send_ajax_request.adding_to_cart",[e]))return t(document.body).trigger("ajax_request_not_sent.adding_to_cart",[!1,!1,e]),!0;var r={};t.each(e.data(),function(t,a){r[t]=a}),t.each(e[0].dataset,function(t,a){r[t]=a}),t(document.body).trigger("adding_to_cart",[e,r]),a.data.addToCartHandler.addRequest({type:"POST",url:wc_add_to_cart_params.wc_ajax_url.toString().replace("%%endpoint%%","add_to_cart"),data:r,success:function(a){a&&(a.error&&a.product_url?window.location=a.product_url:"yes"!==wc_add_to_cart_params.cart_redirect_after_add?t(document.body).trigger("added_to_cart",[a.fragments,a.cart_hash,e]):window.location=wc_add_to_cart_params.cart_url)},dataType:"json"})}},a.prototype.onRemoveFromCart=function(a){var e=t(this),r=e.closest(".woocommerce-mini-cart-item");a.data.addToCartHandler.$liveRegion.text("").removeAttr("aria-relevant"),a.preventDefault(),r.block({message:null,overlayCSS:{opacity:.6}}),a.data.addToCartHandler.addRequest({type:"POST",url:wc_add_to_cart_params.wc_ajax_url.toString().replace("%%endpoint%%","remove_from_cart"),data:{cart_item_key:e.data("cart_item_key")},success:function(a){a&&a.fragments?t(document.body).trigger("removed_from_cart",[a.fragments,a.cart_hash,e]):window.location=e.attr("href")},error:function(){window.location=e.attr("href")},dataType:"json"})},a.prototype.onKeydownRemoveFromCart=function(a){" "===a.key&&(a.preventDefault(),t(this).trigger("click"))},a.prototype.updateButton=function(a,e,r,o){if(o=void 0!==o&&o){if(o.removeClass("loading"),e&&o.addClass("added"),e&&!wc_add_to_cart_params.is_cart&&0===o.parent().find(".added_to_cart").length){var d=document.createElement("a");d.href=wc_add_to_cart_params.cart_url,d.className="added_to_cart wc-forward",d.title=wc_add_to_cart_params.i18n_view_cart,d.textContent=wc_add_to_cart_params.i18n_view_cart,o.after(d)}t(document.body).trigger("wc_cart_button_updated",[o])}},a.prototype.updateFragments=function(a,e){e&&(t.each(e,function(a){t(a).addClass("updating").fadeTo("400","0.6").block({message:null,overlayCSS:{opacity:.6}})}),t.each(e,function(a,e){t(a).replaceWith(e),t(a).stop(!0).css("opacity","1").unblock()}),t(document.body).trigger("wc_fragments_loaded"))},a.prototype.alertCartUpdated=function(t,a,e,r){if(r=void 0!==r&&r){var o=r.data("success_message");if(!o)return;t.data.addToCartHandler.$liveRegion.delay(1e3).text(o).attr("aria-relevant","all")}},a.prototype.createLiveRegion=function(){var a=t(".widget_shopping_cart_live_region");
16return a.length?a:t('<div class="widget_shopping_cart_live_region screen-reader-text" role="status"></div>').appendTo("body")},a.prototype.onAddedToCart=function(t,a,e,r){t.data.addToCartHandler.updateButton(t,a,e,r),t.data.addToCartHandler.updateFragments(t,a),t.data.addToCartHandler.alertCartUpdated(t,a,e,r)},a.prototype.onRemovedFromCart=function(t,a,e,r){t.data.addToCartHandler.updateFragments(t,a),t.data.addToCartHandler.alertCartUpdated(t,a,e,r)},new a});
17/*! js-cookie v3.0.5 | MIT */
18!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)e[o]=n[o]}return e}return function t(n,o){function r(t,r,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n.write(r,t)+c}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var t=document.cookie?document.cookie.split("; "):[],o={},r=0;r<t.length;r++){var i=t[r].split("="),c=i.slice(1).join("=");try{var u=decodeURIComponent(i[0]);if(o[u]=n.read(c,u),e===u)break}catch(f){}}return e?o[e]:o}},remove:function(t,n){r(t,"",e({},n,{expires:-1}))},withAttributes:function(n){return t(this.converter,e({},this.attributes,n))},withConverter:function(n){return t(e({},this.converter,n),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(n)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"})});
19function on_keydown_remove_from_cart(e){" "===e.key&&(e.preventDefault(),e.currentTarget.click())}function focus_populate_live_region(){var e=["woocommerce-message","woocommerce-error","wc-block-components-notice-banner"].map(function(e){return"."+e+'[role="alert"]'}).join(", "),o=document.querySelectorAll(e);if(0!==o.length){var t=o[0];t.setAttribute("tabindex","-1");var n=setTimeout(function(){t.focus(),clearTimeout(n)},500)}}function refresh_sorted_by_live_region(){var e=document.querySelector(".woocommerce-result-count"),o=document.querySelector('[data-wp-interactive="woocommerce/product-filters"]');if(e&&window.location.search&&!o){var t=e.innerHTML;e.setAttribute("role","alert"),e.setAttribute("aria-hidden","true");var n=setTimeout(function(){e.setAttribute("aria-hidden","false"),e.innerHTML="",e.innerHTML=t,clearTimeout(n)},2e3)}}function on_document_ready(){focus_populate_live_region(),refresh_sorted_by_live_region()}jQuery(function(e){e(".woocommerce-ordering").on("change","select.orderby",function(){e(this).closest("form").trigger("submit")}),e("input.qty:not(.product-quantity input.qty)").each(function(){var o=parseFloat(e(this).attr("min"));o>=0&&parseFloat(e(this).val())<o&&e(this).val(o)});var o="store_notice"+(e(".woocommerce-store-notice").data("noticeId")||"");if("hidden"===Cookies.get(o))e(".woocommerce-store-notice").hide();else{function t(o){["Enter"," "].includes(o.key)&&(o.preventDefault(),e(".woocommerce-store-notice__dismiss-link").click())}e(".woocommerce-store-notice").show(),e(".woocommerce-store-notice__dismiss-link").on("click",function n(r){Cookies.set(o,"hidden",{path:"/"}),e(".woocommerce-store-notice").hide(),r.preventDefault(),e(".woocommerce-store-notice__dismiss-link").off("click",n).off("keydown",t)}).on("keydown",t)}e(".woocommerce-input-wrapper span.description").length&&e(document.body).on("click",function(){e(".woocommerce-input-wrapper span.description:visible").prop("aria-hidden",!0).slideUp(250)}),e(".woocommerce-input-wrapper").on("click",function(e){e.stopPropagation()}),e(".woocommerce-input-wrapper :input").on("keydown",function(o){var t=e(this).parent().find("span.description");if(27===o.which&&t.length&&t.is(":visible"))return t.prop("aria-hidden",!0).slideUp(250),o.preventDefault(),!1}).on("click focus",function(){var o=e(this).parent(),t=o.find("span.description");o.addClass("currentTarget"),e(".woocommerce-input-wrapper:not(.currentTarget) span.description:visible").prop("aria-hidden",!0).slideUp(250),t.length&&t.is(":hidden")&&t.prop("aria-hidden",!1).slideDown(250),o.removeClass("currentTarget")}),e.scroll_to_notices=function(o){o.length&&e("html, body").animate({scrollTop:o.offset().top-100},1e3)},e('.woocommerce form .woocommerce-Input[type="password"]').wrap('<span class="password-input"></span>'),e(".woocommerce form input").filter(":password").parent("span").addClass("password-input"),e(".password-input").each(function(){const o=e(this).find("input").attr("id"),t=e("<button>",{type:"button","class":"show-password-input","aria-label":woocommerce_params.i18n_password_show});t.attr("aria-describedby",o),e(this).append(t)}
19),e(".show-password-input").on("click",function(o){o.preventDefault(),e(this).hasClass("display-password")?(e(this).removeClass("display-password"),e(this).attr("aria-label",woocommerce_params.i18n_password_show)):(e(this).addClass("display-password"),e(this).attr("aria-label",woocommerce_params.i18n_password_hide)),e(this).hasClass("display-password")?e(this).siblings(['input[type="password"]']).prop("type","text"):e(this).siblings('input[type="text"]').prop("type","password"),e(this).siblings("input").trigger("focus")}),e("a.coming-soon-footer-banner-dismiss").on("click",function(o){var t=e(o.target);e.ajax({type:"post",url:t.data("rest-url"),data:{woocommerce_meta:{coming_soon_banner_dismissed:"yes"}},beforeSend:function(e){e.setRequestHeader("X-WP-Nonce",t.data("rest-nonce"))},complete:function(){e("#coming-soon-footer-banner").hide()}})}),"undefined"==typeof wc_add_to_cart_params&&e(document.body).on("keydown",".remove_from_cart_button",on_keydown_remove_from_cart),e(document.body).on("item_removed_from_classic_cart updated_wc_div",focus_populate_live_region)}),document.addEventListener("DOMContentLoaded",on_document_ready);
20(c=>{c(document).ready(function(){c("body").on("adding_to_cart",function(d,a,o){a&&a.hasClass("vc_gitem-link")&&a.addClass("vc-gitem-add-to-cart-loading-btn").parents(".vc_grid-item-mini").addClass("vc-woocommerce-a
20dd-to-cart-loading").append(c('<div class="vc_wc-load-add-to-loader-wrapper"><div class="vc_wc-load-add-to-loader"></div></div>'))}).on("added_to_cart",function(d,a,o,t){(t=void 0===t?c(".vc-gitem-add-to-cart-loading-btn"):t)&&t.hasClass("vc_gitem-link")&&t.removeClass("vc-gitem-add-to-cart-loading-btn").parents(".vc_grid-item-mini").removeClass("vc-woocommerce-add-to-cart-loading").find(".vc_wc-load-add-to-loader-wrapper").remove()})})})(window.jQuery);
21(n=>{n.fn.iconPicker=function(r){var r=["fas","fa"],l;function o(){"fas"==r[0]?(l=["inbox","envelope","envelope-square","envelope-open","envelope-open-text","paperclip","reply-all","reply","mail-bulk","music","film","step-backward","fast-backward","backward","play","play-circle","pause","stop","forward","fast-forward","step-forward","eject","redo","redo-alt","random","sync","sync-alt","headphones","volume-off","volume-down","volume-up","angle-double-left","angle-double-right","angle-double-up","angle-double-down","angle-left","angle-right","angle-up","angle-down","arrow-left","arrow-right","arrow-up","arrow-down","arrows-alt","arrows-alt-v","arrows-alt-h","arrow-circle-left","arrow-circle-right","arrow-circle-up","arrow-circle-down","arrow-alt-circle-down","arrow-alt-circle-up","arrow-alt-circle-right","arrow-alt-circle-left","caret-down","caret-up","caret-left","caret-right","chevron-left","chevron-right","chevron-up","chevron-down","chevron-circle-left","chevron-circle-right","chevron-circle-up","chevron-circle-down","expand","compress","hands","handshake","handshake-slash","handshake-alt-slash","hands-wash","hands-helping","hand-spock","hand-sparkles","hand-scissors","hand-rock","hand-pointer","hand-point-up","hand-point-right","hand-point-left","hand-point-down","hand-peace","hand-paper","hand-middle-finger","hand-lizard","hand-holding-water","hand-holding-usd","hand-holding-medical","hand-holding-heart","hand-holding","praying-hands","level-up-alt","level-down-alt","long-arrow-alt-down","long-arrow-alt-up","long-arrow-alt-left","long-arrow-alt-right","toggle-on","toggle-off","search","search-plus","search-minus","cut","crop","copy","paste","font","bold","italic","anchor","link","unlink","external-link-alt","external-link-square-alt","text-height","text-width","align-left","align-center","align-right","align-justify","list","quote-left","quote-right","outdent","indent","undo","adjust","tint","edit","list-ul","list-ol","list-alt","th-large","th","th-list","strikethrough","underline","magic","superscript","subscript","eraser","asterisk","question","info","exclamation","smile","frown","frown-open","meh","meh-rolling-eyes","meh-blank","check","check-circle","check-square","check-double","spell-check","user-check","user-shield","clipboard-check","times","times-circle","user-times","business-time","plus","minus","crosshairs","spinner","circle","circle-notch","dot-circle","minus-circle","exclamation-circle","question-circle","info-circle","plus-circle","plus-square","square","h-square","share","share-square","share-alt","share-alt-square","ellipsis-h","ellipsis-v","minus-square","bullseye","thumbs-up","thumbs-down","thumbtack","star","star-of-life","star-of-david","star-half","star-half-alt","star-and-crescent","heart","heartbeat","heart-broken","lemon","trophy","user","user-md","user-edit","user-friends","users-cog","user-lock","object-group","object-ungroup","layer-group","sign-in-alt","sign-out-alt","key","lock","unlock","unlock-alt","ban","female","male","comment","comments","ticket-alt","tasks","calendar","calendar-check","calendar-times","calendar-plus","calendar-minus","calendar-alt","calendar-day","calendar-week","poo-storm","bolt","sun","moon","clock","user-clock","history","stopwatch","cloud-meatball","cloud-moon","cloud-moon-rain","cloud-sun","cloud-rain","cloud-sun-rain","cloud-showers-heavy","home","comment-alt","comment-slash","comment-medical","comment-dots","sitemap","upload","download","exchange-alt","file-word","file-video","file-powerpoint","file-pdf","file-image","file-excel","file-code","file-audio","file-archive","file-upload","file-signature","file-prescription","file-medical-alt","file-alt","file","file-contract","file-csv","file-ex
21port","file-import","file-invoice","file-medical","folder","folder-plus","folder-minus","folder-open","hdd","cloud","cloud-download-alt","cloud-upload-alt","save","trash","trash-alt","trash-restore","trash-restore-alt","print","rss","rss-square","desktop","laptop","tablet","mobile","mobile-alt","sms","phone","phone-square","microphone","microphone-slash","window-close","window-maximize","window-restore","gamepad","keyboard","chalkboard","chalkboard-teacher","signal","power-off","terminal","code","laptop-code","code-branch","bug","glasses","globe","map-marker","building","warehouse","monument","city","school","store-alt","synagogue","church","university","mosque","landmark","hotel","place-of-worship","torii-gate","hospital","hospital-alt","location-arrow","compass","road","bell","bell-slash","concierge-bell","book","bookmark","bullhorn","camera","camera-retro","video","video-slash","portrait","image","images","pencil-alt","pencil-ruler","pen-square","flask","briefcase","table","truck","wrench","plane","lightbulb","traffic-light","stethoscope","suitcase","coffee","utensils","utensil-spoon","umbrella","ambulance","medkit","fighter-jet","beer","wheelchair","gift","leaf","fire","eye","eye-slash","exclamation-triangle","radiation","skull-crossbones","magnet","flag","flag-usa","flag-checkered","fire-extinguisher","rocket","bomb","retweet","shield-alt","shield-virus","puzzle-piece","balance-scale","balance-scale-right","balance-scale-left","tachometer-alt","bars","columns","filter","sort","sort-down","sort-up","sort-alpha-up","sort-alpha-up-alt","sort-alpha-down","sort-alpha-down-alt","sort-amount-up","sort-amount-up-alt","sort-amount-down-alt","sort-amount-down","sort-numeric-up","sort-numeric-up-alt","sort-numeric-down","sort-numeric-down-alt","money-check","money-check-alt","money-bill-wave-alt","money-bill-wave","money-bill-alt","ruble-sign","lira-sign","hryvnia","dollar-sign","euro-sign","rupee-sign","pound-sign","tenge","shekel-sign","won-sign","yen-sign","funnel-dollar","certificate","wallet","comments-dollar","comment-dollar","file-invoice-dollar","search-dollar","credit-card","shopping-cart","tag","tags","qrcode","barcode"],r[1]="fa"):"fab"==r[0]?(l=["windows","css3","css3-alt","html5","linux","android","apple","behance","bitbucket","codepen","delicious","deviantart","digg","dribbble","elementor","facebook","flickr","foursquare","free-code-camp","github","gitlab","houzz","instagram","jsfiddle","linkedin","medium","meetup","mix","mixcloud","odnoklassniki","pinterest","product-hunt","reddit","skype","slideshare","snapchat","soundcloud","mixcloud","spotify","stack-overflow","steam","telegram","tripadvisor","tumblr","twitch","twitter","viber","vimeo","vk","weibo","weixin","whatsapp","wordpress","xing","yelp","youtube","500px","bitcoin","monero","centercode","creative-commons-share","font-awesome-flag","playstation","pagelines","cloudsmith","cloudscale","cloudversify","ussunnah","stack-exchange"],r[1]="fa"):"dashicons"==r[0]?(l=["blank","menu","admin-site","dashboard","admin-media","admin-page","admin-comments","admin-appearance","admin-plugins","admin-users","admin-tools","admin-settings","admin-network","admin-generic","admin-home","admin-collapse","admin-links","format-links","admin-post","format-standard","format-image","format-gallery","format-audio","format-video","format-chat","format-status","format-aside","format-quote","welcome-write-blog","welcome-edit-page","welcome-add-page","welcome-view-site","welcome-widgets-menus","welcome-comments","welcome-learn-more","image-crop","image-rotate-left","image-rotate-right","image-flip-vertical","image-flip-horizontal","undo","redo","editor-bold","editor-italic","editor-ul","editor-ol","editor-quote","editor-alignleft","editor-aligncenter","editor-alignright","editor-insertmore","editor-spellcheck","editor-distractionfree","editor-kitchensink","editor-underline","editor-justify","editor-textcolor","editor-paste-word","editor-paste-text","editor-removeformatting","editor-video","editor-customchar","editor-outdent","editor-indent","editor-help","editor-strikethrough","editor-unlink","editor-rtl","align-left","align-right","align-center","align-none","lock","calendar","visibility","post-status","post-trash","edit","trash","arrow-up","arrow-down","arrow-left","arrow-right","arrow-up-alt","arrow-down-alt","arrow-left-alt","arrow-right-alt","arrow-up-alt2","arrow-down-alt2","arrow-left-alt2","arrow-right-alt2","leftright","sort","list-view","exerpt-view","share","share1","share-alt","share-alt2","twitter","rss","facebook","facebook-alt","networking","googleplus","hammer","art","migrate","performance","wordpress","wordpress-alt","pressthis","update","screenoptions","info","cart","feedback","cloud","translation","tag","category","yes","no","no-alt","plus","minus","dismiss","marker","star-filled","star-half","star-empty","flag","location","location-alt","camera","images-alt","images-alt2","video-alt","video-alt2","video-alt3","vault","shield","shield-alt","search","slides","analytics","chart-pie","chart
21-bar","chart-line","chart-area","groups","businessman","id","id-alt","products","awards","forms","portfolio","book","book-alt","download","upload","backup","lightbulb","smiley"],r[1]="dashicons"):(l=["blank","standard","aside","image","gallery","video","status","quote","link","chat","audio","github","dribbble","twitter","facebook","facebook-alt","wordpress","googleplus","linkedin","linkedin-alt","pinterest","pinterest-alt","flickr","vimeo","youtube","tumblr","instagram","codepen","polldaddy","googleplus-alt","path","skype","digg","reddit","stumbleupon","pocket","comment","category","tag","time","user","day","week","month","pinned","search","unzoom","zoom","show","hide","close","close-alt","trash","star","home","mail","edit","reply","feed","warning","share","attachment","location","checkmark","menu","refresh","minimize","maximize","404","spam","summary","cloud","key","dot","next","previous","expand","collapse","dropdown","dropdown-left","top","draggable","phone","send-to-phone","plugin","cloud-download","cloud-upload","cloud-upload-alt","external","document","book","cog","unapprove","cart","pause","stop","skip-back","skip-ahead","play","tablet","send-to-tablet","info","notice","help","fastforward","rewind","portfolio","heart","code","subscribe","unsubscribe","subscribed","reply-alt","reply-single","flag","print","lock","bold","italic","picture","uparrow","rightarrow","downarrow","leftarrow"],r[1]="genericon")}function t(e,a,o){for(var t in $list=e.find(".icon-picker-list"),1==o&&$list.empty(),l)$list.append('<li data-icon="'+l[t]+'"><a href="#" title="'+l[t]+'"><span class="'+r[0]+" "+r[1]+"-"+l[t]+'"></span></a></li>');n("a",$list).on("click",function(e){e.preventDefault();var e=n(this).attr("title");$target.val(r[0]+"|"+r[1]+"-"+e),a.removeClass().addClass("button icon-picker "+r[0]+" "+r[1]+"-"+e),i()})}function i(){n(".icon-picker-container").remove()}function e(a){$target=n(a.data("target")),t($popup=n('<div class="icon-picker-container"><div class="icon-picker-control"></div><ul class="icon-picker-list"><ul></div>').css({top:a.offset().top,left:a.offset().left}),a,0);var e=$popup.find(".icon-picker-control");e.html('<p><select><option value="fas">Font Awesome Solid</option><option value="fab">Font Awesome Brand</option><option value="dashicons">Dashicons</option><option value="genericon">Genericons</option></select></p><a data-direction="back" href="#"><span class="dashicons dashicons-arrow-left-alt2"></span></a> <input type="text" class="" placeholder="Search" /><a data-direction="forward" href="#"><span class="dashicons dashicons-arrow-right-alt2"></span></a>'),n("select",e).on("change",function(e){e.preventDefault(),this.value!=r[0]&&(r[0]=this.value,o(),t($popup,a,1))}),n("a",e).on("click",function(e){e.preventDefault(),"back"===n(this).data("direction")?n("li:gt("+(l.length-26)+")",$list).each(function(){n(this).prependTo($list)}):n("li:lt(25)",$list).each(function(){n(this).appendTo($list)})}),$popup.appendTo("body").show(),n("input",e).on("keyup",function(e){var a=n(this).val();""===a?n("li:lt(25)",$list).show():n("li",$list).each(function(){-1!==n(this).data("icon").toString().toLowerCase().indexOf(a.toLowerCase())?n(this).show():n(this).hide()})}),n(document).on("mouseup",function(e){$popup.is(e.target)||0!==$popup.has(e.target).length||i()})}$list=n(""),o(),($button=n(".icon-picker")).each(function(){n(this).on("click.iconPicker",function(){e(n(this))})})},n(function(){n(".icon-picker").iconPicker()})})(jQuery);
22/*!
23 * @preserve
24 *
25 * Readmore.js jQuery plugin
26 * Author: @jed_foster
27 * Project home: http://jedfoster.github.io/Readmore.js
28 * Licensed under the MIT license
29 *
30 * Debounce function from http://davidwalsh.name/javascript-debounce-function
31 */
32!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof exports?module.exports=t(require("jquery")):t(jQuery)}(function(t){"use strict";function e(t,e,i){var o;return function(){var n=this,a=arguments,s=function(){o=null,i||t.apply(n,a)},r=i&&!o;clearTimeout(o),o=setTimeout(s,e),r&&t.apply(n,a)}}function i(t){var e=++h;return String(null==t?"rmjs-":t)+e}function o(t){var e=t.clone().css({height:"auto",width:t.width(),maxHeight:"none",overflow:"hidden"}).insertAfter(t),i=e.outerHeight(),o=parseInt(e.css({maxHeight:""}).css("max-height").replace(/[^-\d\.]/g,""),10),n=t.data("defaultHeight");e.remove();var a=o||t.data("collapsedHeight")||n;
32t.data({expandedHeight:i,maxHeight:o,collapsedHeight:a}).css({maxHeight:"none"})}function n(t){if(!d[t.selector]){var e=" ";t.embedCSS&&""!==t.blockCSS&&(e+=t.selector+" + [data-readmore-toggle], "+t.selector+"[data-readmore]{"+t.blockCSS+"}"),e+=t.selector+"[data-readmore]{transition: height "+t.speed+"ms;overflow: hidden;}",function(t,e){var i=t.createElement("style");i.type="text/css",i.styleSheet?i.styleSheet.cssText=e:i.appendChild(t.createTextNode(e)),t.getElementsByTagName("head")[0].appendChild(i)}(document,e),d[t.selector]=!0}}function a(e,i){this.element=e,this.options=t.extend({},r,i),n(this.options),this._defaults=r,this._name=s,this.init(),window.addEventListener?(window.addEventListener("load",c),window.addEventListener("resize",c)):(window.attachEvent("load",c),window.attachEvent("resize",c))}var s="readmore",r={speed:100,collapsedHeight:200,heightMargin:16,moreLink:'<a href="#">Read More</a>',lessLink:'<a href="#">Close</a>',embedCSS:!0,blockCSS:"display: block; width: 100%;",startOpen:!1,blockProcessed:function(){},beforeToggle:function(){},afterToggle:function(){}},d={},h=0,c=e(function(){t("[data-readmore]").each(function(){var e=t(this),i="true"===e.attr("aria-expanded");o(e),e.css({height:e.data(i?"expandedHeight":"collapsedHeight")})})},100);a.prototype={init:function(){var e=t(this.element);e.data({defaultHeight:this.options.collapsedHeight,heightMargin:this.options.heightMargin}),o(e);var n=e.data("collapsedHeight"),a=e.data("heightMargin");if(e.outerHeight(!0)<=n+a)return this.options.blockProcessed&&"function"==typeof this.options.blockProcessed&&this.options.blockProcessed(e,!1),!0;var s=e.attr("id")||i(),r=this.options.startOpen?this.options.lessLink:this.options.moreLink;e.attr({"data-readmore":"","aria-expanded":this.options.startOpen,id:s}),e.after(t(r).on("click",function(t){return function(i){t.toggle(this,e[0],i)}}(this)).attr({"data-readmore-toggle":s,"aria-controls":s})),this.options.startOpen||e.css({height:n}),this.options.blockProcessed&&"function"==typeof this.options.blockProcessed&&this.options.blockProcessed(e,!0)},toggle:function(e,i,o){o&&o.preventDefault(),e||(e=t('[aria-controls="'+this.element.id+'"]')[0]),i||(i=this.element);var n=t(i),a="",s="",r=!1,d=n.data("collapsedHeight");n.height()<=d?(a=n.data("expandedHeight")+"px",s="lessLink",r=!0):(a=d,s="moreLink"),this.options.beforeToggle&&"function"==typeof this.options.beforeToggle&&this.options.beforeToggle(e,n,!r),n.css({height:a}),n.on("transitionend",function(i){return function(){i.options.afterToggle&&"function"==typeof i.options.afterToggle&&i.options.afterToggle(e,n,r),t(this).attr({"aria-expanded":r}).off("transitionend")}}(this)),t(e).replaceWith(t(this.options[s]).on("click",function(t){return function(e){t.toggle(this,i,e)}}(this)).attr({"data-readmore-toggle":n.attr("id"),"aria-controls":n.attr("id")}))},destroy:function(){t(this.element).each(function(){var e=t(this);e.attr({"data-readmore":null,"aria-expanded":null}).css({maxHeight:"",height:""}).next("[data-readmore-toggle]").remove(),e.removeData()})}},t.fn.readmore=function(e){var i=arguments,o=this.selector;return e=e||{},"object"==typeof e?this.each(function(){if(t.data(this,"plugin_"+s)){var i=t.data(this,"plugin_"+s);i.destroy.apply(i)}e.selector=o,t.data(this,"plugin_"+s,new a(this,e))}):"string"==typeof e&&"_"!==e[0]&&"init"!==e?this.each(function(){var o=t.data(this,"plugin_"+s);o instanceof a&&"function"==typeof o[e]&&o[e].apply(o,Array.prototype.slice.call(i,1))}):void 0}});
33/*!
34 * jquery-confirm v3.3.2 (http://craftpip.github.io/jquery-confirm/)
35 * Author: Boniface Pereira
36 * Website: www.craftpip.com
37 * Contact: [email protected]
38 *
39 * Copyright 2013-2017 jquery-confirm
40 * Licensed under MIT (https://github.com/craftpip/jquery-confirm/blob/master/LICENSE)
41 */
42if(typeof jQuery==="undefined"){throw new Error("jquery-confirm requires jQuery");}var jconfirm,Jconfirm;(function($,window){$.fn.confirm=function(options,option2){if(typeof options==="undefined"){options={};}if(typeof options==="string"){options={content:options,title:(option2)?option2:false};}$(this).each(function(){var $this=$(this);if($this.attr("jc-attached")){console.warn("jConfirm has already been attached to this element ",$this[0]);return;}$this.on("click",function(e){e.preventDefault();var jcOption=$.extend({},options);if($this.attr("data-title")){jcOption.title=$this.attr("data-title");}if($this.attr("data-content")){jcOption.content=$this.attr("data-content");}if(typeof jcOption.buttons=="undefined"){jcOption.buttons={};}jcOption["$target"]=$this;if($this.attr("href")&&Object.keys(jcOption.buttons).length==0){var buttons=$.extend(true,{},jconfirm.pluginDefaults.defaultButtons,(jconfirm.defaults||{}).defaultButtons||{});var firstBtn=Object.keys(buttons)[0];jcOption.buttons=buttons;jcOption.buttons[firstBtn].action=function(){location.href=$this.attr("href");};}jcOption.closeIcon=false;var instance=$.confirm(jcOption);});$this.attr("jc-attached",true);});return $(this);};$.confirm=function(options,option2){if(typeof options==="undefined"){options={};}if(typeof options==="string"){options={content:options,title:(option2)?o
42ption2:false};}var putDefaultButtons=!(options.buttons==false);if(typeof options.buttons!="object"){options.buttons={};}if(Object.keys(options.buttons).length==0&&putDefaultButtons){var buttons=$.extend(true,{},jconfirm.pluginDefaults.defaultButtons,(jconfirm.defaults||{}).defaultButtons||{});options.buttons=buttons;}return jconfirm(options);};$.alert=function(options,option2){if(typeof options==="undefined"){options={};}if(typeof options==="string"){options={content:options,title:(option2)?option2:false};}var putDefaultButtons=!(options.buttons==false);if(typeof options.buttons!="object"){options.buttons={};}if(Object.keys(options.buttons).length==0&&putDefaultButtons){var buttons=$.extend(true,{},jconfirm.pluginDefaults.defaultButtons,(jconfirm.defaults||{}).defaultButtons||{});var firstBtn=Object.keys(buttons)[0];options.buttons[firstBtn]=buttons[firstBtn];}return jconfirm(options);};$.dialog=function(options,option2){if(typeof options==="undefined"){options={};}if(typeof options==="string"){options={content:options,title:(option2)?option2:false,closeIcon:function(){}};}options.buttons={};if(typeof options.closeIcon=="undefined"){options.closeIcon=function(){};}options.confirmKeys=[13];return jconfirm(options);};jconfirm=function(options){if(typeof options==="undefined"){options={};}var pluginOptions=$.extend(true,{},jconfirm.pluginDefaults);if(jconfirm.defaults){pluginOptions=$.extend(true,pluginOptions,jconfirm.defaults);}pluginOptions=$.extend(true,{},pluginOptions,options);var instance=new Jconfirm(pluginOptions);jconfirm.instances.push(instance);return instance;};Jconfirm=function(options){$.extend(this,options);this._init();};Jconfirm.prototype={_init:function(){var that=this;if(!jconfirm.instances.length){jconfirm.lastFocused=$("body").find(":focus");}this._id=Math.round(Math.random()*99999);this.contentParsed=$(document.createElement("div"));if(!this.lazyOpen){setTimeout(function(){that.open();},0);}},_buildHTML:function(){var that=this;this._parseAnimation(this.animation,"o");this._parseAnimation(this.closeAnimation,"c");this._parseBgDismissAnimation(this.backgroundDismissAnimation);this._parseColumnClass(this.columnClass);this._parseTheme(this.theme);this._parseType(this.type);var template=$(this.template);template.find(".jconfirm-box").addClass(this.animationParsed).addClass(this.backgroundDismissAnimationParsed).addClass(this.typeParsed);if(this.typeAnimated){template.find(".jconfirm-box").addClass("jconfirm-type-animated");}if(this.useBootstrap){template.find(".jc-bs3-row").addClass(this.bootstrapClasses.row);template.find(".jc-bs3-row").addClass("justify-content-md-center justify-content-sm-center justify-content-xs-center justify-content-lg-center");template.find(".jconfirm-box-container").addClass(this.columnClassParsed);if(this.containerFluid){template.find(".jc-bs3-container").addClass(this.bootstrapClasses.containerFluid);}else{template.find(".jc-bs3-container").addClass(this.bootstrapClasses.container);}}else{template.find(".jconfirm-box").css("width",this.boxWidth);}if(this.titleClass){template.find(".jconfirm-title-c").addClass(this.titleClass);}template.addClass(this.themeParsed);var ariaLabel="jconfirm-box"+this._id;template.find(".jconfirm-box").attr("aria-labelledby",ariaLabel).attr("tabindex",-1);template.find(".jconfirm-content").attr("id",ariaLabel);if(this.bgOpacity!==null){template.find(".jconfirm-bg").css("opacity",this.bgOpacity);}if(this.rtl){template.addClass("jconfirm-rtl");}this.$el=template.appendTo(this.container);this.$jconfirmBoxContainer=this.$el.find(".jconfirm-box-container");this.$jconfirmBox=this.$body=this.$el.find(".jconfirm-box");this.$jconfirmBg=this.$el.find(".jconfirm-bg");this.$title=this.$el.find(".jconfirm-title");this.$titleContainer=this.$el.find(".jconfirm-title-c");this.$content=this.$el.find("div.jconfirm-content");this.$contentPane=this.$el.find(".jconfirm-content-pane");this.$icon=this.$el.find(".jconfirm-icon-c");this.$closeIcon=this.$el.find(".jconfirm-closeIcon");this.$holder=this.$el.find(".jconfirm-holder");this.$btnc=this.$el.find(".jconfirm-buttons");this.$scrollPane=this.$el.find(".jconfirm-scrollpane");
vendor: 19,095 bytes, line 42
42that.setStartingPoint();this._contentReady=$.Deferred();this._modalReady=$.Deferred();this.$holder.css({"padding-top":this.offsetTop,"padding-bottom":this.offsetBottom,});this.setTitle();this.setIcon();this._setButtons();this._parseContent();this.initDraggable();if(this.isAjax){this.showLoading(false);}$.when(this._contentReady,this._modalReady).then(function(){if(that.isAjaxLoading){setTimeout(function(){that.isAjaxLoading=false;that.setContent();that.setTitle();that.setIcon();setTimeout(function(){that.hideLoading(false);that._updateContentMaxHeight();},100);if(typeof that.onContentReady==="function"){that.onContentReady();}},50);}else{that._updateContentMaxHeight();that.setTitle();that.setIcon();if(typeof that.onContentReady==="function"){that.onContentReady();}}if(that.autoClose){that._startCountDown();}});this._watchContent();if(this.animation==="none"){this.animationSpeed=1;this.animationBounce=1;}this.$body.css(this._getCSS(this.animationSpeed,this.animationBounce));this.$contentPane.css(this._getCSS(this.animationSpeed,1));this.$jconfirmBg.css(this._getCSS(this.animationSpeed,1));this.$jconfirmBoxContainer.css(this._getCSS(this.animationSpeed,1));},_typePrefix:"jconfirm-type-",typeParsed:"",_parseType:function(type){this.typeParsed=this._typePrefix+type;},setType:function(type){var oldClass=this.typeParsed;this._parseType(type);this.$jconfirmBox.removeClass(oldClass).addClass(this.typeParsed);},themeParsed:"",_themePrefix:"jconfirm-",setTheme:function(theme){var previous=this.theme;this.theme=theme||this.theme;this._parseTheme(this.theme);if(previous){this.$el.removeClass(previous);}this.$el.addClass(this.themeParsed);this.theme=theme;},_parseTheme:function(theme){var that=this;theme=theme.split(",");$.each(theme,function(k,a){if(a.indexOf(that._themePrefix)===-1){theme[k]=that._themePrefix+$.trim(a);}});this.themeParsed=theme.join(" ").toLowerCase();},backgroundDismissAnimationParsed:"",_bgDismissPrefix:"jconfirm-hilight-",_parseBgDismissAnimation:function(bgDismissAnimation){var animation=bgDismissAnimation.split(",");var that=this;$.each(animation,function(k,a){if(a.indexOf(that._bgDismissPrefix)===-1){animation[k]=that._bgDismissPrefix+$.trim(a);}});this.backgroundDismissAnimationParsed=animation.join(" ").toLowerCase();},animationParsed:"",closeAnimationParsed:"",_animationPrefix:"jconfirm-animation-",setAnimation:function(animation){this.animation=animation||this.animation;this._parseAnimation(this.animation,"o");},_parseAnimation:function(animation,which){which=which||"o";var animations=animation.split(",");var that=this;$.each(animations,function(k,a){if(a.indexOf(that._animationPrefix)===-1){animations[k]=that._animationPrefix+$.trim(a);}});var a_string=animations.join(" ").toLowerCase();if(which==="o"){this.animationParsed=a_string;}else{this.closeAnimationParsed=a_string;}return a_string;},setCloseAnimation:function(closeAnimation){this.closeAnimation=closeAnimation||this.closeAnimation;this._parseAnimation(this.closeAnimation,"c");},setAnimationSpeed:function(speed){this.animationSpeed=speed||this.animationSpeed;},columnClassParsed:"",setColumnClass:function(colClass){if(!this.useBootstrap){console.warn("cannot set columnClass, useBootstrap is set to false");return;}this.columnClass=colClass||this.columnClass;this._parseColumnClass(this.columnClass);this.$jconfirmBoxContainer.addClass(this.columnClassParsed);},_updateContentMaxHeight:function(){var height=$(window).height()-(this.$jconfirmBox.outerHeight()-this.$contentPane.outerHeight())-(this.offsetTop+this.offsetBottom);this.$contentPane.css({"max-height":height+"px"});},setBoxWidth:function(width){if(this.useBootstrap){console.warn("cannot set boxWidth, useBootstrap is set to true");return;}this.boxWidth=width;this.$jconfirmBox.css("width",width);},_parseColumnClass:function(colClass){colClass=colClass.toLowerCase();var p;switch(colClass){case"xl":case"xlarge":p="col-md-12";break;case"l":case"large":p="col-md-8 col-md-offset-2";break;case"m":case"medium":p="col-md-6 col-md-offset-3";break;case"s":case"small":p="col-md-4 col-md-offset-4";break;case"xs":case"xsmall":p="col-md-2 col-md-offset-5";break;default:p=colClass;}this.columnClassParsed=p;},initDraggable:function(){var that=this;var $t=this.$titleContainer;this.resetDrag();if(this.draggable){$t.on("mousedown",function(e){$t.addClass("jconfirm-hand");that.mouseX=e.clientX;that.mouseY=e.clientY;that.isDrag=true;});$(window).on("mousemove."+this._id,function(e){if(that.isDrag){that.movingX=e.clientX-that.mouseX+that.initialX;that.movingY=e.clientY-that.mouseY+that.initialY;that.setDrag();}});$(window).on("mouseup."+this._id,function(){$t.removeClass("jconfirm-hand");if(that.isDrag){that.isDrag=false;that.initialX=that.movingX;that.initialY=that.movingY;}});}},resetDrag:function(){this.isDrag=false;this.initialX=0;this.initialY=0;this.movingX=0;this.movingY=0;this.mouseX=0;this.mouseY=0;this.$jconfirmBoxContainer.css("transform","translate("+0+"px, "+0+"px)");},setDrag:function(){if(!this.draggable){return;}this.alignMiddle=false;var boxWidth=this.$jconfirmBox.outerWidth();var boxHeight=this.$jconfirmBox.outerHeight();var windowWidth=$(window).width();var windowHeight=$(window).height();var that=this;var dragUpdate=1;if(that.movingX%dragUpdate===0||that.movingY%dragUpdate===0){if(that.dragWindowBorder){var leftDistance=(windowWidth/2)-boxWidth/2;var topDistance=(windowHeight/2)-boxHeight/2;topDistance-=that.dragWindowGap;leftDistance-=that.dragWindowGap;if(leftDistance+that.movingX<0){that.movingX=-leftDistance;}else{if(leftDistance-that.movingX<0){that.movingX=leftDistance;}}if(topDistance+that.movingY<0){that.movingY=-topDistance;}else{if(topDistance-that.movingY<0){that.movingY=topDistance;}}}that.$jconfirmBoxContainer.css("transform","translate("+that.movingX+"px, "+that.movingY+"px)");}},_scrollTop:function(){if(typeof pageYOffset!=="undefined"){return pageYOffset;}else{var B=document.body;var D=document.documentElement;D=(D.clientHeight)?D:B;return D.scrollTop;}},_watchContent:function(){var that=this;if(this._timer){clearInterval(this._timer);}var prevContentHeight=0;this._timer=setInterval(function(){if(that.smoothContent){var contentHeight=that.$content.outerHeight()||0;if(contentHeight!==prevContentHeight){that.$contentPane.css({height:contentHeight}).scrollTop(0);prevContentHeight=contentHeight;}var wh=$(window).height();var total=that.offsetTop+that.offsetBottom+that.$jconfirmBox.height()-that.$contentPane.height()+that.$content.height();if(total<wh){that.$contentPane.addClass("no-scroll");}else{that.$contentPane.removeClass("no-scroll");}}},this.watchInterval);},_overflowClass:"jconfirm-overflow",_hilightAnimating:false,highlight:function(){this.hiLightModal();},hiLightModal:function(){var that=this;if(this._hilightAnimating){return;}that.$body.addClass("hilight");var duration=parseFloat(that.$body.css("animation-duration"))||2;this._hilightAnimating=true;setTimeout(function(){that._hilightAnimating=false;that.$body.removeClass("hilight");},duration*1000);},_bindEvents:function(){var that=this;this.boxClicked=false;this.$scrollPane.click(function(e){if(!that.boxClicked){var buttonName=false;var shouldClose=false;var str;if(typeof that.backgroundDismiss=="function"){str=that.backgroundDismiss();}else{str=that.backgroundDismiss;}if(typeof str=="string"&&typeof that.buttons[str]!="undefined"){buttonName=str;shouldClose=false;}else{if(typeof str=="undefined"||!!(str)==true){shouldClose=true;}else{shouldClose=false;}}if(buttonName){var btnResponse=that.buttons[buttonName].action.apply(that);shouldClose=(typeof btnResponse=="undefined")||!!(btnResponse);}if(shouldClose){that.close();}else{that.hiLightModal();}}that.boxClicked=false;});this.$jconfirmBox.click(function(e){that.boxClicked=true;});var isKeyDown=false;$(window).on("jcKeyDown."+that._id,function(e){if(!isKeyDown){isKeyDown=true;}});$(window).on("keyup."+that._id,function(e){if(isKeyDown){that.reactOnKey(e);isKeyDown=false;}});$(window).on("resize."+this._id,function(){that._updateContentMaxHeight();setTimeout(function(){that.resetDrag();},100);});},_cubic_bezier:"0.36, 0.55, 0.19",_getCSS:function(speed,bounce){return{"-webkit-transition-duration":speed/1000+"s","transition-duration":speed/1000+"s","-webkit-transition-timing-function":"cubic-bezier("+this._cubic_bezier+", "+bounce+")","transition-timing-function":"cubic-bezier("+this._cubic_bezier+", "+bounce+")"};},_setButtons:function(){var that=this;var total_buttons=0;if(typeof this.buttons!=="object"){this.buttons={};}$.each(this.buttons,function(key,button){total_buttons+=1;if(typeof button==="function"){that.buttons[key]=button={action:button};}that.buttons[key].text=button.text||key;that.buttons[key].btnClass=button.btnClass||"btn-default";that.buttons[key].action=button.action||function(){};that.buttons[key].keys=button.keys||[];that.buttons[key].isHidden=button.isHidden||false;that.buttons[key].isDisabled=button.isDisabled||false;$.each(that.buttons[key].keys,function(i,a){that.buttons[key].keys[i]=a.toLowerCase();});var button_element=$('<button type="button" class="btn"></button>').html(that.buttons[key].text).addClass(that.buttons[key].btnClass).prop("disabled",that.buttons[key].isDisabled).css("display",that.buttons[key].isHidden?"none":"").click(function(e){e.preventDefault();var res=that.buttons[key].action.apply(that,[that.buttons[key]]);that.onAction.apply(that,[key,that.buttons[key]]);that._stopCountDown();if(typeof res==="undefined"||res){that.close();}});that.buttons[key].el=button_element;that.buttons[key].setText=function(text){button_element.html(text);};that.buttons[key].addClass=function(className){button_element.addClass(className);};that.buttons[key].removeClass=function(className){button_element.removeClass(className);};that.buttons[key].disable=function(){that.buttons[key].isDisabled=true;button_element.prop("disabled",true);};that.buttons[key].enable=function(){that.buttons[key].isDisabled=false;button_element.prop("disabled",false);};that.buttons[key].show=function(){that.buttons[key].isHidden=false;button_element.css("display","");};that.buttons[key].hide=function(){that.buttons[key].isHidden=true;button_element.css("display","none");};that["$_"+key]=that["$$"+key]=button_element;that.$btnc.append(button_element);});if(total_buttons===0){this.$btnc.hide();}if(this.closeIcon===null&&total_buttons===0){this.closeIcon=true;}if(this.closeIcon){if(this.closeIconClass){var closeHtml='<i class="'+this.closeIconClass+'"></i>';this.$closeIcon.html(closeHtml);}this.$closeIcon.click(function(e){e.preventDefault();var buttonName=false;var shouldClose=false;var str;if(typeof that.closeIcon=="function"){str=that.closeIcon();}else{str=that.closeIcon;}if(typeof str=="string"&&typeof that.buttons[str]!="undefined"){buttonName=str;shouldClose=false;}else{if(typeof str=="undefined"||!!(str)==true){shouldClose=true;}else{shouldClose=false;}}if(buttonName){var btnResponse=that.buttons[buttonName].action.apply(that);shouldClose=(typeof btnResponse=="undefined")||!!(btnResponse);}if(shouldClose){that.close();}});this.$closeIcon.show();}else{this.$closeIcon.hide();}},setTitle:function(string,force){force=force||false;if(typeof string!=="undefined"){if(typeof string=="string"){this.title=string;}else{if(typeof string=="function"){if(typeof string.promise=="function"){console.error("Promise was returned from title function, this is not supported.");}var response=string();if(typeof response=="string"){this.title=response;}else{this.title=false;}}else{this.title=false;}}}if(this.isAjaxLoading&&!force){return;}this.$title.html(this.title||"");this.updateTitleContainer();},setIcon:function(iconClass,force){force=force||false;if(typeof iconClass!=="undefined"){if(typeof iconClass=="string"){this.icon=iconClass;}else{if(typeof iconClass==="function"){var response=iconClass();if(typeof response=="string"){this.icon=response;}else{this.icon=false;}}else{this.icon=false;}}}if(this.isAjaxLoading&&!force){return;}this.$icon.html(this.icon?'<i class="'+this.icon+'"></i>':"");this.updateTitleContainer();},updateTitleContainer:function(){if(!this.title&&!this.icon){this.$titleContainer.hide();}else{this.$titleContainer.show();}},setContentPrepend:function(content,force){if(!content){return;}this.contentParsed.prepend(content);},setContentAppend:function(content){if(!content){return;}this.contentParsed.append(content);},setContent:function(content,force){force=!!force;var that=this;if(content){this.contentParsed.html("").append(content);}if(this.isAjaxLoading&&!force){return;}this.$content.html("");this.$content.append(this.contentParsed);setTimeout(function(){that.$body.find("input[autofocus]:visible:first").focus();},100);},loadingSpinner:false,showLoading:function(disableButtons){this.loadingSpinner=true;this.$jconfirmBox.addClass("loading");if(disableButtons){this.$btnc.find("button").prop("disabled",true);}},hideLoading:function(enableButtons){this.loadingSpinner=false;this.$jconfirmBox.removeClass("loading");if(enableButtons){this.$btnc.find("button").prop("disabled",false);}},ajaxResponse:false,contentParsed:"",isAjax:false,isAjaxLoading:false,_parseContent:function(){var that=this;var e="&nbsp;";if(typeof this.content=="function"){var res=this.content.apply(this);if(typeof res=="string"){this.content=res;}else{if(typeof res=="object"&&typeof res.always=="function"){this.isAjax=true;this.isAjaxLoading=true;res.always(function(data,status,xhr){that.ajaxResponse={data:data,status:status,xhr:xhr};that._contentReady.resolve(data,status,xhr);if(typeof that.contentLoaded=="function"){that.contentLoaded(data,status,xhr);}});this.content=e;}else{this.content=e;}}}if(typeof this.content=="string"&&this.content.substr(0,4).toLowerCase()==="url:"){this.isAjax=true;this.isAjaxLoading=true;var u=this.content.substring(4,this.content.length);$.get(u).done(function(html){that.contentParsed.html(html);}).always(function(data,status,xhr){that.ajaxResponse={data:data,status:status,xhr:xhr};that._contentReady.resolve(data,status,xhr);if(typeof that.contentLoaded=="function"){that.contentLoaded(data,status,xhr);}});}if(!this.content){this.content=e;}if(!this.isAjax){this.contentParsed.html(this.content);this.setContent();that._contentReady.resolve();}},_stopCountDown:function(){clearInterval(this.autoCloseInterval);if(this.$cd){this.$cd.remove();}},_startCountDown:function(){var that=this;var opt=this.autoClose.split("|");if(opt.length!==2){console.error("Invalid option for autoClose. example 'close|10000'");return false;}var button_key=opt[0];var time=parseInt(opt[1]);if(typeof this.buttons[button_key]==="undefined"){console.error("Invalid button key '"+button_key+"' for autoClose");return false;}var seconds=Math.ceil(time/1000);this.$cd=$('<span class="countdown"> ('+seconds+")</span>").appendTo(this["$_"+button_key]);this.autoCloseInterval=setInterval(function(){that.$cd.html(" ("+(seconds-=1)+") ");if(seconds<=0){that["$$"+button_key].trigger("click");that._stopCountDown();}},1000);},_getKey:function(key){switch(key){case 192:return"tilde";case 13:return"enter";case 16:return"shift";case 9:return"tab";case 20:return"capslock";case 17:return"ctrl";case 91:return"win";case 18:return"alt";case 27:return"esc";case 32:return"space";}var initial=String.fromCharCode(key);if(/^[A-z0-9]+$/.test(initial)){return initial.toLowerCase();}else{return false;}},reactOnKey:function(e){var that=this;var a=$(".jconfirm");if(a.eq(a.length-1)[0]!==this.$el[0]){return false;}var key=e.which;if(this.$content.find(":input").is(":focus")&&/13|32/.test(key)){return false;}var keyChar=this._getKey(key);if(keyChar==="esc"&&this.escapeKey){if(this.escapeKey===true){this.$scrollPane.trigger("click");}else{if(typeof this.escapeKey==="string"||typeof this.escapeKey==="function"){var buttonKey;if(typeof this.escapeKey==="function"){buttonKey=this.escapeKey();}else{buttonKey=this.escapeKey;}if(buttonKey){if(typeof this.buttons[buttonKey]==="undefined"){console.warn("Invalid escapeKey, no buttons found with key "+buttonKey);}else{this["$_"+buttonKey].trigger("click");}}}}}$.each(this.buttons,function(key,button){if(button.keys.indexOf(keyChar)!=-1){that["$_"+key].trigger("click");}});},setDialogCenter:function(){console.info("setDialogCenter is deprecated, dialogs are centered with CSS3 tables");},_unwatchContent:function(){clearInterval(this._timer);},close:function(onClosePayload){var that=this;if(typeof this.onClose==="function"){this.onClose(onClosePayload);}this._unwatchContent();$(window).unbind("resize."+this._id);$(window).unbind("keyup."+this._id);$(window).unbind("jcKeyDown."+this._id);if(this.draggable){$(window).unbind("mousemove."+this._id);$(window).unbind("mouseup."+this._id);this.$titleContainer.unbind("mousedown");}that.$el.removeClass(that.loadedClass);$("body").removeClass("jconfirm-no-scroll-"+that._id);that.$jconfirmBoxContainer.removeClass("jconfirm-no-transition");setTimeout(function(){that.$body.addClass(that.closeAnimationParsed);that.$jconfirmBg.addClass("jconfirm-bg-h");var closeTimer=(that.closeAnimation==="none")?1:that.animationSpeed;setTimeout(function(){that.$el.remove();var l=jconfirm.instances;var i=jconfirm.instances.length-1;for(i;i>=0;i--){if(jconfirm.instances[i]._id===that._id){jconfirm.instances.splice(i,1);}}if(!jconfirm.instances.length){if(that.scrollToPreviousElement&&jconfirm.lastFocused&&jconfirm.lastFocused.length&&$.contains(document,jconfirm.lastFocused[0])){var $lf=jconfirm.lastFocused;if(that.scrollToPreviousElementAnimate){var st=$(window).scrollTop();var ot=jconfirm.lastFocused.offset().top;var wh=$(window).height();if(!(ot>st&&ot<(st+wh))){var scrollTo=(ot-Math.round((wh/3)));$("html, body").animate({scrollTop:scrollTo},that.animationSpeed,"swing",function(){$lf.focus();});}else{$lf.focus();}}else{$lf.focus();}jconfirm.lastFocused=false;}}if(typeof that.onDestroy==="function"){that.onDestroy();}},closeTimer*0.4);},50);return true;},open:function(){if(this.isOpen()){return false;}this._buildHTML();this._bindEvents();this._open();return true;},setStartingPoint:function(){var el=false;if(this.animateFromElement!==true&&this.animateFromElement){el=this.animateFromElement;jconfirm.lastClicked=false;}else{if(jconfirm.lastClicked&&this.animateFromElement===true){el=jconfirm.lastClicked;jconfirm.lastClicked=false;}else{return false;}}if(!el){return false;}var offset=el.offset();var iTop=el.outerHeight()/2;var iLeft=el.outerWidth()/2;iTop-=this.$jconfirmBox.outerHeight()/2;iLeft-=this.$jconfirmBox.outerWidth()/2;var sourceTop=offset.top+iTop;sourceTop=sourceTop-this._scrollTop();var sourceLeft=offset.left+iLeft;var wh=$(window).height()/2;var ww=$(window).width()/2;var targetH=wh-this.$jconfirmBox.outerHeight()/2;var targetW=ww-this.$jconfirmBox.outerWidth()/2;sourceTop-=targetH;sourceLeft-=targetW;if(Math.abs(sourceTop)>wh||Math.abs(sourceLeft)>ww){return false;}this.$jconfirmBoxContainer.css("transform","translate("+sourceLeft+"px, "+sourceTop+"px)");},_open:function(){var that=this;if(typeof that.onOpenBefore==="function"){that.onOpenBefore();}this.$body.removeClass(this.animationParsed);
42this.$jconfirmBg.removeClass("jconfirm-bg-h");this.$body.focus();that.$jconfirmBoxContainer.css("transform","translate("+0+"px, "+0+"px)");setTimeout(function(){that.$body.css(that._getCSS(that.animationSpeed,1));that.$body.css({"transition-property":that.$body.css("transition-property")+", margin"});that.$jconfirmBoxContainer.addClass("jconfirm-no-transition");that._modalReady.resolve();if(typeof that.onOpen==="function"){that.onOpen();}that.$el.addClass(that.loadedClass);},this.animationSpeed);},loadedClass:"jconfirm-open",isClosed:function(){return !this.$el||this.$el.css("display")==="";},isOpen:function(){return !this.isClosed();},toggle:function(){if(!this.isOpen()){this.open();}else{this.close();}}};jconfirm.instances=[];jconfirm.lastFocused=false;jconfirm.pluginDefaults={template:'<div class="jconfirm"><div class="jconfirm-bg jconfirm-bg-h"></div><div class="jconfirm-scrollpane"><div class="jconfirm-row"><div class="jconfirm-cell"><div class="jconfirm-holder"><div class="jc-bs3-container"><div class="jc-bs3-row"><div class="jconfirm-box-container jconfirm-animated"><div class="jconfirm-box" role="dialog" aria-labelledby="labelled" tabindex="-1"><div class="jconfirm-closeIcon">&times;</div><div class="jconfirm-title-c"><span class="jconfirm-icon-c"></span><span class="jconfirm-title"></span></div><div class="jconfirm-content-pane"><div class="jconfirm-content"></div></div><div class="jconfirm-buttons"></div><div class="jconfirm-clear"></div></div></div></div></div></div></div></div></div></div>',title:"Hello",titleClass:"",type:"default",typeAnimated:true,draggable:true,dragWindowGap:15,dragWindowBorder:true,animateFromElement:true,alignMiddle:true,smoothContent:true,content:"Are you sure to continue?",buttons:{},defaultButtons:{ok:{action:function(){}},close:{action:function(){}}},contentLoaded:function(){},icon:"",lazyOpen:false,bgOpacity:null,theme:"light",animation:"scale",closeAnimation:"scale",animationSpeed:400,animationBounce:1,escapeKey:true,rtl:false,container:"body",containerFluid:false,backgroundDismiss:false,backgroundDismissAnimation:"shake",autoClose:false,closeIcon:null,closeIconClass:false,watchInterval:100,columnClass:"col-md-4 col-md-offset-4 col-sm-6 col-sm-offset-3 col-xs-10 col-xs-offset-1",boxWidth:"50%",scrollToPreviousElement:true,scrollToPreviousElementAnimate:true,useBootstrap:true,offsetTop:40,offsetBottom:40,bootstrapClasses:{container:"container",containerFluid:"container-fluid",row:"row"},onContentReady:function(){},onOpenBefore:function(){},onOpen:function(){},onClose:function(){},onDestroy:function(){},onAction:function(){}};var keyDown=false;$(window).on("keydown",function(e){if(!keyDown){var $target=$(e.target);var pass=false;if($target.closest(".jconfirm-box").length){pass=true;}if(pass){$(window).trigger("jcKeyDown");}keyDown=true;}});$(window).on("keyup",function(){keyDown=false;});jconfirm.lastClicked=false;$(document).on("mousedown","button, a",function(){jconfirm.lastClicked=$(this);});})(jQuery,window);
43(e=>{"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof module&&module.exports?module.exports=function(t,i){return void 0===i&&(i="undefined"!=typeof window?require("jquery"):require("jquery")(t)),e(i),i}:e(jQuery)})(function(D){var M=[].indexOf||function(t){for(var i=0,e=this.length;i<e;i++)if(i in this&&this[i]===t)return i;return-1},n="notify",r=n+"js",a=n+"!blank",k={t:"top",m:"middle",b:"bottom",l:"left",c:"center",r:"right"},B=["l","c","r"],H=["t","m","b"],Q=["t","b","l","r"],R={t:"b",m:null,b:"t",l:"r",c:null,r:"l"},o=function(t){var e,e=[];return D.each(t.split(/\W+/),function(t,i){var i,i=i.toLowerCase().charAt(0);if(k[i])return e.push(i)}),e},s={},l={name:"core",html:'<div class="'+r+'-wrapper">\n\t<div class="'+r+'-arrow"></div>\n\t<div class="'+r+'-container"></div>\n</div>',css:"."+r+"-corner {\n\tposition: fixed;\n\tmargin: 5px;\n\tz-index: 1050;\n}\n\n."+r+"-corner ."+r+"-wrapper,\n."+r+"-corner ."+r+"-container {\n\tposition: relative;\n\tdisplay: block;\n\theight: inherit;\n\twidth: inherit;\n\tmargin: 3px;\n}\n\n."+r+"-wrapper {\n\tz-index: 1;\n\tposition: absolute;\n\tdisplay: inline-block;\n\theight: 0;\n\twidth: 0;\n}\n\n."+r+"-container {\n\tdisplay: none;\n\tz-index: 1;\n\tposition: absolute;\n}\n\n."+r+"-hidable {\n\tcursor: pointer;\n}\n\n[data-notify-text],[data-notify-html] {\n\tposition: relative;\n}\n\n."+r+"-arrow {\n\tposition: absolute;\n\tz-index: 2;\n\twidth: 0;\n\theight: 0;\n}"},h={"border-radius":["-webkit-","-moz-"]},t=function(t){return s[t]},i=function(t,e){if(!t)throw"Missing Style name";if(!e)throw"Missing Style definition";if(!e.html)throw"Missing Style HTML";var i=s[t],o=(i&&i.cssElem&&(window.console&&console.warn(n+": overwriting style '"+t+"'"),s[t].cssElem.remove()),s[e.name=t]=e,""),i=(e.classes&&D.each(e.classes,function(t,i){return o+="."+r+"-"+e.name+"-"+t+" {\n",D.each(i,function(e,n){return h[e]&&D.each(h[e],function(t,i){return o+="\t"+i+e+": "+n+";\n"}),o+="\t"+e+": "+n+";\n"}),o+="}\n"}),e.css&&(o+="/* styles for "+e.name+" */\n"+e.css),o&&(e.cssElem=A(o),e.cssElem.attr("id","notify-"+e.name)),{}),t=D(e.html);c("html",t,i),c("text",t,i),e.fields=i},A=function(i){var t,e,n,e=f("style");e.attr("type","text/css"),D("head").append(e);try{e.html(i)}catch(t){e[0].styleSheet.cssText=i}return e},c=function(i,t,e){var n;return d(t,"["+(n="data-notify-"+(i="html"!==i?"text":i))+"]").each(function(){var t,t=D(this).attr(n);e[t=t||a]=i})},d=function(t,i){return t.is(i)?t:t.find(i)},p={clickToHide:!0,autoHide:!0,autoHideDelay:5e3,arrowShow:!0,arrowSize:5,breakNewLines:!0,elementPosition:"bottom",globalPosition:"top right",style:"bootstrap",className:"error",showAnimation:"slideDown",showDuration:400,hideAnimation:"slideUp",hideDuration:200,gap:5},u=function(t,i){var e,e=function(){};return e.prototype=t,D.extend(!0,new e,i)},e=function(t){return D.extend(p,t)},f=function(t){return D("<"+t+"></"+t+">")},g={},w=function(e){var t;return e=e.is("[type=radio]")?(t=e.parents("form:first").find("[type=radio]").filter(function(t,i){return D(i).attr("name")===e.attr("name")}
43)).first():e},U=function(t,i,e){var n,o;if("string"==typeof e)e=parseInt(e,10);else if("number"!=typeof e)return;if(!isNaN(e))return n=k[R[i.charAt(0)]],o=i,void 0!==t[n]&&(i=k[n.charAt(0)],e=-e),void 0===t[i]?t[i]=e:t[i]+=e,null},X=function(t,i,e){if("l"===t||"t"===t)return 0;if("c"===t||"m"===t)return e/2-i/2;if("r"===t||"b"===t)return e-i;throw"Invalid alignment"},m=function(t){return(m.e=m.e||f("div")).text(t).html()};function y(t,i,e){this.options=u(p,D.isPlainObject(e="string"==typeof e?{className:e}:e)?e:{}),this.loadHTML(),this.wrapper=D(l.html),this.options.clickToHide&&this.wrapper.addClass(r+"-hidable"),this.wrapper.data(r,this),this.arrow=this.wrapper.find("."+r+"-arrow"),this.container=this.wrapper.find("."+r+"-container"),this.container.append(this.userContainer),t&&t.length&&(this.elementType=t.attr("type"),this.originalElement=t,this.elem=w(t),this.elem.data(r,this),this.elem.before(this.wrapper)),this.container.hide(),this.run(i)}y.prototype.loadHTML=function(){var t,t=this.getStyle();this.userContainer=D(t.html),this.userFields=t.fields},y.prototype.show=function(t,i){var e,n,o,r,s,a,n=function(){if(t||a.elem||a.destroy(),i)return i()},s=0<(a=this).container.parent().parents(":hidden").length,o=this.container.add(this.arrow),e=[];if(s&&t)r="show";else if(s&&!t)r="hide";else if(!s&&t)r=this.options.showAnimation,e.push(this.options.showDuration);else{if(s||t)return n();r=this.options.hideAnimation,e.push(this.options.hideDuration)}return e.push(n),o[r].apply(o,e)},y.prototype.setGlobalPosition=function(){var t=this.getPosition(),i=t[0],t=t[1],e=k[i],n=k[t],i=i+"|"+t,t=g[i],t,i;return t||(t=g[i]=f("div"),(i={})[e]=0,"middle"===n?i.top="45%":"center"===n?i.left="45%":i[n]=0,t.css(i).addClass(r+"-corner"),D("body").append(t)),t.prepend(this.wrapper)},y.prototype.setElementPosition=function(){var t,i,e,n,o,r,s,a,l,h,A,c,A,d,p,u,f,g,w,m,y,b,v,C,E,x,A,F,S,A=this.getPosition(),C=A[0],b=A[1],v=A[2],A=this.elem.position(),a=this.elem.outerHeight(),c=this.elem.outerWidth(),l=this.elem.innerHe
43ight(),h=this.elem.innerWidth(),S=this.wrapper.position(),o=this.container.height(),r=this.container.width(),g=k[C],m=R[C],y=k[m],s={};for(s[y]="b"===C?a:"r"===C?c:0,U(s,"top",A.top-S.top),U(s,"left",A.left-S.left),d=0,u=(F=["top","left"]).length;d<u;d++)E=F[d],(w=parseInt(this.elem.css("margin-"+E),10))&&U(s,E,w);if(A=Math.max(0,this.options.gap-(this.options.arrowShow?e:0)),U(s,y,A),this.options.arrowShow){for(e=this.options.arrowSize,i=D.extend({},s),t=this.userContainer.css("border-color")||this.userContainer.css("border-top-color")||this.userContainer.css("background-color")||"white",p=0,f=Q.length;p<f;p++)x=k[E=Q[p]],E!==m&&(i["border-"+x]=e+"px solid "+(n=x===g?t:"transparent"));U(s,k[m],e),0<=M.call(Q,b)&&U(i,k[b],2*e)}else this.arrow.hide();if(0<=M.call(H,C)?(U(s,"left",X(b,r,c)),i&&U(i,"left",X(b,e,h))):0<=M.call(B,C)&&(U(s,"top",X(b,o,a)),i)&&U(i,"top",X(b,e,l)),this.container.is(":visible")&&(s.display="block"),this.container.removeAttr("style").css(s),i)return this.arrow.removeAttr("style").css(i)},y.prototype.getPosition=function(){var t,i,e,e,e,e,e,t,t=this.options.position||(this.elem?this.options.elementPosition:this.options.globalPosition),t=o(t);if(0===t.length&&(t[0]="b"),M.call(Q,i=t[0])<0)throw"Must be one of ["+Q+"]";return(1===t.length||(e=t[0],0<=M.call(H,e)&&(e=t[1],M.call(B,e)<0))||(e=t[0],0<=M.call(B,e)&&(e=t[1],M.call(H,e)<0)))&&(t[1]=(e=t[0],0<=M.call(B,e)?"m":"l")),2===t.length&&(t[2]=t[1]),t},y.prototype.getStyle=function(t){var i;if(t=t||this.options.style,i=s[t=t||"default"])return i;throw"Missing style: "+t},y.prototype.updateClasses=function(){var t,i,t=["base"];return D.isArray(this.options.className)?t=t.concat(this.options.className):this.options.className&&t.push(this.options.className),i=this.getStyle(),t=D.map(t,function(t){return r+"-"+i.name+"-"+t}).join(" "),this.userContainer.attr("class",t)},y.prototype.run=function(t,i){var e,n,o,r,s;if(D.isPlainObject(i)?D.extend(this.options,i):"string"===D.type(i)&&(this.options.className=i),this.container&&!t)this.show(!1);else if(this.container||t){for(o in n={},D.isPlainObject(t)?n=t:n[a]=t,n)e=n[o],(r=this.userFields[o])&&("text"===r&&(e=m(e),this.options.breakNewLines)&&(e=e.replace(/\n/g,"<br/>")),d(this.userContainer,"[data-notify-"+r+(s=o===a?"":"="+o)+"]").html(e));this.updateClasses(),this.elem?this.setElementPosition():this.setGlobalPosition(),this.show(!0),this.options.autoHide&&(clearTimeout(this.autohideTimer),this.autohideTimer=setTimeout(this.show.bind(this,!1),this.options.autoHideDelay))}},y.prototype.destroy=function(){this.wrapper.data(r,null),this.wrapper.remove()},D[n]=function(t,i,e){return t&&t.nodeName||t.jquery?D(t)[n](i,e):(e=i,new y(null,i=t,e)),t},D.fn[n]=function(e,n){return D(this).each(function(){var t=w(D(this)).data(r),i=(t&&t.destroy(),new y(D(this),e,n))}),this},D.extend(D[n],{defaults:e,addStyle:i,pluginOptions:p,getStyle:t,insertCSS:A}),i("bootstrap",{html:"<div>\n<span data-notify-text></span>\n</div>",classes:{base:{"font-weight":"bold",padding:"8px 15px 8px 14px","text-shadow":"0 1px 0 rgba(255, 255, 255, 0.5)","background-color":"#fcf8e3",border:"1px solid #fbeed5","border-radius":"4px","white-space":"nowrap","padding-left":"25px","background-repeat":"no-repeat","background-position":"3px 7px"},error:{color:"#B94A48","background-color":"#F2DEDE","border-color":"#EED3D7","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAtRJREFUeNqkVc1u00AQHq+dOD+0poIQfkIjalW0SEGqRMuRnHos3DjwAH0ArlyQeANOOSMeAA5VjyBxKBQhgSpVUKKQNGloFdw4cWw2jtfMOna6JOUArDTazXi/b3dm55socPqQhFka++aHBsI8GsopRJERNFlY88FCEk9Yiwf8RhgRyaHFQpPHCDmZG5oX2ui2yilkcTT1AcDsbYC1NMAyOi7zTX2Agx7A9luAl88BauiiQ/cJaZQfIpAlngDcvZZMrl8vFPK5+XktrWlx3/ehZ5r9+t6e+WVnp1pxnNIjgBe4/6dAysQc8dsmHwPcW9C0h3fW1hans1ltwJhy0GxK7XZbUlMp5Ww2eyan6+ft/f2FAqXGK4CvQk5HueFz7D6GOZtIrK+srupdx1GRBBqNBtzc2AiMr7nPplRdKhb1q6q6zjFhrklEFOUutoQ50xcX86ZlqaZpQrfbBdu2R6/G19zX6XSgh6RX5ubyHCM8nqSID6ICrGiZjGYYxojEsiw4PDwMSL5VKsC8Yf4VRYFzMzMaxwjlJSlCyAQ9l0CW44PBADzXhe7xMdi9HtTrdYjFYkDQL0cn4Xdq2/EAE+InCnvADTf2eah4Sx9vExQjkqXT6aAERICMewd/UAp/IeYANM2joxt+q5VI+ieq2i0Wg3l6DNzHwTERPgo1ko7XBXj3vdlsT2F+UuhIhYkp7u7CarkcrFOCtR3H5JiwbAIeImjT/YQKKBtGjRFCU5IUgFRe7fF4cCNVIPMYo3VKqxwjyNAXNepuopyqnld602qVsfRpEkkz+GFL1wPj6ySXBpJtWVa5xlhpcyhBNwpZHmtX8AGgfIExo0ZpzkWVTBGiXCSEaHh62/PoR0p/vHaczxXGnj4bSo+G78lELU80h1uogBwWLf5YlsPmgDEd4M236xjm+8nm4IuE/9u+/PH2JXZfbwz4zw1WbO+SQPpXfwG/BBgAhCNZiSb/pOQAAAAASUVORK5CYII=)"},success:{color:"#468847","background-color":"#DFF0D8","border-color":"#D6E9C6","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAutJREFUeNq0lctPE0Ecx38zu/RFS1EryqtgJFA08YCiMZIAQQ4eRG8eDGdPJiYeTIwHTfwPiAcvXIwXLwoXPaDxkWgQ6islKlJLS
43QWLUraPLTv7Gme32zoF9KSTfLO7v53vZ3d/M7/fIth+IO6INt2jjoA7bjHCJoAlzCRw59YwHYjBnfMPqAKWQYKjGkfCJqAF0xwZjipQtA3MxeSG87VhOOYegVrUCy7UZM9S6TLIdAamySTclZdYhFhRHloGYg7mgZv1Zzztvgud7V1tbQ2twYA34LJmF4p5dXF1KTufnE+SxeJtuCZNsLDCQU0+RyKTF27Unw101l8e6hns3u0PBalORVVVkcaEKBJDgV3+cGM4tKKmI+ohlIGnygKX00rSBfszz/n2uXv81wd6+rt1orsZCHRdr1Imk2F2Kob3hutSxW8thsd8AXNaln9D7CTfA6O+0UgkMuwVvEFFUbbAcrkcTA8+AtOk8E6KiQiDmMFSDqZItAzEVQviRkdDdaFgPp8HSZKAEAL5Qh7Sq2lIJBJwv2scUqkUnKoZgNhcDKhKg5aH+1IkcouCAdFGAQsuWZYhOjwFHQ96oagWgRoUov1T9kRBEODAwxM2QtEUl+Wp+Ln9VRo6BcMw4ErHRYjH4/B26AlQoQQTRdHWwcd9AH57+UAXddvDD37DmrBBV34WfqiXPl61g+vr6xA9zsGeM9gOdsNXkgpEtTwVvwOklXLKm6+/p5ezwk4B+j6droBs2CsGa/gNs6RIxazl4Tc25mpTgw/apPR1LYlNRFAzgsOxkyXYLIM1V8NMwyAkJSctD1eGVKiq5wWjSPdjmeTkiKvVW4f2YPHWl3GAVq6ymcyCTgovM3FzyRiDe2TaKcEKsLpJvNHjZgPNqEtyi6mZIm4SRFyLMUsONSSdkPeFtY1n0mczoY3BHTLhwPRy9/lzcziCw9ACI+yql0VLzcGAZbYSM5CCSZg1/9oc/nn7+i8N9p/8An4JMADxhH+xHfuiKwAAAABJRU5ErkJggg==)"},info:{color:"#3A87AD","background-color":"#D9EDF7","border-color":"#BCE8F1","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYFAhkSsdes/QAAA8dJREFUOMvVlGtMW2UYx//POaWHXg6lLaW0ypAtw1UCgbniNOLcVOLmAjHZolOYlxmTGXVZdAnRfXQm+7SoU4mXaOaiZsEpC9FkiQs6Z6bdCnNYruM6KNBw6YWewzl9z+sHImEWv+vz7XmT95f/+3/+7wP814v+efDOV3/SoX3lHAA+6ODeUFfMfjOWMADgdk+eEKz0pF7aQdMAcOKLLjrcVMVX3xdWN29/GhYP7SvnP0cWfS8caSkfHZsPE9Fgnt02JNutQ0QYHB2dDz9/pKX8QjjuO9xUxd/66HdxTeCHZ3rojQObGQBcuNjfplkD3b19Y/6MrimSaKgSMmpGU5WevmE/swa6Oy73tQHA0Rdr2Mmv/6A1n9w9suQ7097Z9lM4FlTgTDrzZTu4StXVfpiI48rVcUDM5cmEksrFnHxfpTtU/3BFQzCQF/2bYVoNbH7zmItbSoMj40JSzmMyX5qDvriA7QdrIIpA+3cdsMpu0nXI8cV0MtKXCPZev+gCEM1S2NHPvWfP/hL+7FSr3+0p5RBEyhEN5JCKYr8XnASMT0xBNyzQGQeI8fjsGD39RMPk7se2bd5ZtTyoFYXftF6y37gx7NeUtJJOTFlAHDZLDuILU3j3+H5oOrD3yWbIztugaAzg
43nBKJuBLpGfQrS8wO4FZgV+c1IxaLgWVU0tMLEETCos4xMzEIv9cJXQcyagIwigDGwJgOAtHAwAhisQUjy0ORGERiELgG4iakkzo4MYAxcM5hAMi1WWG1yYCJIcMUaBkVRLdGeSU2995TLWzcUAzONJ7J6FBVBYIggMzmFbvdBV44Corg8vjhzC+EJEl8U1kJtgYrhCzgc/vvTwXKSib1paRFVRVORDAJAsw5FuTaJEhWM2SHB3mOAlhkNxwuLzeJsGwqWzf5TFNdKgtY5qHp6ZFf67Y/sAVadCaVY5YACDDb3Oi4NIjLnWMw2QthCBIsVhsUTU9tvXsjeq9+X1d75/KEs4LNOfcdf/+HthMnvwxOD0wmHaXr7ZItn2wuH2SnBzbZAbPJwpPx+VQuzcm7dgRCB57a1uBzUDRL4bfnI0RE0eaXd9W89mpjqHZnUI5Hh2l2dkZZUhOqpi2qSmpOmZ64Tuu9qlz/SEXo6MEHa3wOip46F1n7633eekV8ds8Wxjn37Wl63VVa+ej5oeEZ/82ZBETJjpJ1Rbij2D3Z/1trXUvLsblCK0XfOx0SX2kMsn9dX+d+7Kf6h8o4AIykuffjT8L20LU+w4AZd5VvEPY+XpWqLV327HR7DzXuDnD8r+ovkBehJ8i+y8YAAAAASUVORK5CYII=)"},warn:{color:"#C09853","background-color":"#FCF8E3","border-color":"#FBEED5","background-image":"url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAABJlBMVEXr6eb/2oD/wi7/xjr/0mP/ykf/tQD/vBj/3o7/uQ//vyL/twebhgD/4pzX1K3z8e349vK6tHCilCWbiQymn0jGworr6dXQza3HxcKkn1vWvV/5uRfk4dXZ1bD18+/52YebiAmyr5S9mhCzrWq5t6ufjRH54aLs0oS+qD751XqPhAybhwXsujG3sm+Zk0PTwG6Shg+PhhObhwOPgQL4zV2nlyrf27uLfgCPhRHu7OmLgAafkyiWkD3l49ibiAfTs0C+lgCniwD4sgDJxqOilzDWowWFfAH08uebig6qpFHBvH/aw26FfQTQzsvy8OyEfz20r3jAvaKbhgG9q0nc2LbZxXanoUu/u5WSggCtp1anpJKdmFz/zlX/1nGJiYmuq5Dx7+sAAADoPUZSAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfdBgUBGhh4aah5AAAAlklEQVQY02NgoBIIE8EUcwn1FkIXM1Tj5dDUQhPU502Mi7XXQxGz5uVIjGOJUUUW81HnYEyMi2HVcUOICQZzMMYmxrEyMylJwgUt5BljWRLjmJm4pI1hYp5SQLGYxDgmLnZOVxuooClIDKgXKMbN5ggV1ACLJcaBxNgcoiGCBiZwdWxOETBDrTyEFey0jYJ4eHjMGWgEAIpRFRCUt08qAAAAAElFTkSuQmCC)"}}}),D(function(){A(l.css).attr("id","core-notify"),D(document).on("click","."+r+"-hidable",function(t){D(this).trigger("notify-hide")}),D(document).on("notify-hide","."+r+"-wrapper",function(t){var i=D(this).data(r);i&&i.show(!1)})})});
44(l=>{function r(t,e){var n=new google.maps.Map(t,e),o=new google.maps.Marker({position:new google.maps.LatLng(54.19335,-3.92695),map:n,title:"Drag Me",visible:e.markerVisible,draggable:e.markerDraggable,icon:void 0!==e.markerIcon?e.markerIcon:void 0});return{map:n,marker:o,circle:null,location:o.position,radius:e.radius,locationName:e.locationName,addressComponents:{formatted_address:null,addressLine1:null,addressLine2:null,streetName:null,streetNumber:null,city:null,district:null,state:null,stateOrProvince:null},settings:e.settings,domContainer:t,geodecoder:new google.maps.Geocoder}}var u={drawCircle:function(t,e,n,o){return null!=t.circle&&t.circle.setMap(null),0<n?(n*=1,(o=l.extend({strokeColor:"#0000FF",strokeOpacity:.35,strokeWeight:2,fillColor:"#0000FF",fillOpacity:.2},o)).map=t.map,o.radius=n,o.center=e,t.circle=new google.maps.Circle(o),t.cir
44cle):null},setPosition:function(t,e,n){t.location=e,t.marker.setPosition(e),t.map.panTo(e),this.drawCircle(t,e,t.radius,{}),t.settings.enableReverseGeocode?this.updateLocationName(t,n):n&&n.call(this,t)},locationFromLatLng:function(t){return{latitude:t.lat(),longitude:t.lng()}},addressByFormat:function(t,e){for(var n=null,o=t.length-1;0<=o;o--)0<=t[o].types.indexOf(e)&&(n=t[o]);return n||t[0]},updateLocationName:function(n,o){n.geodecoder.geocode({latLng:n.marker.position},function(t,e){if(e==google.maps.GeocoderStatus.OK&&0<t.length){var t=u.addressByFormat(t,n.settings.addressFormat);n.locationName=t.formatted_address,n.addressComponents=u.address_component_from_google_geocode(t.address_components)}else if(e==google.maps.GeocoderStatus.OVER_QUERY_LIMIT)return setTimeout(function(){u.updateLocationName(n,o)},1e3);o&&o.call(this,n)})},address_component_from_google_geocode:function(t){for(var e={},n=t.length-1;0<=n;n--){var o=t[n];0<=o.types.indexOf("postal_code")?e.postalCode=o.short_name:0<=o.types.indexOf("street_number")?e.streetNumber=o.short_name:0<=o.types.indexOf("route")?e.streetName=o.short_name:0<=o.types.indexOf("locality")?e.city=o.short_name:0<=o.types.indexOf("sublocality")?e.district=o.short_name:0<=o.types.indexOf("administrative_area_level_1")?e.stateOrProvince=o.short_name:0<=o.types.indexOf("country")&&(e.country=o.short_name)}return e.addressLine1=[e.streetNumber,e.streetName].join(" ").trim(),e.addressLine2="",e}};function s(t){return null!=c(t)}function c(t){return l(t).data("locationpicker")}function d(t,e){var n;t&&(n=u.locationFromLatLng(e.marker.position),t.latitudeInput&&t.latitudeInput.val(n.latitude).change(),t.longitudeInput&&t.longitudeInput.val(n.longitude).change(),t.radiusInput)&&t.radiusInput.val(e.radius).change()}function g(n,o){var e;n&&(n.radiusInput&&n.radiusInput.on("change",function(t){var e=l(this).val();t.originalEvent&&!isNaN(e)&&(o.radius=e,u.setPosition(o,o.location,function(t){t.settings.onchanged.apply(o.domContainer,[u.locationFromLatLng(t.location),t.radius,!1])}))}),n.locationNameInput&&o.settings.enableAutocomplete&&(e=!1,o.autocomplete=new google.maps.places.Autocomplete(n.locationNameInput.get(0),o.settings.autocompleteOptions),google.maps.event.addListener(o.autocomplete,"place_changed",function(){e=!1;var t=o.autocomplete.getPlace();t.geometry?u.setPosition(o,t.geometry.location,function(t){d(n,t),t.settings.onchanged.apply(o.domContainer,[u.locationFromLatLng(t.location),t.radius,!1])}):o.settings.onlocationnotfound(t.name)}),o.settings.enableAutocompleteBlur)&&(n.locationNameInput.on("change",function(t){t.originalEvent&&(e=!0)}),n.locationNameInput.on("blur",function(t){t.originalEvent&&setTimeout(function(){var t=l(n.locationNameInput).val();5<t.length&&e&&(e=!1,o.geodecoder.geocode({address:t},function(t,e){e==google.maps.GeocoderStatus.OK&&t&&t.length&&u.setPosition(o,t[0].geometry.location,function(t){d(n,t),t.settings.onchanged.apply(o.domContainer,[u.locationFromLatLng(t.location),t.radius,!1])})}))},1e3)})),n.latitudeInput&&n.latitudeInput.on("change",function(t){var e=l(this).val();t.originalEvent&&!isNaN(e)&&u.setPosition(o,new google.maps.LatLng(e,o.location.lng()),function(t){t.settings.onchanged.apply(o.domContainer,[u.locationFromLatLng(t.location),t.radius,!1]),d(o.settings.inputBinding,o)})}),n.longitudeInput)&&n.longitudeInput.on("change",function(t){var e=l(this).val();t.originalEvent&&!isNaN(e)&&u.setPosition(o,new google.maps.LatLng(o.location.lat(),e),function(t){t.settings.onchanged.apply(o.domContainer,[u.locationFromLatLng(t.location),t.radius,!1]),d(o.settings.inputBinding,o)})})}function m(t){google.maps.event.trigger(t.map,"resize"),setTimeout(function(){t.map.setCenter(t.marker.position)},300)}function p(e,n,t){var t=l.extend({},l.fn.locationpicker.defaults,t),o=t.location.latitude,a=t.location.longitude,t=t.radius,i=e.settings.location.latitude,r=e.settings.location.longitude,s=e.settings.radius;o==i&&a==r&&t==s||(e.settings.location.latitude=o,e.settings.location.longitude=a,e.radius=t,u.setPosition(e,new google.maps.LatLng(e.settings.location.latitude,e.settings.location.longitude),function(t){g(e.settings.inputBinding,e),t.settings.oninitialized(n)}))}l.fn.locationpicker=function(t,e){if("string"!=typeof t)return this.each(function(){var e=l(this),n,o;function a(){u.setPosition(o,o.marker.position,function(t){var e=u.locationFromLatLng(o.location);d(o.settings.inputBinding,o),t.settings.onchanged.apply(o.domContainer,[e,t.radius,!0])})}s(this)?p(c(this),l(this),t):(n=l.extend({},l.fn.locationpicker.defaults,t),o=new r(this,l.extend({},{zoom:n.zoom,center:new google.maps.LatLng(n.location.latitude,n.location.longitude),mapTypeId:n.mapTypeId,mapTypeControl:!1,styles:n.styles,disableDoubleClickZoom:!1,scrollwheel:n.scrollwheel,streetViewControl:!1,radius:n.radius,locationName:n.locationName,settings:n,autocompleteOptions:n.autocompleteOptions,addressFormat:n.addressFormat,draggable:n.draggable,markerIcon:n.markerIcon,markerDraggable:n.markerDraggable,markerVisible:n.markerVisible},n.mapOptions)),e.data("locationpicker",o),n.markerInCenter&&(o.map.addListener("bounds_changed",function(){o.marker.dragging||(o.marker.setPosition(o.map.center),d(o.settings.inputBinding,o))}),o.map.addListener("idle",function(){o.marker.dragging||a()})),google.maps.event.addListener(o.marker,"drag",function(t){d(o.settings.inputBinding,o)}),google.maps.event.addListener(o.marker,"dragend",function(t){a()}),u.setPosition(o,new google.maps.LatLng(n.location.latitude,n.location.longitude),function(t){d(n.inputBinding,o),g(n.inputBinding,o),t.settings.oninitialized(e)}))});var n=this.get(0);if(s(n)){var o=c(n),a,a;switch(t){case"location":if(null==e)return(a=u.locationFromLatLng(o.location)).radius=o.radius,a.name=o.locationName,a;e.radius&&(o.radius=e.radius),u.setPosition(o,new google.maps.LatLng(e.latitude,e.longitude),function(t){d(t.settings.inputBinding,t)});break;case"subscribe":if(null==e)return null;var a=e.event,i=e.callback;if(!a||!i)return console.error('LocationPicker: Invalid arguments for method "subscribe"'),null;google.maps.event.addListener(o.map,a,i);break;case"map":return null==e?((a=u.locationFromLatLng(o.location)).formattedAddress=o.locationName,a.addressComponents=o.addressComponents,{map:o.map,marker:o.marker,location:a}):null;case"autosize":return m(o),this}return null}},l.fn.locationpicker.defaults={location:{latitude:40.7324319,longitude:-73.82480777777776},locationName:"",radius:500,zoom:15,mapTypeId:google.maps.MapTypeId.ROADMAP,styles:[],mapOptions:{},scrollwheel:!0,inputBinding:{latitudeInput:null,longitudeInput:null,radiusInput:null,locationNameInput:null},enableAutocomplete:!1,enableAutocompleteBlur:!1,autocompleteOptions:null,addressFormat:"postal_code",enableReverseGeocode:!0,draggable:!0,onchanged:function(t,e,n){},onlocationnotfound:function(t){},oninitialized:function(t){},markerIcon:void 0,markerDraggable:!0,markerVisible:!0}})(jQuery);
45;window.Modernizr=function(a,b,c){function w(a){j.cssText=a}function x(a,b){return w(m.join(a+";")+(b||""))}function y(a,b){return typeof a===b}function z(a,b){return!!~(""+a).indexOf(b)}function A(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:y(f,"function")?f.bind(d||b):f}return!1}var d="2.7.1",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n={},o={},p={},q=[],r=q.slice,s,t=function(a,c,d,e){var f,i,j,k,l=b.createElement("div"),m=b.body,n=m||b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),l.appendChild(j);return f=["&#173;",'<style id="s',h,'">',a,"</style>"].join(""),l.id=h,(m?l:n).innerHTML+=f,n.appendChild(l),m||(n.style.background="",n.style.overflow="hidden",k=g.style.overflow,g.style.overflow="hidden",g.appendChild(n)),i=c(l,a),m?l.parentNode.removeChild(l):(n.parentNode.removeChild(n),g.style.overflow=k),!!i},u={}.hasOwnProperty,v;!y(u,"undefined")&&!y(u.call,"undefined")?v=function(a,b){return u.call(a,b)}:v=function(a,b){return b in a&&y(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;
vendor: 7,524 bytes, lines 45-57
45var d=r.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(r.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(r.call(arguments)))};return e}),n.touch=function(){var c;return"ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch?c=!0:t(["@media (",m.join("touch-enabled),("),h,")","{#modernizr{top:9px;position:absolute}}"].join(""),function(a){c=a.offsetTop===9}),c};for(var B in n)v(n,B)&&(s=B.toLowerCase(),e[s]=n[B](),q.push((e[s]?"":"no-")+s));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)v(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,typeof f!="undefined"&&f&&(g.className+=" "+(b?"":"no-")+a),e[a]=b}return e},w(""),i=k=null,function(a,b){function l(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function m(){var a=s.elements;return typeof a=="string"?a.split(" "):a}function n(a){var b=j[a[h]];return b||(b={},i++,a[h]=i,j[i]=b),b}function o(a,c,d){c||(c=b);if(k)return c.createElement(a);d||(d=n(c));var g;return d.cache[a]?g=d.cache[a].cloneNode():f.test(a)?g=(d.cache[a]=d.createElem(a)).cloneNode():g=d.createElem(a),g.canHaveChildren&&!e.test(a)&&!g.tagUrn?d.frag.appendChild(g):g}function p(a,c){a||(a=b);if(k)return a.createDocumentFragment();c=c||n(a);var d=c.frag.cloneNode(),e=0,f=m(),g=f.length;for(;e<g;e++)d.createElement(f[e]);return d}function q(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return s.shivMethods?o(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/[\w\-]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(s,b.frag)}function r(a){a||(a=b);var c=n(a);return s.shivCSS&&!g&&!c.hasCSS&&(c.hasCSS=!!l(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),k||q(a,c),a}var c="3.7.0",d=a.html5||{},e=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,f=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,g,h="_html5shiv",i=0,j={},k;(function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",g="hidden"in a,k=a.childNodes.length==1||function(){b.createElement("a");var a=b.createDocumentFragment();return typeof a.cloneNode=="undefined"||typeof a.createDocumentFragment=="undefined"||typeof a.createElement=="undefined"}()}catch(c){g=!0,k=!0}})();var s={elements:d.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video",version:c,shivCSS:d.shivCSS!==!1,supportsUnknownElements:k,shivMethods:d.shivMethods!==!1,type:"default",shivDocument:r,createElement:o,createDocumentFragment:p};a.html5=s,r(b)}(this,b),e._version=d,e._prefixes=m,e.testStyles=t,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+q.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return"[object Function]"==o.call(a)}function e(a){return"string"==typeof a}function f(){}function g(a){return!a||"loaded"==a||"complete"==a||"uninitialized"==a}function h(){var a=p.shift();q=1,a?a.t?m(function(){("c"==a.t?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){"img"!=a&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l=b.createElement(a),o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};1===y[c]&&(r=1,y[c]=[]),"object"==a?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),"img"!=a&&(r||2===y[c]?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i("c"==b?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),1==p.length&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&"[object Opera]"==o.call(a.opera),l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return"[object Array]"==o.call(a)},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,h){var i=b(a),j=i.autoCallback;i.url.split(".").pop().split("?").shift(),i.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]),i.instead?i.instead(a,e,f,g,h):(y[i.url]?i.noexec=!0:y[i.url]=1,f.load(i.url,i.forceCSS||!i.forceJS&&"css"==i.url.split(".").pop().split("?").shift()?"c":c,i.noexec,i.attrs,i.timeout),(d(e)||d(j))&&f.load(function(){k(),e&&e(i.origUrl,h,g),j&&j(i.origUrl,h,g),y[i.url]=2})))}function h(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var i,j,l=this.yepnope.loader;if(e(a))g(a,0,l,0);else if(w(a))for(i=0;i<a.length;i++)j=a[i],e(j)?g(j,0,l,0):w(j)?B(j):Object(j)===j&&h(j,l);else Object(a)===a&&h(a,l)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,null==b.readyState&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
46/*
47 * This combined file was created by the DataTables downloader builder:
48 *   https://datatables.net/download
49 *
50 * To rebuild or modify this file with the latest versions of the included
51 * software please visit:
52 *   https://datatables.net/download/#bs/dt-1.10.16/r-2.2.1
53 *
54 * Included libraries:
55 *   DataTables 1.10.16, Responsive 2.2.1
56 */
57
58/*! DataTables 1.10.16
59 * ©2008-2017 SpryMedia Ltd - datatables.net/license
60 */
61
62/**
63 * @summary     DataTables
64 * @description Paginate, search and order HTML tables
65 * @version     1.10.16
66 * @file        jquery.dataTables.js
67 * @author      SpryMedia Ltd
68 * @contact     www.datatables.net
69 * @copyright   Copyright 2008-2017 SpryMedia Ltd.
70 *
71 * This source file is free software, available under the following license:
72 *   MIT license - http://datatables.net/license
73 *
74 * This source file is distributed in the hope that it will be useful, but
75 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
76 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
77 *
78 * For details please refer to: http://www.datatables.net
79 */
80
81/*jslint evil: true, undef: true, browser: true */
82/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
83
84(function( factory ) {
85	"use strict";
86
87	if ( typeof define === 'function' && define.amd ) {
88		// AMD
89		define( ['jquery'], function ( $ ) {
90			return factory( $, window, document );
91		} );
92	}
93	else if ( typeof exports === 'object' ) {
94		// CommonJS
95		module.exports = function (root, $) {
96			if ( ! root ) {
97				// CommonJS environments without a window global must pass a
98				// root. This will give an error otherwise
99				root = window;
100			}
101
102			if ( ! $ ) {
103				$ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
104					require('jquery') :
105					require('jquery')( root );
106			}
107
108			return factory( $, root, root.document );
109		};
110	}
111	else {
112		// Browser
113		factory( jQuery, window, document );
114	}
115}
116(function( $, window, document, undefined ) {
117	"use strict";
118
119	/**
120	 * DataTables is a plug-in for the jQuery Javascript library. It is a highly
121	 * flexible tool, based upon the foundations of progressive enhancement,
122	 * which will add advanced interaction controls to any HTML table. For a
123	 * full list of features please refer to
124	 * [DataTables.net](href="http://datatables.net).
125	 *
126	 * Note that the `DataTable` object is not a global variable but is aliased
127	 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
128	 * be  accessed.
129	 *
130	 *  @class
131	 *  @param {object} [init={}] Configuration object for DataTables. Options
132	 *    are defined by {@link DataTable.defaults}
133	 *  @requires jQuery 1.7+
134	 *
135	 *  @example
136	 *    // Basic initialisation
137	 *    $(document).ready( function {
138	 *      $('#example').dataTable();
139	 *    } );
140	 *
141	 *  @example
142	 *    // Initialisation with configuration options - in this case, disable
143	 *    // pagination and sorting.
144	 *    $(document).ready( function {
145	 *      $('#example').dataTable( {
146	 *        "paginate": false,
147	 *        "sort": false
148	 *      } );
149	 *    } );
150	 */
151	var DataTable = function ( options )
152	{
vendor: 6,636 bytes, lines 152-311
152
153		/**
154		 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
155		 * return the resulting jQuery object.
156		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
157		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
158		 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
159		 *    criterion ("applied") or all TR elements (i.e. no filter).
160		 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
161		 *    Can be either 'current', whereby the current sorting of the table is used, or
162		 *    'original' whereby the original order the data was read into the table is used.
163		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
164		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
165		 *    'current' and filter is 'applied', regardless of what they might be given as.
166		 *  @returns {object} jQuery object, filtered by the given selector.
167		 *  @dtopt API
168		 *  @deprecated Since v1.10
169		 *
170		 *  @example
171		 *    $(document).ready(function() {
172		 *      var oTable = $('#example').dataTable();
173		 *
174		 *      // Highlight every second row
175		 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
176		 *    } );
177		 *
178		 *  @example
179		 *    $(document).ready(function() {
180		 *      var oTable = $('#example').dataTable();
181		 *
182		 *      // Filter to rows with 'Webkit' in them, add a background colour and then
183		 *      // remove the filter, thus highlighting the 'Webkit' rows only.
184		 *      oTable.fnFilter('Webkit');
185		 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
186		 *      oTable.fnFilter('');
187		 *    } );
188		 */
189		this.$ = function ( sSelector, oOpts )
190		{
191			return this.api(true).$( sSelector, oOpts );
192		};
193		
194		
195		/**
196		 * Almost identical to $ in operation, but in this case returns the data for the matched
197		 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
198		 * rather than any descendants, so the data can be obtained for the row/cell. If matching
199		 * rows are found, the data returned is the original data array/object that was used to
200		 * create the row (or a generated array if from a DOM source).
201		 *
202		 * This method is often useful in-combination with $ where both functions are given the
203		 * same parameters and the array indexes will match identically.
204		 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
205		 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
206		 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
207		 *    criterion ("applied") or all elements (i.e. no filter).
208		 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
209		 *    Can be either 'current', whereby the current sorting of the table is used, or
210		 *    'original' whereby the original order the data was read into the table is used.
211		 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
212		 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
213		 *    'current' and filter is 'applied', regardless of what they might be given as.
214		 *  @returns {array} Data for the matched elements. If any elements, as a result of the
215		 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
216		 *    entry in the array.
217		 *  @dtopt API
218		 *  @deprecated Since v1.10
219		 *
220		 *  @example
221		 *    $(document).ready(function() {
222		 *      var oTable = $('#example').dataTable();
223		 *
224		 *      // Get the data from the first row in the table
225		 *      var data = oTable._('tr:first');
226		 *
227		 *      // Do something useful with the data
228		 *      alert( "First cell is: "+data[0] );
229		 *    } );
230		 *
231		 *  @example
232		 *    $(document).ready(function() {
233		 *      var oTable = $('#example').dataTable();
234		 *
235		 *      // Filter to 'Webkit' and get all data for
236		 *      oTable.fnFilter('Webkit');
237		 *      var data = oTable._('tr', {"search": "applied"});
238		 *
239		 *      // Do something with the data
240		 *      alert( data.length+" rows matched the search" );
241		 *    } );
242		 */
243		this._ = function ( sSelector, oOpts )
244		{
245			return this.api(true).rows( sSelector, oOpts ).data();
246		};
247		
248		
249		/**
250		 * Create a DataTables Api instance, with the currently selected tables for
251		 * the Api's context.
252		 * @param {boolean} [traditional=false] Set the API instance's context to be
253		 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
254		 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
255		 *   or if all tables captured in the jQuery object should be used.
256		 * @return {DataTables.Api}
257		 */
258		this.api = function ( traditional )
259		{
260			return traditional ?
261				new _Api(
262					_fnSettingsFromNode( this[ _ext.iApiIndex ] )
263				) :
264				new _Api( this );
265		};
266		
267		
268		/**
269		 * Add a single new row or multiple rows of data to the table. Please note
270		 * that this is suitable for client-side processing only - if you are using
271		 * server-side processing (i.e. "bServerSide": true), then to add data, you
272		 * must add it to the data source, i.e. the server-side, through an Ajax call.
273		 *  @param {array|object} data The data to be added to the table. This can be:
274		 *    <ul>
275		 *      <li>1D array of data - add a single row with the data provided</li>
276		 *      <li>2D array of arrays - add multiple rows in a single call</li>
277		 *      <li>object - data object when using <i>mData</i></li>
278		 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
279		 *    </ul>
280		 *  @param {bool} [redraw=true] redraw the table or not
281		 *  @returns {array} An array of integers, representing the list of indexes in
282		 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
283		 *    the table.
284		 *  @dtopt API
285		 *  @deprecated Since v1.10
286		 *
287		 *  @example
288		 *    // Global var for counter
289		 *    var giCount = 2;
290		 *
291		 *    $(document).ready(function() {
292		 *      $('#example').dataTable();
293		 *    } );
294		 *
295		 *    function fnClickAddRow() {
296		 *      $('#example').dataTable().fnAddData( [
297		 *        giCount+".1",
298		 *        giCount+".2",
299		 *        giCount+".3",
300		 *        giCount+".4" ]
301		 *      );
302		 *
303		 *      giCount++;
304		 *    }
305		 */
306		this.fnAddData = function( data, redraw )
307		{
308			var api = this.api( true );
309		
310			/* Check if we want to add multiple rows or not */
311			var rows = 
311$.isArray(data) && ( $
vendor: 18,409 bytes, lines 311-907
311.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
312				api.rows.add( data ) :
313				api.row.add( data );
314		
315			if ( redraw === undefined || redraw ) {
316				api.draw();
317			}
318		
319			return rows.flatten().toArray();
320		};
321		
322		
323		/**
324		 * This function will make DataTables recalculate the column sizes, based on the data
325		 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
326		 * through the sWidth parameter). This can be useful when the width of the table's
327		 * parent element changes (for example a window resize).
328		 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
329		 *  @dtopt API
330		 *  @deprecated Since v1.10
331		 *
332		 *  @example
333		 *    $(document).ready(function() {
334		 *      var oTable = $('#example').dataTable( {
335		 *        "sScrollY": "200px",
336		 *        "bPaginate": false
337		 *      } );
338		 *
339		 *      $(window).on('resize', function () {
340		 *        oTable.fnAdjustColumnSizing();
341		 *      } );
342		 *    } );
343		 */
344		this.fnAdjustColumnSizing = function ( bRedraw )
345		{
346			var api = this.api( true ).columns.adjust();
347			var settings = api.settings()[0];
348			var scroll = settings.oScroll;
349		
350			if ( bRedraw === undefined || bRedraw ) {
351				api.draw( false );
352			}
353			else if ( scroll.sX !== "" || scroll.sY !== "" ) {
354				/* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
355				_fnScrollDraw( settings );
356			}
357		};
358		
359		
360		/**
361		 * Quickly and simply clear a table
362		 *  @param {bool} [bRedraw=true] redraw the table or not
363		 *  @dtopt API
364		 *  @deprecated Since v1.10
365		 *
366		 *  @example
367		 *    $(document).ready(function() {
368		 *      var oTable = $('#example').dataTable();
369		 *
370		 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
371		 *      oTable.fnClearTable();
372		 *    } );
373		 */
374		this.fnClearTable = function( bRedraw )
375		{
376			var api = this.api( true ).clear();
377		
378			if ( bRedraw === undefined || bRedraw ) {
379				api.draw();
380			}
381		};
382		
383		
384		/**
385		 * The exact opposite of 'opening' a row, this function will close any rows which
386		 * are currently 'open'.
387		 *  @param {node} nTr the table row to 'close'
388		 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
389		 *  @dtopt API
390		 *  @deprecated Since v1.10
391		 *
392		 *  @example
393		 *    $(document).ready(function() {
394		 *      var oTable;
395		 *
396		 *      // 'open' an information row when a row is clicked on
397		 *      $('#example tbody tr').click( function () {
398		 *        if ( oTable.fnIsOpen(this) ) {
399		 *          oTable.fnClose( this );
400		 *        } else {
401		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
402		 *        }
403		 *      } );
404		 *
405		 *      oTable = $('#example').dataTable();
406		 *    } );
407		 */
408		this.fnClose = function( nTr )
409		{
410			this.api( true ).row( nTr ).child.hide();
411		};
412		
413		
414		/**
415		 * Remove a row for the table
416		 *  @param {mixed} target The index of the row from aoData to be deleted, or
417		 *    the TR element you want to delete
418		 *  @param {function|null} [callBack] Callback function
419		 *  @param {bool} [redraw=true] Redraw the table or not
420		 *  @returns {array} The row that was deleted
421		 *  @dtopt API
422		 *  @deprecated Since v1.10
423		 *
424		 *  @example
425		 *    $(document).ready(function() {
426		 *      var oTable = $('#example').dataTable();
427		 *
428		 *      // Immediately remove the first row
429		 *      oTable.fnDeleteRow( 0 );
430		 *    } );
431		 */
432		this.fnDeleteRow = function( target, callback, redraw )
433		{
434			var api = this.api( true );
435			var rows = api.rows( target );
436			var settings = rows.settings()[0];
437			var data = settings.aoData[ rows[0][0] ];
438		
439			rows.remove();
440		
441			if ( callback ) {
442				callback.call( this, settings, data );
443			}
444		
445			if ( redraw === undefined || redraw ) {
446				api.draw();
447			}
448		
449			return data;
450		};
451		
452		
453		/**
454		 * Restore the table to it's original state in the DOM by removing all of DataTables
455		 * enhancements, alterations to the DOM structure of the table and event listeners.
456		 *  @param {boolean} [remove=false] Completely remove the table from the DOM
457		 *  @dtopt API
458		 *  @deprecated Since v1.10
459		 *
460		 *  @example
461		 *    $(document).ready(function() {
462		 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
463		 *      var oTable = $('#example').dataTable();
464		 *      oTable.fnDestroy();
465		 *    } );
466		 */
467		this.fnDestroy = function ( remove )
468		{
469			this.api( true ).destroy( remove );
470		};
471		
472		
473		/**
474		 * Redraw the table
475		 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
476		 *  @dtopt API
477		 *  @deprecated Since v1.10
478		 *
479		 *  @example
480		 *    $(document).ready(function() {
481		 *      var oTable = $('#example').dataTable();
482		 *
483		 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
484		 *      oTable.fnDraw();
485		 *    } );
486		 */
487		this.fnDraw = function( complete )
488		{
489			// Note that this isn't an exact match to the old call to _fnDraw - it takes
490			// into account the new data, but can hold position.
491			this.api( true ).draw( complete );
492		};
493		
494		
495		/**
496		 * Filter the input based on data
497		 *  @param {string} sInput String to filter the table on
498		 *  @param {int|null} [iColumn] Column to limit filtering to
499		 *  @param {bool} [bRegex=false] Treat as regular expression or not
500		 *  @param {bool} [bSmart=true] Perform smart filtering or not
501		 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
502		 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
503		 *  @dtopt API
504		 *  @deprecated Since v1.10
505		 *
506		 *  @example
507		 *    $(document).ready(function() {
508		 *      var oTable = $('#example').dataTable();
509		 *
510		 *      // Sometime later - filter...
511		 *      oTable.fnFilter( 'test string' );
512		 *    } );
513		 */
514		this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
515		{
516			var api = this.api( true );
517		
518			if ( iColumn === null || iColumn === undefined ) {
519				api.search( sInput, bRegex, bSmart, bCaseInsensitive );
520			}
521			else {
522				api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
523			}
524		
525			api.draw();
526		};
527		
528		
529		/**
530		 * Get the data for the whole table, an individual row or an individual cell based on the
531		 * provided parameters.
532		 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
533		 *    a TR node then the data source for the whole row will be returned. If given as a
534		 *    TD/TH cell node then iCol will be automatically calculated and the data for the
535		 *    cell returned. If given as an integer, then this is treated as the aoData internal
536		 *    data index for the row (see fnGetPosition) and the data for that row used.
537		 *  @param {int} [col] Optional column index that you want the data of.
538		 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
539		 *    returned. If mRow is defined, just data for that row, and is iCol is
540		 *    defined, only data for the designated cell is returned.
541		 *  @dtopt API
542		 *  @deprecated Since v1.10
543		 *
544		 *  @example
545		 *    // Row data
546		 *    $(document).ready(function() {
547		 *      oTable = $('#example').dataTable();
548		 *
549		 *      oTable.$('tr').click( function () {
550		 *        var data = oTable.fnGetData( this );
551		 *        // ... do something with the array / object of data for the row
552		 *      } );
553		 *    } );
554		 *
555		 *  @example
556		 *    // Individual cell data
557		 *    $(document).ready(function() {
558		 *      oTable = $('#example').dataTable();
559		 *
560		 *      oTable.$('td').click( function () {
561		 *        var sData = oTable.fnGetData( this );
562		 *        alert( 'The cell clicked on had the value of '+sData );
563		 *      } );
564		 *    } );
565		 */
566		this.fnGetData = function( src, col )
567		{
568			var api = this.api( true );
569		
570			if ( src !== undefined ) {
571				var type = src.nodeName ? src.nodeName.toLowerCase() : '';
572		
573				return col !== undefined || type == 'td' || type == 'th' ?
574					api.cell( src, col ).data() :
575					api.row( src ).data() || null;
576			}
577		
578			return api.data().toArray();
579		};
580		
581		
582		/**
583		 * Get an array of the TR nodes that are used in the table's body. Note that you will
584		 * typically want to use the '$' API method in preference to this as it is more
585		 * flexible.
586		 *  @param {int} [iRow] Optional row index for the TR element you want
587		 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
588		 *    in the table's body, or iRow is defined, just the TR element requested.
589		 *  @dtopt API
590		 *  @deprecated Since v1.10
591		 *
592		 *  @example
593		 *    $(document).ready(function() {
594		 *      var oTable = $('#example').dataTable();
595		 *
596		 *      // Get the nodes from the table
597		 *      var nNodes = oTable.fnGetNodes( );
598		 *    } );
599		 */
600		this.fnGetNodes = function( iRow )
601		{
602			var api = this.api( true );
603		
604			return iRow !== undefined ?
605				api.row( iRow ).node() :
606				api.rows().nodes().flatten().toArray();
607		};
608		
609		
610		/**
611		 * Get the array indexes of a particular cell from it's DOM element
612		 * and column index including hidden columns
613		 *  @param {node} node this can either be a TR, TD or TH in the table's body
614		 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
615		 *    if given as a cell, an array of [row index, column index (visible),
616		 *    column index (all)] is given.
617		 *  @dtopt API
618		 *  @deprecated Since v1.10
619		 *
620		 *  @example
621		 *    $(document).ready(function() {
622		 *      $('#example tbody td').click( function () {
623		 *        // Get the position of the current data from the node
624		 *        var aPos = oTable.fnGetPosition( this );
625		 *
626		 *        // Get the data array for this row
627		 *        var aData = oTable.fnGetData( aPos[0] );
628		 *
629		 *        // Update the data array and return the value
630		 *        aData[ aPos[1] ] = 'clicked';
631		 *        this.innerHTML = 'clicked';
632		 *      } );
633		 *
634		 *      // Init DataTables
635		 *      oTable = $('#example').dataTable();
636		 *    } );
637		 */
638		this.fnGetPosition = function( node )
639		{
640			var api = this.api( true );
641			var nodeName = node.nodeName.toUpperCase();
642		
643			if ( nodeName == 'TR' ) {
644				return api.row( node ).index();
645			}
646			else if ( nodeName == 'TD' || nodeName == 'TH' ) {
647				var cell = api.cell( node ).index();
648		
649				return [
650					cell.row,
651					cell.columnVisible,
652					cell.column
653				];
654			}
655			return null;
656		};
657		
658		
659		/**
660		 * Check to see if a row is 'open' or not.
661		 *  @param {node} nTr the table row to check
662		 *  @returns {boolean} true if the row is currently open, false otherwise
663		 *  @dtopt API
664		 *  @deprecated Since v1.10
665		 *
666		 *  @example
667		 *    $(document).ready(function() {
668		 *      var oTable;
669		 *
670		 *      // 'open' an information row when a row is clicked on
671		 *      $('#example tbody tr').click( function () {
672		 *        if ( oTable.fnIsOpen(this) ) {
673		 *          oTable.fnClose( this );
674		 *        } else {
675		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
676		 *        }
677		 *      } );
678		 *
679		 *      oTable = $('#example').dataTable();
680		 *    } );
681		 */
682		this.fnIsOpen = function( nTr )
683		{
684			return this.api( true ).row( nTr ).child.isShown();
685		};
686		
687		
688		/**
689		 * This function will place a new row directly after a row which is currently
690		 * on display on the page, with the HTML contents that is passed into the
691		 * function. This can be used, for example, to ask for confirmation that a
692		 * particular record should be deleted.
693		 *  @param {node} nTr The table row to 'open'
694		 *  @param {string|node|jQuery} mHtml The HTML to put into the row
695		 *  @param {string} sClass Class to give the new TD cell
696		 *  @returns {node} The row opened. Note that if the table row passed in as the
697		 *    first parameter, is not found in the table, this method will silently
698		 *    return.
699		 *  @dtopt API
700		 *  @deprecated Since v1.10
701		 *
702		 *  @example
703		 *    $(document).ready(function() {
704		 *      var oTable;
705		 *
706		 *      // 'open' an information row when a row is clicked on
707		 *      $('#example tbody tr').click( function () {
708		 *        if ( oTable.fnIsOpen(this) ) {
709		 *          oTable.fnClose( this );
710		 *        } else {
711		 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
712		 *        }
713		 *      } );
714		 *
715		 *      oTable = $('#example').dataTable();
716		 *    } );
717		 */
718		this.fnOpen = function( nTr, mHtml, sClass )
719		{
720			return this.api( true )
721				.row( nTr )
722				.child( mHtml, sClass )
723				.show()
724				.child()[0];
725		};
726		
727		
728		/**
729		 * Change the pagination - provides the internal logic for pagination in a simple API
730		 * function. With this function you can have a DataTables table go to the next,
731		 * previous, first or last pages.
732		 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
733		 *    or page number to jump to (integer), note that page 0 is the first page.
734		 *  @param {bool} [bRedraw=true] Redraw the table or not
735		 *  @dtopt API
736		 *  @deprecated Since v1.10
737		 *
738		 *  @example
739		 *    $(document).ready(function() {
740		 *      var oTable = $('#example').dataTable();
741		 *      oTable.fnPageChange( 'next' );
742		 *    } );
743		 */
744		this.fnPageChange = function ( mAction, bRedraw )
745		{
746			var api = this.api( true ).page( mAction );
747		
748			if ( bRedraw === undefined || bRedraw ) {
749				api.draw(false);
750			}
751		};
752		
753		
754		/**
755		 * Show a particular column
756		 *  @param {int} iCol The column whose display should be changed
757		 *  @param {bool} bShow Show (true) or hide (false) the column
758		 *  @param {bool} [bRedraw=true] Redraw the table or not
759		 *  @dtopt API
760		 *  @deprecated Since v1.10
761		 *
762		 *  @example
763		 *    $(document).ready(function() {
764		 *      var oTable = $('#example').dataTable();
765		 *
766		 *      // Hide the second column after initialisation
767		 *      oTable.fnSetColumnVis( 1, false );
768		 *    } );
769		 */
770		this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
771		{
772			var api = this.api( true ).column( iCol ).visible( bShow );
773		
774			if ( bRedraw === undefined || bRedraw ) {
775				api.columns.adjust().draw();
776			}
777		};
778		
779		
780		/**
781		 * Get the settings for a particular table for external manipulation
782		 *  @returns {object} DataTables settings object. See
783		 *    {@link DataTable.models.oSettings}
784		 *  @dtopt API
785		 *  @deprecated Since v1.10
786		 *
787		 *  @example
788		 *    $(document).ready(function() {
789		 *      var oTable = $('#example').dataTable();
790		 *      var oSettings = oTable.fnSettings();
791		 *
792		 *      // Show an example parameter from the settings
793		 *      alert( oSettings._iDisplayStart );
794		 *    } );
795		 */
796		this.fnSettings = function()
797		{
798			return _fnSettingsFromNode( this[_ext.iApiIndex] );
799		};
800		
801		
802		/**
803		 * Sort the table by a particular column
804		 *  @param {int} iCol the data index to sort on. Note that this will not match the
805		 *    'display index' if you have hidden data entries
806		 *  @dtopt API
807		 *  @deprecated Since v1.10
808		 *
809		 *  @example
810		 *    $(document).ready(function() {
811		 *      var oTable = $('#example').dataTable();
812		 *
813		 *      // Sort immediately with columns 0 and 1
814		 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
815		 *    } );
816		 */
817		this.fnSort = function( aaSort )
818		{
819			this.api( true ).order( aaSort ).draw();
820		};
821		
822		
823		/**
824		 * Attach a sort listener to an element for a given column
825		 *  @param {node} nNode the element to attach the sort listener to
826		 *  @param {int} iColumn the column that a click on this node will sort on
827		 *  @param {function} [fnCallback] callback function when sort is run
828		 *  @dtopt API
829		 *  @deprecated Since v1.10
830		 *
831		 *  @example
832		 *    $(document).ready(function() {
833		 *      var oTable = $('#example').dataTable();
834		 *
835		 *      // Sort on column 1, when 'sorter' is clicked on
836		 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
837		 *    } );
838		 */
839		this.fnSortListener = function( nNode, iColumn, fnCallback )
840		{
841			this.api( true ).order.listener( nNode, iColumn, fnCallback );
842		};
843		
844		
845		/**
846		 * Update a table cell or row - this method will accept either a single value to
847		 * update the cell with, an array of values with one element for each column or
848		 * an object in the same format as the original data source. The function is
849		 * self-referencing in order to make the multi column updates easier.
850		 *  @param {object|array|string} mData Data to update the cell/row with
851		 *  @param {node|int} mRow TR element you want to update or the aoData index
852		 *  @param {int} [iColumn] The column to update, give as null or undefined to
853		 *    update a whole row.
854		 *  @param {bool} [bRedraw=true] Redraw the table or not
855		 *  @param {bool} [bAction=true] Perform pre-draw actions or not
856		 *  @returns {int} 0 on success, 1 on error
857		 *  @dtopt API
858		 *  @deprecated Since v1.10
859		 *
860		 *  @example
861		 *    $(document).ready(function() {
862		 *      var oTable = $('#example').dataTable();
863		 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
864		 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
865		 *    } );
866		 */
867		this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
868		{
869			var api = this.api( true );
870		
871			if ( iColumn === undefined || iColumn === null ) {
872				api.row( mRow ).data( mData );
873			}
874			else {
875				api.cell( mRow, iColumn ).data( mData );
876			}
877		
878			if ( bAction === undefined || bAction ) {
879				api.columns.adjust();
880			}
881		
882			if ( bRedraw === undefined || bRedraw ) {
883				api.draw();
884			}
885			return 0;
886		};
887		
888		
889		/**
890		 * Provide a common method for plug-ins to check the version of DataTables being used, in order
891		 * to ensure compatibility.
892		 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
893		 *    formats "X" and "X.Y" are also acceptable.
894		 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
895		 *    version, or false if this version of DataTales is not suitable
896		 *  @method
897		 *  @dtopt API
898		 *  @deprecated Since v1.10
899		 *
900		 *  @example
901		 *    $(document).ready(function() {
902		 *      var oTable = $('#example').dataTable();
903		 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
904		 *    } );
905		 */
906		this.fnVersionCheck = _ext.fnVersionCheck;
907		
vendor: 13,127 bytes, lines 908-1320
908
909		var _that = this;
910		var emptyInit = options === undefined;
911		var len = this.length;
912
913		if ( emptyInit ) {
914			options = {};
915		}
916
917		this.oApi = this.internal = _ext.internal;
918
919		// Extend with old style plug-in API methods
920		for ( var fn in DataTable.ext.internal ) {
921			if ( fn ) {
922				this[fn] = _fnExternApiFunc(fn);
923			}
924		}
925
926		this.each(function() {
927			// For each initialisation we want to give it a clean initialisation
928			// object that can be bashed around
929			var o = {};
930			var oInit = len > 1 ? // optimisation for single table case
931				_fnExtend( o, options, true ) :
932				options;
933
934			/*global oInit,_that,emptyInit*/
935			var i=0, iLen, j, jLen, k, kLen;
936			var sId = this.getAttribute( 'id' );
937			var bInitHandedOff = false;
938			var defaults = DataTable.defaults;
939			var $this = $(this);
940			
941			
942			/* Sanity check */
943			if ( this.nodeName.toLowerCase() != 'table' )
944			{
945				_fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
946				return;
947			}
948			
949			/* Backwards compatibility for the defaults */
950			_fnCompatOpts( defaults );
951			_fnCompatCols( defaults.column );
952			
953			/* Convert the camel-case defaults to Hungarian */
954			_fnCamelToHungarian( defaults, defaults, true );
955			_fnCamelToHungarian( defaults.column, defaults.column, true );
956			
957			/* Setting up the initialisation object */
958			_fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
959			
960			
961			
962			/* Check to see if we are re-initialising a table */
963			var allSettings = DataTable.settings;
964			for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
965			{
966				var s = allSettings[i];
967			
968				/* Base check on table node */
969				if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
970				{
971					var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
972					var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
973			
974					if ( emptyInit || bRetrieve )
975					{
976						return s.oInstance;
977					}
978					else if ( bDestroy )
979					{
980						s.oInstance.fnDestroy();
981						break;
982					}
983					else
984					{
985						_fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
986						return;
987					}
988				}
989			
990				/* If the element we are initialising has the same ID as a table which was previously
991				 * initialised, but the table nodes don't match (from before) then we destroy the old
992				 * instance by simply deleting it. This is under the assumption that the table has been
993				 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
994				 */
995				if ( s.sTableId == this.id )
996				{
997					allSettings.splice( i, 1 );
998					break;
999				}
1000			}
1001			
1002			/* Ensure the table has an ID - required for accessibility */
1003			if ( sId === null || sId === "" )
1004			{
1005				sId = "DataTables_Table_"+(DataTable.ext._unique++);
1006				this.id = sId;
1007			}
1008			
1009			/* Create the settings object for this table and set some of the default parameters */
1010			var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
1011				"sDestroyWidth": $this[0].style.width,
1012				"sInstance":     sId,
1013				"sTableId":      sId
1014			} );
1015			oSettings.nTable = this;
1016			oSettings.oApi   = _that.internal;
1017			oSettings.oInit  = oInit;
1018			
1019			allSettings.push( oSettings );
1020			
1021			// Need to add the instance after the instance after the settings object has been added
1022			// to the settings array, so we can self reference the table instance if more than one
1023			oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
1024			
1025			// Backwards compatibility, before we apply all the defaults
1026			_fnCompatOpts( oInit );
1027			
1028			if ( oInit.oLanguage )
1029			{
1030				_fnLanguageCompat( oInit.oLanguage );
1031			}
1032			
1033			// If the length menu is given, but the init display length is not, use the length menu
1034			if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
1035			{
1036				oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
1037					oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
1038			}
1039			
1040			// Apply the defaults and init options to make a single init object will all
1041			// options defined from defaults and instance options.
1042			oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
1043			
1044			
1045			// Map the initialisation options onto the settings object
1046			_fnMap( oSettings.oFeatures, oInit, [
1047				"bPaginate",
1048				"bLengthChange",
1049				"bFilter",
1050				"bSort",
1051				"bSortMulti",
1052				"bInfo",
1053				"bProcessing",
1054				"bAutoWidth",
1055				"bSortClasses",
1056				"bServerSide",
1057				"bDeferRender"
1058			] );
1059			_fnMap( oSettings, oInit, [
1060				"asStripeClasses",
1061				"ajax",
1062				"fnServerData",
1063				"fnFormatNumber",
1064				"sServerMethod",
1065				"aaSorting",
1066				"aaSortingFixed",
1067				"aLengthMenu",
1068				"sPaginationType",
1069				"sAjaxSource",
1070				"sAjaxDataProp",
1071				"iStateDuration",
1072				"sDom",
1073				"bSortCellsTop",
1074				"iTabIndex",
1075				"fnStateLoadCallback",
1076				"fnStateSaveCallback",
1077				"renderer",
1078				"searchDelay",
1079				"rowId",
1080				[ "iCookieDuration", "iStateDuration" ], // backwards compat
1081				[ "oSearch", "oPreviousSearch" ],
1082				[ "aoSearchCols", "aoPreSearchCols" ],
1083				[ "iDisplayLength", "_iDisplayLength" ]
1084			] );
1085			_fnMap( oSettings.oScroll, oInit, [
1086				[ "sScrollX", "sX" ],
1087				[ "sScrollXInner", "sXInner" ],
1088				[ "sScrollY", "sY" ],
1089				[ "bScrollCollapse", "bCollapse" ]
1090			] );
1091			_fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1092			
1093			/* Callback functions which are array driven */
1094			_fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1095			_fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1096			_fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1097			_fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1098			_fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1099			_fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1100			_fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1101			_fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1102			_fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1103			_fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1104			_fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1105			
1106			oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1107			
1108			/* Browser support detection */
1109			_fnBrowserDetect( oSettings );
1110			
1111			var oClasses = oSettings.oClasses;
1112			
1113			$.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1114			$this.addClass( oClasses.sTable );
1115			
1116			
1117			if ( oSettings.iInitDisplayStart === undefined )
1118			{
1119				/* Display start point, taking into account the save saving */
1120				oSettings.iInitDisplayStart = oInit.iDisplayStart;
1121				oSettings._iDisplayStart = oInit.iDisplayStart;
1122			}
1123			
1124			if ( oInit.iDeferLoading !== null )
1125			{
1126				oSettings.bDeferLoading = true;
1127				var tmp = $.isArray( oInit.iDeferLoading );
1128				oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1129				oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1130			}
1131			
1132			/* Language definitions */
1133			var oLanguage = oSettings.oLanguage;
1134			$.extend( true, oLanguage, oInit.oLanguage );
1135			
1136			if ( oLanguage.sUrl )
1137			{
1138				/* Get the language definitions from a file - because this Ajax call makes the language
1139				 * get async to the remainder of this function we use bInitHandedOff to indicate that
1140				 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1141				 */
1142				$.ajax( {
1143					dataType: 'json',
1144					url: oLanguage.sUrl,
1145					success: function ( json ) {
1146						_fnLanguageCompat( json );
1147						_fnCamelToHungarian( defaults.oLanguage, json );
1148						$.extend( true, oLanguage, json );
1149						_fnInitialise( oSettings );
1150					},
1151					error: function () {
1152						// Error occurred loading language file, continue on as best we can
1153						_fnInitialise( oSettings );
1154					}
1155				} );
1156				bInitHandedOff = true;
1157			}
1158			
1159			/*
1160			 * Stripes
1161			 */
1162			if ( oInit.asStripeClasses === null )
1163			{
1164				oSettings.asStripeClasses =[
1165					oClasses.sStripeOdd,
1166					oClasses.sStripeEven
1167				];
1168			}
1169			
1170			/* Remove row stripe classes if they are already on the table row */
1171			var stripeClasses = oSettings.asStripeClasses;
1172			var rowOne = $this.children('tbody').find('tr').eq(0);
1173			if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1174				return rowOne.hasClass(el);
1175			} ) ) !== -1 ) {
1176				$('tbody tr', this).removeClass( stripeClasses.join(' ') );
1177				oSettings.asDestroyStripes = stripeClasses.slice();
1178			}
1179			
1180			/*
1181			 * Columns
1182			 * See if we should load columns automatically or use defined ones
1183			 */
1184			var anThs = [];
1185			var aoColumnsInit;
1186			var nThead = this.getElementsByTagName('thead');
1187			if ( nThead.length !== 0 )
1188			{
1189				_fnDetectHeader( oSettings.aoHeader, nThead[0] );
1190				anThs = _fnGetUniqueThs( oSettings );
1191			}
1192			
1193			/* If not given a column array, generate one with nulls */
1194			if ( oInit.aoColumns === null )
1195			{
1196				aoColumnsInit = [];
1197				for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1198				{
1199					aoColumnsInit.push( null );
1200				}
1201			}
1202			else
1203			{
1204				aoColumnsInit = oInit.aoColumns;
1205			}
1206			
1207			/* Add the columns */
1208			for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1209			{
1210				_fnAddColumn( oSettings, anThs ? anThs[i] : null );
1211			}
1212			
1213			/* Apply the column definitions */
1214			_fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1215				_fnColumnOptions( oSettings, iCol, oDef );
1216			} );
1217			
1218			/* HTML5 attribute detection - build an mData object automatically if the
1219			 * attributes are found
1220			 */
1221			if ( rowOne.length ) {
1222				var a = function ( cell, name ) {
1223					return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1224				};
1225			
1226				$( rowOne[0] ).children('th, td').each( function (i, cell) {
1227					var col = oSettings.aoColumns[i];
1228			
1229					if ( col.mData === i ) {
1230						var sort = a( cell, 'sort' ) || a( cell, 'order' );
1231						var filter = a( cell, 'filter' ) || a( cell, 'search' );
1232			
1233						if ( sort !== null || filter !== null ) {
1234							col.mData = {
1235								_:      i+'.display',
1236								sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1237								type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1238								filter: filter !== null ? i+'.@data-'+filter : undefined
1239							};
1240			
1241							_fnColumnOptions( oSettings, i );
1242						}
1243					}
1244				} );
1245			}
1246			
1247			var features = oSettings.oFeatures;
1248			var loadedInit = function () {
1249				/*
1250				 * Sorting
1251				 * @todo For modularisation (1.11) this needs to do into a sort start up handler
1252				 */
1253			
1254				// If aaSorting is not defined, then we use the first indicator in asSorting
1255				// in case that has been altered, so the default sort reflects that option
1256				if ( oInit.aaSorting === undefined ) {
1257					var sorting = oSettings.aaSorting;
1258					for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1259						sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1260					}
1261				}
1262			
1263				/* Do a first pass on the sorting classes (allows any size changes to be taken into
1264				 * account, and also will apply sorting disabled classes if disabled
1265				 */
1266				_fnSortingClasses( oSettings );
1267			
1268				if ( features.bSort ) {
1269					_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1270						if ( oSettings.bSorted ) {
1271							var aSort = _fnSortFlatten( oSettings );
1272							var sortedColumns = {};
1273			
1274							$.each( aSort, function (i, val) {
1275								sortedColumns[ val.src ] = val.dir;
1276							} );
1277			
1278							_fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1279							_fnSortAria( oSettings );
1280						}
1281					} );
1282				}
1283			
1284				_fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1285					if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1286						_fnSortingClasses( oSettings );
1287					}
1288				}, 'sc' );
1289			
1290			
1291				/*
1292				 * Final init
1293				 * Cache the header, body and footer as required, creating them if needed
1294				 */
1295			
1296				// Work around for Webkit bug 83867 - store the caption-side before removing from doc
1297				var captions = $this.children('caption').each( function () {
1298					this._captionSide = $(this).css('caption-side');
1299				} );
1300			
1301				var thead = $this.children('thead');
1302				if ( thead.length === 0 ) {
1303					thead = $('<thead/>').appendTo($this);
1304				}
1305				oSettings.nTHead = thead[0];
1306			
1307				var tbody = $this.children('tbody');
1308				if ( tbody.length === 0 ) {
1309					tbody = $('<tbody/>').appendTo($this);
1310				}
1311				oSettings.nTBody = tbody[0];
1312			
1313				var tfoot = $this.children('tfoot');
1314				if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1315					// If we are a scrolling table, and no footer has been given, then we need to create
1316					// a tfoot element for the caption element to be appended to
1317					tfoot = $('<tfoot/>').appendTo($this);
1318				}
1319			
1320				if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1321					$this.addClass( oClasses.sNoFooter );
1322				}
1323				else if ( tfoot.length > 0 ) {
1324					oSettings.nTFoot = tfoot[0];
1325					_fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1326				}
1327			
1328				/* Check if there is data passing into the constructor */
1329				if ( oInit.aaData ) {
1330					for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1331						_fnAddData( oSettings, oInit.aaData[ i ] );
1332					}
1333				}
1334				else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1335					/* Grab the data from the page - only do this when deferred loading or no Ajax
1336					 * source since there is no point in reading the DOM data if we are then going
1337					 * to replace it with Ajax data
1338					 */
1339					_fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1340				}
1341			
1342				/* Copy the data index array */
1343				oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1344			
1345				/* Initialisation complete - table can be drawn */
1346				oSettings.bInitialised = true;
1347			
1348				/* Check if we need to initialise the table (it might not have been handed off to the
1349				 * language processor)
1350				 */
1351				if ( bInitHandedOff === false ) {
1352					_fnInitialise( oSettings );
1353				}
1354			};
1355			
1356			/* Must be done after everything which can be overridden by the state saving! */
1357			if ( oInit.bStateSave )
1358			{
1359				features.bStateSave = true;
1360				_fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1361				_fnLoadState( oSettings, oInit, loadedInit );
1362			}
1363			else {
1364				loadedInit();
1365			}
1366			
1367		} );
1368		_that = null;
1369		return this;
1370	};
1371
1372	
1373	/*
1374	 * It is useful to have variables which are scoped locally so only the
1375	 * DataTables functions can access them and they don't leak into global space.
1376	 * At the same time these functions are often useful over multiple files in the
1377	 * core and API, so we list, or at least document, all variables which are used
1378	 * by DataTables as private variables here. This also ensures that there is no
1379	 * clashing of variable names and that they can easily referenced for reuse.
1380	 */
1381	
1382	
1383	// Defined else where
1384	//  _selector_run
1385	//  _selector_opts
1386	//  _selector_first
1387	//  _selector_row_indexes
1388	
1389	var _ext; // DataTable.ext
1390	var _Api; // DataTable.Api
1391	var _api_register; // DataTable.Api.register
1392	var _api_registerPlural; // DataTable.Api.registerPlural
1393	
1394	var _re_dic = {};
1395	var _re_new_lines = /[\r\n]/g;
1396	var _re_html = /<.*?>/g;
1397	
1398	// This is not strict ISO8601 - Date.parse() is quite lax, although
1399	// implementations differ between browsers.
1400	var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1401	
1402	// Escape regular expression special characters
1403	var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1404	
1405	// http://en.wikipedia.org/wiki/Foreign_exchange_market
1406	// - \u20BD - Russian ruble.
1407	// - \u20a9 - South Korean Won
1408	// - \u20BA - Turkish Lira
1409	// - \u20B9 - Indian Rupee
1410	// - R - Brazil (R$) and South Africa
1411	// - fr - Swiss Franc
1412	// - kr - Swedish krona, Norwegian krone and Danish krone
1413	// - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1414	//   standards as thousands separators.
1415	var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
1416	
1417	
1418	var _empty = function ( d ) {
1419		return !d || d === true || d === '-' ? true : false;
1420	};
1421	
1422	
1423	var _intVal = function ( s ) {
1424		var integer = parseInt( s, 10 );
1425		return !isNaN(integer) && isFinite(s) ? integer : null;
1426	};
1427	
1428	// Convert from a formatted number with characters other than `.` as the
1429	// decimal place, to a Javascript number
1430	var _numToDecimal = function ( num, decimalPoint ) {
1431		// Cache created regular expressions for speed as this function is called often
1432		if ( ! _re_dic[ decimalPoint ] ) {
1433			_re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1434		}
1435		return typeof num === 'string' && decimalPoint !== '.' ?
1436			num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1437			num;
1438	};
1439	
1440	
1441	var _isNumber = function ( d, decimalPoint, formatted ) {
1442		var strType = typeof d === 'string';
1443	
1444		// If empty return immediately so there must be a number if it is a
1445		// formatted string (this stops the string "k", or "kr", etc being detected
1446		// as a formatted number for currency
1447		if ( _empty( d ) ) {
1448			return true;
1449		}
1450	
1451		if ( decimalPoint && strType ) {
1452			d = _numToDecimal( d, decimalPoint );
1453		}
1454	
1455		if ( formatted && strType ) {
1456			d = d.replace( _re_formatted_numeric, '' );
1457		}
1458	
1459		return !isNaN( parseFloat(d) ) && isFinite( d );
1460	};
1461	
1462	
1463	// A string without HTML in it can be considered to be HTML still
1464	var _isHtml = function ( d ) {
1465		return _empty( d ) || typeof d === 'string';
1466	};
1467	
1468	
1469	var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1470		if ( _empty( d ) ) {
1471			return true;
1472		}
1473	
1474		var html = _isHtml( d );
1475		return ! html ?
1476			null :
1477			_isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1478				true :
1479				null;
1480	};
1481	
1482	
1483	var _pluck = function ( a, prop, prop2 ) {
1484		var out = [];
1485		var i=0, ien=a.length;
1486	
1487		// Could have the test in the loop for slightly smaller code, but speed
1488		// is essential here
1489		if ( prop2 !== undefined ) {
1490			for ( ; i<ien ; i++ ) {
1491				if ( a[i] && a[i][ prop ] ) {
1492					out.push( a[i][ prop ][ prop2 ] );
1493				}
1494			}
1495		}
1496		else {
1497			for ( ; i<ien ; i++ ) {
1498				if ( a[i] ) {
1499					out.push( a[i][ prop ] );
1500				}
1501			}
1502		}
1503	
1504		return out;
1505	};
1506	
1507	
1508	// Basically the same as _pluck, but rather than looping over `a` we use `order`
1509	// as the indexes to pick from `a`
1510	var _pluck_order = function ( a, order, prop, prop2 )
1511	{
1512		var out = [];
1513		var i=0, ien=order.length;
1514	
1515		// Could have the test in the loop for slightly smaller code, but speed
1516		// is essential here
1517		if ( prop2 !== undefined ) {
1518			for ( ; i<ien ; i++ ) {
1519				if ( a[ order[i] ][ prop ] ) {
1520					out.push( a[ order[i] ][ prop ][ prop2 ] );
1521				}
1522			}
1523		}
1524		else {
1525			for ( ; i<ien ; i++ ) {
1526				out.push( a[ order[i] ][ prop ] );
1527			}
1528		}
1529	
1530		return out;
1531	};
1532	
1533	
1534	var _range = function ( len, start )
1535	{
1536		var out = [];
1537		var end;
1538	
1539		if ( start === undefined ) {
1540			start = 0;
1541			end = len;
1542		}
1543		else {
1544			end = start;
1545			start = len;
1546		}
1547	
1548		for ( var i=start ; i<end ; i++ ) {
1549			out.push( i );
1550		}
1551	
1552		return out;
1553	};
1554	
1555	
1556	var _removeEmpty = function ( a )
1557	{
1558		var out = [];
1559	
1560		for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1561			if ( a[i] ) { // careful - will remove all falsy values!
1562				out.push( a[i] );
1563			}
1564		}
1565	
1566		return out;
1567	};
1568	
1569	
1570	var _stripHtml = function ( d ) {
1571		return d.replace( _re_html, '' );
1572	};
1573	
1574	
1575	/**
1576	 * Determine if all values in the array are unique. This means we can short
1577	 * cut the _unique method at the cost of a single loop. A sorted array is used
1578	 * to easily check the values.
1579	 *
1580	 * @param  {array} src Source array
1581	 * @return {boolean} true if all unique, false otherwise
1582	 * @ignore
1583	 */
1584	var _areAllUnique = function ( src ) {
1585		if ( src.length < 2 ) {
1586			return true;
1587		}
1588	
1589		var sorted = src.slice().sort();
1590		var last = sorted[0];
1591	
1592		for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1593			if ( sorted[i] === last ) {
1594				return false;
vendor: 37,141 bytes, lines 1595-2917
1595			}
1596	
1597			last = sorted[i];
1598		}
1599	
1600		return true;
1601	};
1602	
1603	
1604	/**
1605	 * Find the unique elements in a source array.
1606	 *
1607	 * @param  {array} src Source array
1608	 * @return {array} Array of unique items
1609	 * @ignore
1610	 */
1611	var _unique = function ( src )
1612	{
1613		if ( _areAllUnique( src ) ) {
1614			return src.slice();
1615		}
1616	
1617		// A faster unique method is to use object keys to identify used values,
1618		// but this doesn't work with arrays or objects, which we must also
1619		// consider. See jsperf.com/compare-array-unique-versions/4 for more
1620		// information.
1621		var
1622			out = [],
1623			val,
1624			i, ien=src.length,
1625			j, k=0;
1626	
1627		again: for ( i=0 ; i<ien ; i++ ) {
1628			val = src[i];
1629	
1630			for ( j=0 ; j<k ; j++ ) {
1631				if ( out[j] === val ) {
1632					continue again;
1633				}
1634			}
1635	
1636			out.push( val );
1637			k++;
1638		}
1639	
1640		return out;
1641	};
1642	
1643	
1644	/**
1645	 * DataTables utility methods
1646	 * 
1647	 * This namespace provides helper methods that DataTables uses internally to
1648	 * create a DataTable, but which are not exclusively used only for DataTables.
1649	 * These methods can be used by extension authors to save the duplication of
1650	 * code.
1651	 *
1652	 *  @namespace
1653	 */
1654	DataTable.util = {
1655		/**
1656		 * Throttle the calls to a function. Arguments and context are maintained
1657		 * for the throttled function.
1658		 *
1659		 * @param {function} fn Function to be called
1660		 * @param {integer} freq Call frequency in mS
1661		 * @return {function} Wrapped function
1662		 */
1663		throttle: function ( fn, freq ) {
1664			var
1665				frequency = freq !== undefined ? freq : 200,
1666				last,
1667				timer;
1668	
1669			return function () {
1670				var
1671					that = this,
1672					now  = +new Date(),
1673					args = arguments;
1674	
1675				if ( last && now < last + frequency ) {
1676					clearTimeout( timer );
1677	
1678					timer = setTimeout( function () {
1679						last = undefined;
1680						fn.apply( that, args );
1681					}, frequency );
1682				}
1683				else {
1684					last = now;
1685					fn.apply( that, args );
1686				}
1687			};
1688		},
1689	
1690	
1691		/**
1692		 * Escape a string such that it can be used in a regular expression
1693		 *
1694		 *  @param {string} val string to escape
1695		 *  @returns {string} escaped string
1696		 */
1697		escapeRegex: function ( val ) {
1698			return val.replace( _re_escape_regex, '\\$1' );
1699		}
1700	};
1701	
1702	
1703	
1704	/**
1705	 * Create a mapping object that allows camel case parameters to be looked up
1706	 * for their Hungarian counterparts. The mapping is stored in a private
1707	 * parameter called `_hungarianMap` which can be accessed on the source object.
1708	 *  @param {object} o
1709	 *  @memberof DataTable#oApi
1710	 */
1711	function _fnHungarianMap ( o )
1712	{
1713		var
1714			hungarian = 'a aa ai ao as b fn i m o s ',
1715			match,
1716			newKey,
1717			map = {};
1718	
1719		$.each( o, function (key, val) {
1720			match = key.match(/^([^A-Z]+?)([A-Z])/);
1721	
1722			if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1723			{
1724				newKey = key.replace( match[0], match[2].toLowerCase() );
1725				map[ newKey ] = key;
1726	
1727				if ( match[1] === 'o' )
1728				{
1729					_fnHungarianMap( o[key] );
1730				}
1731			}
1732		} );
1733	
1734		o._hungarianMap = map;
1735	}
1736	
1737	
1738	/**
1739	 * Convert from camel case parameters to Hungarian, based on a Hungarian map
1740	 * created by _fnHungarianMap.
1741	 *  @param {object} src The model object which holds all parameters that can be
1742	 *    mapped.
1743	 *  @param {object} user The object to convert from camel case to Hungarian.
1744	 *  @param {boolean} force When set to `true`, properties which already have a
1745	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
1746	 *    won't be.
1747	 *  @memberof DataTable#oApi
1748	 */
1749	function _fnCamelToHungarian ( src, user, force )
1750	{
1751		if ( ! src._hungarianMap ) {
1752			_fnHungarianMap( src );
1753		}
1754	
1755		var hungarianKey;
1756	
1757		$.each( user, function (key, val) {
1758			hungarianKey = src._hungarianMap[ key ];
1759	
1760			if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1761			{
1762				// For objects, we need to buzz down into the object to copy parameters
1763				if ( hungarianKey.charAt(0) === 'o' )
1764				{
1765					// Copy the camelCase options over to the hungarian
1766					if ( ! user[ hungarianKey ] ) {
1767						user[ hungarianKey ] = {};
1768					}
1769					$.extend( true, user[hungarianKey], user[key] );
1770	
1771					_fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1772				}
1773				else {
1774					user[hungarianKey] = user[ key ];
1775				}
1776			}
1777		} );
1778	}
1779	
1780	
1781	/**
1782	 * Language compatibility - when certain options are given, and others aren't, we
1783	 * need to duplicate the values over, in order to provide backwards compatibility
1784	 * with older language files.
1785	 *  @param {object} oSettings dataTables settings object
1786	 *  @memberof DataTable#oApi
1787	 */
1788	function _fnLanguageCompat( lang )
1789	{
1790		var defaults = DataTable.defaults.oLanguage;
1791		var zeroRecords = lang.sZeroRecords;
1792	
1793		/* Backwards compatibility - if there is no sEmptyTable given, then use the same as
1794		 * sZeroRecords - assuming that is given.
1795		 */
1796		if ( ! lang.sEmptyTable && zeroRecords &&
1797			defaults.sEmptyTable === "No data available in table" )
1798		{
1799			_fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1800		}
1801	
1802		/* Likewise with loading records */
1803		if ( ! lang.sLoadingRecords && zeroRecords &&
1804			defaults.sLoadingRecords === "Loading..." )
1805		{
1806			_fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1807		}
1808	
1809		// Old parameter name of the thousands separator mapped onto the new
1810		if ( lang.sInfoThousands ) {
1811			lang.sThousands = lang.sInfoThousands;
1812		}
1813	
1814		var decimal = lang.sDecimal;
1815		if ( decimal ) {
1816			_addNumericSort( decimal );
1817		}
1818	}
1819	
1820	
1821	/**
1822	 * Map one parameter onto another
1823	 *  @param {object} o Object to map
1824	 *  @param {*} knew The new parameter name
1825	 *  @param {*} old The old parameter name
1826	 */
1827	var _fnCompatMap = function ( o, knew, old ) {
1828		if ( o[ knew ] !== undefined ) {
1829			o[ old ] = o[ knew ];
1830		}
1831	};
1832	
1833	
1834	/**
1835	 * Provide backwards compatibility for the main DT options. Note that the new
1836	 * options are mapped onto the old parameters, so this is an external interface
1837	 * change only.
1838	 *  @param {object} init Object to map
1839	 */
1840	function _fnCompatOpts ( init )
1841	{
1842		_fnCompatMap( init, 'ordering',      'bSort' );
1843		_fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1844		_fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1845		_fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1846		_fnCompatMap( init, 'order',         'aaSorting' );
1847		_fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1848		_fnCompatMap( init, 'paging',        'bPaginate' );
1849		_fnCompatMap( init, 'pagingType',    'sPaginationType' );
1850		_fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1851		_fnCompatMap( init, 'searching',     'bFilter' );
1852	
1853		// Boolean initialisation of x-scrolling
1854		if ( typeof init.sScrollX === 'boolean' ) {
1855			init.sScrollX = init.sScrollX ? '100%' : '';
1856		}
1857		if ( typeof init.scrollX === 'boolean' ) {
1858			init.scrollX = init.scrollX ? '100%' : '';
1859		}
1860	
1861		// Column search objects are in an array, so it needs to be converted
1862		// element by element
1863		var searchCols = init.aoSearchCols;
1864	
1865		if ( searchCols ) {
1866			for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1867				if ( searchCols[i] ) {
1868					_fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1869				}
1870			}
1871		}
1872	}
1873	
1874	
1875	/**
1876	 * Provide backwards compatibility for column options. Note that the new options
1877	 * are mapped onto the old parameters, so this is an external interface change
1878	 * only.
1879	 *  @param {object} init Object to map
1880	 */
1881	function _fnCompatCols ( init )
1882	{
1883		_fnCompatMap( init, 'orderable',     'bSortable' );
1884		_fnCompatMap( init, 'orderData',     'aDataSort' );
1885		_fnCompatMap( init, 'orderSequence', 'asSorting' );
1886		_fnCompatMap( init, 'orderDataType', 'sortDataType' );
1887	
1888		// orderData can be given as an integer
1889		var dataSort = init.aDataSort;
1890		if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1891			init.aDataSort = [ dataSort ];
1892		}
1893	}
1894	
1895	
1896	/**
1897	 * Browser feature detection for capabilities, quirks
1898	 *  @param {object} settings dataTables settings object
1899	 *  @memberof DataTable#oApi
1900	 */
1901	function _fnBrowserDetect( settings )
1902	{
1903		// We don't need to do this every time DataTables is constructed, the values
1904		// calculated are specific to the browser and OS configuration which we
1905		// don't expect to change between initialisations
1906		if ( ! DataTable.__browser ) {
1907			var browser = {};
1908			DataTable.__browser = browser;
1909	
1910			// Scrolling feature / quirks detection
1911			var n = $('<div/>')
1912				.css( {
1913					position: 'fixed',
1914					top: 0,
1915					left: $(window).scrollLeft()*-1, // allow for scrolling
1916					height: 1,
1917					width: 1,
1918					overflow: 'hidden'
1919				} )
1920				.append(
1921					$('<div/>')
1922						.css( {
1923							position: 'absolute',
1924							top: 1,
1925							left: 1,
1926							width: 100,
1927							overflow: 'scroll'
1928						} )
1929						.append(
1930							$('<div/>')
1931								.css( {
1932									width: '100%',
1933									height: 10
1934								} )
1935						)
1936				)
1937				.appendTo( 'body' );
1938	
1939			var outer = n.children();
1940			var inner = outer.children();
1941	
1942			// Numbers below, in order, are:
1943			// inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1944			//
1945			// IE6 XP:                           100 100 100  83
1946			// IE7 Vista:                        100 100 100  83
1947			// IE 8+ Windows:                     83  83 100  83
1948			// Evergreen Windows:                 83  83 100  83
1949			// Evergreen Mac with scrollbars:     85  85 100  85
1950			// Evergreen Mac without scrollbars: 100 100 100 100
1951	
1952			// Get scrollbar width
1953			browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1954	
1955			// IE6/7 will oversize a width 100% element inside a scrolling element, to
1956			// include the width of the scrollbar, while other browsers ensure the inner
1957			// element is contained without forcing scrolling
1958			browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1959	
1960			// In rtl text layout, some browsers (most, but not all) will place the
1961			// scrollbar on the left, rather than the right.
1962			browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1963	
1964			// IE8- don't provide height and width for getBoundingClientRect
1965			browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1966	
1967			n.remove();
1968		}
1969	
1970		$.extend( settings.oBrowser, DataTable.__browser );
1971		settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1972	}
1973	
1974	
1975	/**
1976	 * Array.prototype reduce[Right] method, used for browsers which don't support
1977	 * JS 1.6. Done this way to reduce code size, since we iterate either way
1978	 *  @param {object} settings dataTables settings object
1979	 *  @memberof DataTable#oApi
1980	 */
1981	function _fnReduce ( that, fn, init, start, end, inc )
1982	{
1983		var
1984			i = start,
1985			value,
1986			isSet = false;
1987	
1988		if ( init !== undefined ) {
1989			value = init;
1990			isSet = true;
1991		}
1992	
1993		while ( i !== end ) {
1994			if ( ! that.hasOwnProperty(i) ) {
1995				continue;
1996			}
1997	
1998			value = isSet ?
1999				fn( value, that[i], i, that ) :
2000				that[i];
2001	
2002			isSet = true;
2003			i += inc;
2004		}
2005	
2006		return value;
2007	}
2008	
2009	/**
2010	 * Add a column to the list used for the table with default values
2011	 *  @param {object} oSettings dataTables settings object
2012	 *  @param {node} nTh The th element for this column
2013	 *  @memberof DataTable#oApi
2014	 */
2015	function _fnAddColumn( oSettings, nTh )
2016	{
2017		// Add column to aoColumns array
2018		var oDefaults = DataTable.defaults.column;
2019		var iCol = oSettings.aoColumns.length;
2020		var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
2021			"nTh": nTh ? nTh : document.createElement('th'),
2022			"sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
2023			"aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
2024			"mData": oDefaults.mData ? oDefaults.mData : iCol,
2025			idx: iCol
2026		} );
2027		oSettings.aoColumns.push( oCol );
2028	
2029		// Add search object for column specific search. Note that the `searchCols[ iCol ]`
2030		// passed into extend can be undefined. This allows the user to give a default
2031		// with only some of the parameters defined, and also not give a default
2032		var searchCols = oSettings.aoPreSearchCols;
2033		searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2034	
2035		// Use the default column options function to initialise classes etc
2036		_fnColumnOptions( oSettings, iCol, $(nTh).data() );
2037	}
2038	
2039	
2040	/**
2041	 * Apply options for a column
2042	 *  @param {object} oSettings dataTables settings object
2043	 *  @param {int} iCol column index to consider
2044	 *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2045	 *  @memberof DataTable#oApi
2046	 */
2047	function _fnColumnOptions( oSettings, iCol, oOptions )
2048	{
2049		var oCol = oSettings.aoColumns[ iCol ];
2050		var oClasses = oSettings.oClasses;
2051		var th = $(oCol.nTh);
2052	
2053		// Try to get width information from the DOM. We can't get it from CSS
2054		// as we'd need to parse the CSS stylesheet. `width` option can override
2055		if ( ! oCol.sWidthOrig ) {
2056			// Width attribute
2057			oCol.sWidthOrig = th.attr('width') || null;
2058	
2059			// Style attribute
2060			var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2061			if ( t ) {
2062				oCol.sWidthOrig = t[1];
2063			}
2064		}
2065	
2066		/* User specified column options */
2067		if ( oOptions !== undefined && oOptions !== null )
2068		{
2069			// Backwards compatibility
2070			_fnCompatCols( oOptions );
2071	
2072			// Map camel case parameters to their Hungarian counterparts
2073			_fnCamelToHungarian( DataTable.defaults.column, oOptions );
2074	
2075			/* Backwards compatibility for mDataProp */
2076			if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2077			{
2078				oOptions.mData = oOptions.mDataProp;
2079			}
2080	
2081			if ( oOptions.sType )
2082			{
2083				oCol._sManualType = oOptions.sType;
2084			}
2085	
2086			// `class` is a reserved word in Javascript, so we need to provide
2087			// the ability to use a valid name for the camel case input
2088			if ( oOptions.className && ! oOptions.sClass )
2089			{
2090				oOptions.sClass = oOptions.className;
2091			}
2092			if ( oOptions.sClass ) {
2093				th.addClass( oOptions.sClass );
2094			}
2095	
2096			$.extend( oCol, oOptions );
2097			_fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2098	
2099			/* iDataSort to be applied (backwards compatibility), but aDataSort will take
2100			 * priority if defined
2101			 */
2102			if ( oOptions.iDataSort !== undefined )
2103			{
2104				oCol.aDataSort = [ oOptions.iDataSort ];
2105			}
2106			_fnMap( oCol, oOptions, "aDataSort" );
2107		}
2108	
2109		/* Cache the data get and set functions for speed */
2110		var mDataSrc = oCol.mData;
2111		var mData = _fnGetObjectDataFn( mDataSrc );
2112		var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2113	
2114		var attrTest = function( src ) {
2115			return typeof src === 'string' && src.indexOf('@') !== -1;
2116		};
2117		oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2118			attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2119		);
2120		oCol._setter = null;
2121	
2122		oCol.fnGetData = function (rowData, type, meta) {
2123			var innerData = mData( rowData, type, undefined, meta );
2124	
2125			return mRender && type ?
2126				mRender( innerData, type, rowData, meta ) :
2127				innerData;
2128		};
2129		oCol.fnSetData = function ( rowData, val, meta ) {
2130			return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2131		};
2132	
2133		// Indicate if DataTables should read DOM data as an object or array
2134		// Used in _fnGetRowElements
2135		if ( typeof mDataSrc !== 'number' ) {
2136			oSettings._rowReadObject = true;
2137		}
2138	
2139		/* Feature sorting overrides column specific when off */
2140		if ( !oSettings.oFeatures.bSort )
2141		{
2142			oCol.bSortable = false;
2143			th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2144		}
2145	
2146		/* Check that the class assignment is correct for sorting */
2147		var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2148		var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2149		if ( !oCol.bSortable || (!bAsc && !bDesc) )
2150		{
2151			oCol.sSortingClass = oClasses.sSortableNone;
2152			oCol.sSortingClassJUI = "";
2153		}
2154		else if ( bAsc && !bDesc )
2155		{
2156			oCol.sSortingClass = oClasses.sSortableAsc;
2157			oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2158		}
2159		else if ( !bAsc && bDesc )
2160		{
2161			oCol.sSortingClass = oClasses.sSortableDesc;
2162			oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2163		}
2164		else
2165		{
2166			oCol.sSortingClass = oClasses.sSortable;
2167			oCol.sSortingClassJUI = oClasses.sSortJUI;
2168		}
2169	}
2170	
2171	
2172	/**
2173	 * Adjust the table column widths for new data. Note: you would probably want to
2174	 * do a redraw after calling this function!
2175	 *  @param {object} settings dataTables settings object
2176	 *  @memberof DataTable#oApi
2177	 */
2178	function _fnAdjustColumnSizing ( settings )
2179	{
2180		/* Not interested in doing column width calculation if auto-width is disabled */
2181		if ( settings.oFeatures.bAutoWidth !== false )
2182		{
2183			var columns = settings.aoColumns;
2184	
2185			_fnCalculateColumnWidths( settings );
2186			for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2187			{
2188				columns[i].nTh.style.width = columns[i].sWidth;
2189			}
2190		}
2191	
2192		var scroll = settings.oScroll;
2193		if ( scroll.sY !== '' || scroll.sX !== '')
2194		{
2195			_fnScrollDraw( settings );
2196		}
2197	
2198		_fnCallbackFire( settings, null, 'column-sizing', [settings] );
2199	}
2200	
2201	
2202	/**
2203	 * Covert the index of a visible column to the index in the data array (take account
2204	 * of hidden columns)
2205	 *  @param {object} oSettings dataTables settings object
2206	 *  @param {int} iMatch Visible column index to lookup
2207	 *  @returns {int} i the data index
2208	 *  @memberof DataTable#oApi
2209	 */
2210	function _fnVisibleToColumnIndex( oSettings, iMatch )
2211	{
2212		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2213	
2214		return typeof aiVis[iMatch] === 'number' ?
2215			aiVis[iMatch] :
2216			null;
2217	}
2218	
2219	
2220	/**
2221	 * Covert the index of an index in the data array and convert it to the visible
2222	 *   column index (take account of hidden columns)
2223	 *  @param {int} iMatch Column index to lookup
2224	 *  @param {object} oSettings dataTables settings object
2225	 *  @returns {int} i the data index
2226	 *  @memberof DataTable#oApi
2227	 */
2228	function _fnColumnIndexToVisible( oSettings, iMatch )
2229	{
2230		var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2231		var iPos = $.inArray( iMatch, aiVis );
2232	
2233		return iPos !== -1 ? iPos : null;
2234	}
2235	
2236	
2237	/**
2238	 * Get the number of visible columns
2239	 *  @param {object} oSettings dataTables settings object
2240	 *  @returns {int} i the number of visible columns
2241	 *  @memberof DataTable#oApi
2242	 */
2243	function _fnVisbleColumns( oSettings )
2244	{
2245		var vis = 0;
2246	
2247		// No reduce in IE8, use a loop for now
2248		$.each( oSettings.aoColumns, function ( i, col ) {
2249			if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2250				vis++;
2251			}
2252		} );
2253	
2254		return vis;
2255	}
2256	
2257	
2258	/**
2259	 * Get an array of column indexes that match a given property
2260	 *  @param {object} oSettings dataTables settings object
2261	 *  @param {string} sParam Parameter in aoColumns to look for - typically
2262	 *    bVisible or bSearchable
2263	 *  @returns {array} Array of indexes with matched properties
2264	 *  @memberof DataTable#oApi
2265	 */
2266	function _fnGetColumns( oSettings, sParam )
2267	{
2268		var a = [];
2269	
2270		$.map( oSettings.aoColumns, function(val, i) {
2271			if ( val[sParam] ) {
2272				a.push( i );
2273			}
2274		} );
2275	
2276		return a;
2277	}
2278	
2279	
2280	/**
2281	 * Calculate the 'type' of a column
2282	 *  @param {object} settings dataTables settings object
2283	 *  @memberof DataTable#oApi
2284	 */
2285	function _fnColumnTypes ( settings )
2286	{
2287		var columns = settings.aoColumns;
2288		var data = settings.aoData;
2289		var types = DataTable.ext.type.detect;
2290		var i, ien, j, jen, k, ken;
2291		var col, cell, detectedType, cache;
2292	
2293		// For each column, spin over the 
2294		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2295			col = columns[i];
2296			cache = [];
2297	
2298			if ( ! col.sType && col._sManualType ) {
2299				col.sType = col._sManualType;
2300			}
2301			else if ( ! col.sType ) {
2302				for ( j=0, jen=types.length ; j<jen ; j++ ) {
2303					for ( k=0, ken=data.length ; k<ken ; k++ ) {
2304						// Use a cache array so we only need to get the type data
2305						// from the formatter once (when using multiple detectors)
2306						if ( cache[k] === undefined ) {
2307							cache[k] = _fnGetCellData( settings, k, i, 'type' );
2308						}
2309	
2310						detectedType = types[j]( cache[k], settings );
2311	
2312						// If null, then this type can't apply to this column, so
2313						// rather than testing all cells, break out. There is an
2314						// exception for the last type which is `html`. We need to
2315						// scan all rows since it is possible to mix string and HTML
2316						// types
2317						if ( ! detectedType && j !== types.length-1 ) {
2318							break;
2319						}
2320	
2321						// Only a single match is needed for html type since it is
2322						// bottom of the pile and very similar to string
2323						if ( detectedType === 'html' ) {
2324							break;
2325						}
2326					}
2327	
2328					// Type is valid for all data points in the column - use this
2329					// type
2330					if ( detectedType ) {
2331						col.sType = detectedType;
2332						break;
2333					}
2334				}
2335	
2336				// Fall back - if no type was detected, always use string
2337				if ( ! col.sType ) {
2338					col.sType = 'string';
2339				}
2340			}
2341		}
2342	}
2343	
2344	
2345	/**
2346	 * Take the column definitions and static columns arrays and calculate how
2347	 * they relate to column indexes. The callback function will then apply the
2348	 * definition found for a column to a suitable configuration object.
2349	 *  @param {object} oSettings dataTables settings object
2350	 *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2351	 *  @param {array} aoCols The aoColumns array that defines columns individually
2352	 *  @param {function} fn Callback function - takes two parameters, the calculated
2353	 *    column index and the definition for that column.
2354	 *  @memberof DataTable#oApi
2355	 */
2356	function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2357	{
2358		var i, iLen, j, jLen, k, kLen, def;
2359		var columns = oSettings.aoColumns;
2360	
2361		// Column definitions with aTargets
2362		if ( aoColDefs )
2363		{
2364			/* Loop over the definitions array - loop in reverse so first instance has priority */
2365			for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2366			{
2367				def = aoColDefs[i];
2368	
2369				/* Each definition can target multiple columns, as it is an array */
2370				var aTargets = def.targets !== undefined ?
2371					def.targets :
2372					def.aTargets;
2373	
2374				if ( ! $.isArray( aTargets ) )
2375				{
2376					aTargets = [ aTargets ];
2377				}
2378	
2379				for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2380				{
2381					if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2382					{
2383						/* Add columns that we don't yet know about */
2384						while( columns.length <= aTargets[j] )
2385						{
2386							_fnAddColumn( oSettings );
2387						}
2388	
2389						/* Integer, basic index */
2390						fn( aTargets[j], def );
2391					}
2392					else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2393					{
2394						/* Negative integer, right to left column counting */
2395						fn( columns.length+aTargets[j], def );
2396					}
2397					else if ( typeof aTargets[j] === 'string' )
2398					{
2399						/* Class name matching on TH element */
2400						for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2401						{
2402							if ( aTargets[j] == "_all" ||
2403							     $(columns[k].nTh).hasClass( aTargets[j] ) )
2404							{
2405								fn( k, def );
2406							}
2407						}
2408					}
2409				}
2410			}
2411		}
2412	
2413		// Statically defined columns array
2414		if ( aoCols )
2415		{
2416			for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2417			{
2418				fn( i, aoCols[i] );
2419			}
2420		}
2421	}
2422	
2423	/**
2424	 * Add a data array to the table, creating DOM node etc. This is the parallel to
2425	 * _fnGatherData, but for adding rows from a Javascript source, rather than a
2426	 * DOM source.
2427	 *  @param {object} oSettings dataTables settings object
2428	 *  @param {array} aData data array to be added
2429	 *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2430	 *    DataTables will create a row automatically
2431	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2432	 *    if nTr is.
2433	 *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2434	 *  @memberof DataTable#oApi
2435	 */
2436	function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2437	{
2438		/* Create the object for storing information about this new row */
2439		var iRow = oSettings.aoData.length;
2440		var oData = $.extend( true, {}, DataTable.models.oRow, {
2441			src: nTr ? 'dom' : 'data',
2442			idx: iRow
2443		} );
2444	
2445		oData._aData = aDataIn;
2446		oSettings.aoData.push( oData );
2447	
2448		/* Create the cells */
2449		var nTd, sThisType;
2450		var columns = oSettings.aoColumns;
2451	
2452		// Invalidate the column types as the new data needs to be revalidated
2453		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2454		{
2455			columns[i].sType = null;
2456		}
2457	
2458		/* Add to the display array */
2459		oSettings.aiDisplayMaster.push( iRow );
2460	
2461		var id = oSettings.rowIdFn( aDataIn );
2462		if ( id !== undefined ) {
2463			oSettings.aIds[ id ] = oData;
2464		}
2465	
2466		/* Create the DOM information, or register it if already present */
2467		if ( nTr || ! oSettings.oFeatures.bDeferRender )
2468		{
2469			_fnCreateTr( oSettings, iRow, nTr, anTds );
2470		}
2471	
2472		return iRow;
2473	}
2474	
2475	
2476	/**
2477	 * Add one or more TR elements to the table. Generally we'd expect to
2478	 * use this for reading data from a DOM sourced table, but it could be
2479	 * used for an TR element. Note that if a TR is given, it is used (i.e.
2480	 * it is not cloned).
2481	 *  @param {object} settings dataTables settings object
2482	 *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2483	 *  @returns {array} Array of indexes for the added rows
2484	 *  @memberof DataTable#oApi
2485	 */
2486	function _fnAddTr( settings, trs )
2487	{
2488		var row;
2489	
2490		// Allow an individual node to be passed in
2491		if ( ! (trs instanceof $) ) {
2492			trs = $(trs);
2493		}
2494	
2495		return trs.map( function (i, el) {
2496			row = _fnGetRowElements( settings, el );
2497			return _fnAddData( settings, row.data, el, row.cells );
2498		} );
2499	}
2500	
2501	
2502	/**
2503	 * Take a TR element and convert it to an index in aoData
2504	 *  @param {object} oSettings dataTables settings object
2505	 *  @param {node} n the TR element to find
2506	 *  @returns {int} index if the node is found, null if not
2507	 *  @memberof DataTable#oApi
2508	 */
2509	function _fnNodeToDataIndex( oSettings, n )
2510	{
2511		return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2512	}
2513	
2514	
2515	/**
2516	 * Take a TD element and convert it into a column data index (not the visible index)
2517	 *  @param {object} oSettings dataTables settings object
2518	 *  @param {int} iRow The row number the TD/TH can be found in
2519	 *  @param {node} n The TD/TH element to find
2520	 *  @returns {int} index if the node is found, -1 if not
2521	 *  @memberof DataTable#oApi
2522	 */
2523	function _fnNodeToColumnIndex( oSettings, iRow, n )
2524	{
2525		return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2526	}
2527	
2528	
2529	/**
2530	 * Get the data for a given cell from the internal cache, taking into account data mapping
2531	 *  @param {object} settings dataTables settings object
2532	 *  @param {int} rowIdx aoData row id
2533	 *  @param {int} colIdx Column index
2534	 *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2535	 *  @returns {*} Cell data
2536	 *  @memberof DataTable#oApi
2537	 */
2538	function _fnGetCellData( settings, rowIdx, colIdx, type )
2539	{
2540		var draw           = settings.iDraw;
2541		var col            = settings.aoColumns[colIdx];
2542		var rowData        = settings.aoData[rowIdx]._aData;
2543		var defaultContent = col.sDefaultContent;
2544		var cellData       = col.fnGetData( rowData, type, {
2545			settings: settings,
2546			row:      rowIdx,
2547			col:      colIdx
2548		} );
2549	
2550		if ( cellData === undefined ) {
2551			if ( settings.iDrawError != draw && defaultContent === null ) {
2552				_fnLog( settings, 0, "Requested unknown parameter "+
2553					(typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2554					" for row "+rowIdx+", column "+colIdx, 4 );
2555				settings.iDrawError = draw;
2556			}
2557			return defaultContent;
2558		}
2559	
2560		// When the data source is null and a specific data type is requested (i.e.
2561		// not the original data), we can use default column data
2562		if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2563			cellData = defaultContent;
2564		}
2565		else if ( typeof cellData === 'function' ) {
2566			// If the data source is a function, then we run it and use the return,
2567			// executing in the scope of the data object (for instances)
2568			return cellData.call( rowData );
2569		}
2570	
2571		if ( cellData === null && type == 'display' ) {
2572			return '';
2573		}
2574		return cellData;
2575	}
2576	
2577	
2578	/**
2579	 * Set the value for a specific cell, into the internal data cache
2580	 *  @param {object} settings dataTables settings object
2581	 *  @param {int} rowIdx aoData row id
2582	 *  @param {int} colIdx Column index
2583	 *  @param {*} val Value to set
2584	 *  @memberof DataTable#oApi
2585	 */
2586	function _fnSetCellData( settings, rowIdx, colIdx, val )
2587	{
2588		var col     = settings.aoColumns[colIdx];
2589		var rowData = settings.aoData[rowIdx]._aData;
2590	
2591		col.fnSetData( rowData, val, {
2592			settings: settings,
2593			row:      rowIdx,
2594			col:      colIdx
2595		}  );
2596	}
2597	
2598	
2599	// Private variable that is used to match action syntax in the data property object
2600	var __reArray = /\[.*?\]$/;
2601	var __reFn = /\(\)$/;
2602	
2603	/**
2604	 * Split string on periods, taking into account escaped periods
2605	 * @param  {string} str String to split
2606	 * @return {array} Split string
2607	 */
2608	function _fnSplitObjNotation( str )
2609	{
2610		return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2611			return s.replace(/\\\./g, '.');
2612		} );
2613	}
2614	
2615	
2616	/**
2617	 * Return a function that can be used to get data from a source object, taking
2618	 * into account the ability to use nested objects as a source
2619	 *  @param {string|int|function} mSource The data source for the object
2620	 *  @returns {function} Data get function
2621	 *  @memberof DataTable#oApi
2622	 */
2623	function _fnGetObjectDataFn( mSource )
2624	{
2625		if ( $.isPlainObject( mSource ) )
2626		{
2627			/* Build an object of get functions, and wrap them in a single call */
2628			var o = {};
2629			$.each( mSource, function (key, val) {
2630				if ( val ) {
2631					o[key] = _fnGetObjectDataFn( val );
2632				}
2633			} );
2634	
2635			return function (data, type, row, meta) {
2636				var t = o[type] || o._;
2637				return t !== undefined ?
2638					t(data, type, row, meta) :
2639					data;
2640			};
2641		}
2642		else if ( mSource === null )
2643		{
2644			/* Give an empty string for rendering / sorting etc */
2645			return function (data) { // type, row and meta also passed, but not used
2646				return data;
2647			};
2648		}
2649		else if ( typeof mSource === 'function' )
2650		{
2651			return function (data, type, row, meta) {
2652				return mSource( data, type, row, meta );
2653			};
2654		}
2655		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2656			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2657		{
2658			/* If there is a . in the source string then the data source is in a
2659			 * nested object so we loop over the data for each level to get the next
2660			 * level down. On each loop we test for undefined, and if found immediately
2661			 * return. This allows entire objects to be missing and sDefaultContent to
2662			 * be used if defined, rather than throwing an error
2663			 */
2664			var fetchData = function (data, type, src) {
2665				var arrayNotation, funcNotation, out, innerSrc;
2666	
2667				if ( src !== "" )
2668				{
2669					var a = _fnSplitObjNotation( src );
2670	
2671					for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2672					{
2673						// Check if we are dealing with special notation
2674						arrayNotation = a[i].match(__reArray);
2675						funcNotation = a[i].match(__reFn);
2676	
2677						if ( arrayNotation )
2678						{
2679							// Array notation
2680							a[i] = a[i].replace(__reArray, '');
2681	
2682							// Condition allows simply [] to be passed in
2683							if ( a[i] !== "" ) {
2684								data = data[ a[i] ];
2685							}
2686							out = [];
2687	
2688							// Get the remainder of the nested object to get
2689							a.splice( 0, i+1 );
2690							innerSrc = a.join('.');
2691	
2692							// Traverse each entry in the array getting the properties requested
2693							if ( $.isArray( data ) ) {
2694								for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2695									out.push( fetchData( data[j], type, innerSrc ) );
2696								}
2697							}
2698	
2699							// If a string is given in between the array notation indicators, that
2700							// is used to join the strings together, otherwise an array is returned
2701							var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2702							data = (join==="") ? out : out.join(join);
2703	
2704							// The inner call to fetchData has already traversed through the remainder
2705							// of the source requested, so we exit from the loop
2706							break;
2707						}
2708						else if ( funcNotation )
2709						{
2710							// Function call
2711							a[i] = a[i].replace(__reFn, '');
2712							data = data[ a[i] ]();
2713							continue;
2714						}
2715	
2716						if ( data === null || data[ a[i] ] === undefined )
2717						{
2718							return undefined;
2719						}
2720						data = data[ a[i] ];
2721					}
2722				}
2723	
2724				return data;
2725			};
2726	
2727			return function (data, type) { // row and meta also passed, but not used
2728				return fetchData( data, type, mSource );
2729			};
2730		}
2731		else
2732		{
2733			/* Array or flat object mapping */
2734			return function (data, type) { // row and meta also passed, but not used
2735				return data[mSource];
2736			};
2737		}
2738	}
2739	
2740	
2741	/**
2742	 * Return a function that can be used to set data from a source object, taking
2743	 * into account the ability to use nested objects as a source
2744	 *  @param {string|int|function} mSource The data source for the object
2745	 *  @returns {function} Data set function
2746	 *  @memberof DataTable#oApi
2747	 */
2748	function _fnSetObjectDataFn( mSource )
2749	{
2750		if ( $.isPlainObject( mSource ) )
2751		{
2752			/* Unlike get, only the underscore (global) option is used for for
2753			 * setting data since we don't know the type here. This is why an object
2754			 * option is not documented for `mData` (which is read/write), but it is
2755			 * for `mRender` which is read only.
2756			 */
2757			return _fnSetObjectDataFn( mSource._ );
2758		}
2759		else if ( mSource === null )
2760		{
2761			/* Nothing to do when the data source is null */
2762			return function () {};
2763		}
2764		else if ( typeof mSource === 'function' )
2765		{
2766			return function (data, val, meta) {
2767				mSource( data, 'set', val, meta );
2768			};
2769		}
2770		else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2771			      mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2772		{
2773			/* Like the get, we need to get data from a nested object */
2774			var setData = function (data, val, src) {
2775				var a = _fnSplitObjNotation( src ), b;
2776				var aLast = a[a.length-1];
2777				var arrayNotation, funcNotation, o, innerSrc;
2778	
2779				for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2780				{
2781					// Check if we are dealing with an array notation request
2782					arrayNotation = a[i].match(__reArray);
2783					funcNotation = a[i].match(__reFn);
2784	
2785					if ( arrayNotation )
2786					{
2787						a[i] = a[i].replace(__reArray, '');
2788						data[ a[i] ] = [];
2789	
2790						// Get the remainder of the nested object to set so we can recurse
2791						b = a.slice();
2792						b.splice( 0, i+1 );
2793						innerSrc = b.join('.');
2794	
2795						// Traverse each entry in the array setting the properties requested
2796						if ( $.isArray( val ) )
2797						{
2798							for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2799							{
2800								o = {};
2801								setData( o, val[j], innerSrc );
2802								data[ a[i] ].push( o );
2803							}
2804						}
2805						else
2806						{
2807							// We've been asked to save data to an array, but it
2808							// isn't array data to be saved. Best that can be done
2809							// is to just save the value.
2810							data[ a[i] ] = val;
2811						}
2812	
2813						// The inner call to setData has already traversed through the remainder
2814						// of the source and has set the data, thus we can exit here
2815						return;
2816					}
2817					else if ( funcNotation )
2818					{
2819						// Function call
2820						a[i] = a[i].replace(__reFn, '');
2821						data = data[ a[i] ]( val );
2822					}
2823	
2824					// If the nested object doesn't currently exist - since we are
2825					// trying to set the value - create it
2826					if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2827					{
2828						data[ a[i] ] = {};
2829					}
2830					data = data[ a[i] ];
2831				}
2832	
2833				// Last item in the input - i.e, the actual set
2834				if ( aLast.match(__reFn ) )
2835				{
2836					// Function call
2837					data = data[ aLast.replace(__reFn, '') ]( val );
2838				}
2839				else
2840				{
2841					// If array notation is used, we just want to strip it and use the property name
2842					// and assign the value. If it isn't used, then we get the result we want anyway
2843					data[ aLast.replace(__reArray, '') ] = val;
2844				}
2845			};
2846	
2847			return function (data, val) { // meta is also passed in, but not used
2848				return setData( data, val, mSource );
2849			};
2850		}
2851		else
2852		{
2853			/* Array or flat object mapping */
2854			return function (data, val) { // meta is also passed in, but not used
2855				data[mSource] = val;
2856			};
2857		}
2858	}
2859	
2860	
2861	/**
2862	 * Return an array with the full table data
2863	 *  @param {object} oSettings dataTables settings object
2864	 *  @returns array {array} aData Master data array
2865	 *  @memberof DataTable#oApi
2866	 */
2867	function _fnGetDataMaster ( settings )
2868	{
2869		return _pluck( settings.aoData, '_aData' );
2870	}
2871	
2872	
2873	/**
2874	 * Nuke the table
2875	 *  @param {object} oSettings dataTables settings object
2876	 *  @memberof DataTable#oApi
2877	 */
2878	function _fnClearTable( settings )
2879	{
2880		settings.aoData.length = 0;
2881		settings.aiDisplayMaster.length = 0;
2882		settings.aiDisplay.length = 0;
2883		settings.aIds = {};
2884	}
2885	
2886	
2887	 /**
2888	 * Take an array of integers (index array) and remove a target integer (value - not
2889	 * the key!)
2890	 *  @param {array} a Index array to target
2891	 *  @param {int} iTarget value to find
2892	 *  @memberof DataTable#oApi
2893	 */
2894	function _fnDeleteIndex( a, iTarget, splice )
2895	{
2896		var iTargetIndex = -1;
2897	
2898		for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2899		{
2900			if ( a[i] == iTarget )
2901			{
2902				iTargetIndex = i;
2903			}
2904			else if ( a[i] > iTarget )
2905			{
2906				a[i]--;
2907			}
2908		}
2909	
2910		if ( iTargetIndex != -1 && splice === undefined )
2911		{
2912			a.splice( iTargetIndex, 1 );
2913		}
2914	}
2915	
2916	
2917	/**
2918	 * Mark cached data as invalid such that a re-read of the data will occur when
2919	 * the cached data is next requested. Also update from the data source object.
2920	 *
2921	 * @param {object} settings DataTables settings object
2922	 * @param {int}    rowIdx   Row index to invalidate
2923	 * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2924	 *     or 'data'
2925	 * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2926	 *     row will be invalidated
2927	 * @memberof DataTable#oApi
2928	 *
2929	 * @todo For the modularisation of v1.11 this will need to become a callback, so
2930	 *   the sort and filter methods can subscribe to it. That will required
2931	 *   initialisation options for sorting, which is why it is not already baked in
2932	 */
2933	function _fnInvalidate( settings, rowIdx, src, colIdx )
2934	{
2935		var row = settings.aoData[ rowIdx ];
2936		var i, ien;
2937		var cellWrite = function ( cell, col ) {
2938			// This is very frustrating, but in IE if you just write directly
2939			// to innerHTML, and elements that are overwritten are GC'ed,
2940			// even if there is a reference to them elsewhere
2941			while ( cell.childNodes.length ) {
2942				cell.removeChild( cell.firstChild );
2943			}
2944	
2945			cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2946		};
2947	
2948		// Are we reading last data from DOM or the data object?
2949		if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2950			// Read the data from the DOM
2951			row._aData = _fnGetRowElements(
2952					settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2953				)
2954				.data;
2955		}
2956		else {
2957			// Reading from data object, update the DOM
2958			var cells = row.anCells;
2959	
2960			if ( cells ) {
2961				if ( colIdx !== undefined ) {
2962					cellWrite( cells[colIdx], colIdx );
2963				}
2964				else {
2965					for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2966						cellWrite( cells[i], i );
2967					}
2968				}
2969			}
2970		}
2971	
2972		// For both row and cell invalidation, the cached data for sorting and
2973		// filtering is nulled out
2974		row._aSortData = null;
2975		row._aFilterData = null;
2976	
2977		// Invalidate the type for a specific column (if given) or all columns since
2978		// the data might have changed
2979		var cols = settings.aoColumns;
2980		if ( colIdx !== undefined ) {
2981			cols[ colIdx ].sType = null;
2982		}
2983		else {
2984			for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2985				cols[i].sType = null;
2986			}
2987	
2988			// Update DataTables special `DT_*` attributes for the row
2989			_fnRowAttributes( settings, row );
2990		}
2991	}
2992	
2993	
2994	/**
2995	 * Build a data source object from an HTML row, reading the contents of the
2996	 * cells that are in the row.
2997	 *
2998	 * @param {object} settings DataTables settings object
2999	 * @param {node|object} TR element from which to read data or existing row
3000	 *   object from which to re-read the data from the cells
3001	 * @param {int} [colIdx] Optional column index
3002	 * @param {array|object} [d] Data source object. If `colIdx` is given then this
3003	 *   parameter should also be given and will be used to write the data into.
3004	 *   Only the column in question will be written
3005	 * @returns {object} Object with two parameters: `data` the data read, in
3006	 *   document order, and `cells` and array of nodes (they can be useful to the
3007	 *   caller, so rather than needing a second traversal to get them, just return
3008	 *   them from here).
3009	 * @memberof DataTable#oApi
3010	 */
3011	function _fnGetRowElements( settings, row, colIdx, d )
3012	{
3013		var
3014			tds = [],
3015			td = row.firstChild,
3016			name, col, o, i=0, contents,
3017			columns = settings.aoColumns,
3018			objectRead = settings._rowReadObject;
3019	
3020		// Allow the data object to be passed in, or construct
3021		d = d !== undefined ?
3022			d :
3023			objectRead ?
3024				{} :
3025				[];
3026	
3027		var attr = function ( str, td  ) {
3028			if ( typeof str === 'string' ) {
3029				var idx = str.indexOf('@');
3030	
3031				if ( idx !== -1 ) {
3032					var attr = str.substring( idx+1 );
3033					var setter = _fnSetObjectDataFn( str );
3034					setter( d, td.getAttribute( attr ) );
3035				}
3036			}
3037		};
3038	
3039		// Read data from a cell and store into the data object
3040		var cellProcess = function ( cell ) {
3041			if ( colIdx === undefined || colIdx === i ) {
3042				col = columns[i];
3043				contents = $.trim(cell.innerHTML);
3044	
3045				if ( col && col._bAttrSrc ) {
3046					var setter = _fnSetObjectDataFn( col.mData._ );
3047					setter( d, contents );
3048	
3049					attr( col.mData.sort, cell );
3050					attr( col.mData.type, cell );
3051					attr( col.mData.filter, cell );
3052				}
3053				else {
3054					// Depending on the `data` option for the columns the data can
3055					// be read to either an object or an array.
vendor: 11,978 bytes, lines 3056-3513
3056					if ( objectRead ) {
3057						if ( ! col._setter ) {
3058							// Cache the setter function
3059							col._setter = _fnSetObjectDataFn( col.mData );
3060						}
3061						col._setter( d, contents );
3062					}
3063					else {
3064						d[i] = contents;
3065					}
3066				}
3067			}
3068	
3069			i++;
3070		};
3071	
3072		if ( td ) {
3073			// `tr` element was passed in
3074			while ( td ) {
3075				name = td.nodeName.toUpperCase();
3076	
3077				if ( name == "TD" || name == "TH" ) {
3078					cellProcess( td );
3079					tds.push( td );
3080				}
3081	
3082				td = td.nextSibling;
3083			}
3084		}
3085		else {
3086			// Existing row object passed in
3087			tds = row.anCells;
3088	
3089			for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3090				cellProcess( tds[j] );
3091			}
3092		}
3093	
3094		// Read the ID from the DOM if present
3095		var rowNode = row.firstChild ? row : row.nTr;
3096	
3097		if ( rowNode ) {
3098			var id = rowNode.getAttribute( 'id' );
3099	
3100			if ( id ) {
3101				_fnSetObjectDataFn( settings.rowId )( d, id );
3102			}
3103		}
3104	
3105		return {
3106			data: d,
3107			cells: tds
3108		};
3109	}
3110	/**
3111	 * Create a new TR element (and it's TD children) for a row
3112	 *  @param {object} oSettings dataTables settings object
3113	 *  @param {int} iRow Row to consider
3114	 *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3115	 *    DataTables will create a row automatically
3116	 *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3117	 *    if nTr is.
3118	 *  @memberof DataTable#oApi
3119	 */
3120	function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3121	{
3122		var
3123			row = oSettings.aoData[iRow],
3124			rowData = row._aData,
3125			cells = [],
3126			nTr, nTd, oCol,
3127			i, iLen;
3128	
3129		if ( row.nTr === null )
3130		{
3131			nTr = nTrIn || document.createElement('tr');
3132	
3133			row.nTr = nTr;
3134			row.anCells = cells;
3135	
3136			/* Use a private property on the node to allow reserve mapping from the node
3137			 * to the aoData array for fast look up
3138			 */
3139			nTr._DT_RowIndex = iRow;
3140	
3141			/* Special parameters can be given by the data source to be used on the row */
3142			_fnRowAttributes( oSettings, row );
3143	
3144			/* Process each column */
3145			for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3146			{
3147				oCol = oSettings.aoColumns[i];
3148	
3149				nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3150				nTd._DT_CellIndex = {
3151					row: iRow,
3152					column: i
3153				};
3154				
3155				cells.push( nTd );
3156	
3157				// Need to create the HTML if new, or if a rendering function is defined
3158				if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3159					 (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3160				) {
3161					nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3162				}
3163	
3164				/* Add user defined class */
3165				if ( oCol.sClass )
3166				{
3167					nTd.className += ' '+oCol.sClass;
3168				}
3169	
3170				// Visibility - add or remove as required
3171				if ( oCol.bVisible && ! nTrIn )
3172				{
3173					nTr.appendChild( nTd );
3174				}
3175				else if ( ! oCol.bVisible && nTrIn )
3176				{
3177					nTd.parentNode.removeChild( nTd );
3178				}
3179	
3180				if ( oCol.fnCreatedCell )
3181				{
3182					oCol.fnCreatedCell.call( oSettings.oInstance,
3183						nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3184					);
3185				}
3186			}
3187	
3188			_fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
3189		}
3190	
3191		// Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3192		// and deployed
3193		row.nTr.setAttribute( 'role', 'row' );
3194	}
3195	
3196	
3197	/**
3198	 * Add attributes to a row based on the special `DT_*` parameters in a data
3199	 * source object.
3200	 *  @param {object} settings DataTables settings object
3201	 *  @param {object} DataTables row object for the row to be modified
3202	 *  @memberof DataTable#oApi
3203	 */
3204	function _fnRowAttributes( settings, row )
3205	{
3206		var tr = row.nTr;
3207		var data = row._aData;
3208	
3209		if ( tr ) {
3210			var id = settings.rowIdFn( data );
3211	
3212			if ( id ) {
3213				tr.id = id;
3214			}
3215	
3216			if ( data.DT_RowClass ) {
3217				// Remove any classes added by DT_RowClass before
3218				var a = data.DT_RowClass.split(' ');
3219				row.__rowc = row.__rowc ?
3220					_unique( row.__rowc.concat( a ) ) :
3221					a;
3222	
3223				$(tr)
3224					.removeClass( row.__rowc.join(' ') )
3225					.addClass( data.DT_RowClass );
3226			}
3227	
3228			if ( data.DT_RowAttr ) {
3229				$(tr).attr( data.DT_RowAttr );
3230			}
3231	
3232			if ( data.DT_RowData ) {
3233				$(tr).data( data.DT_RowData );
3234			}
3235		}
3236	}
3237	
3238	
3239	/**
3240	 * Create the HTML header for the table
3241	 *  @param {object} oSettings dataTables settings object
3242	 *  @memberof DataTable#oApi
3243	 */
3244	function _fnBuildHead( oSettings )
3245	{
3246		var i, ien, cell, row, column;
3247		var thead = oSettings.nTHead;
3248		var tfoot = oSettings.nTFoot;
3249		var createHeader = $('th, td', thead).length === 0;
3250		var classes = oSettings.oClasses;
3251		var columns = oSettings.aoColumns;
3252	
3253		if ( createHeader ) {
3254			row = $('<tr/>').appendTo( thead );
3255		}
3256	
3257		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3258			column = columns[i];
3259			cell = $( column.nTh ).addClass( column.sClass );
3260	
3261			if ( createHeader ) {
3262				cell.appendTo( row );
3263			}
3264	
3265			// 1.11 move into sorting
3266			if ( oSettings.oFeatures.bSort ) {
3267				cell.addClass( column.sSortingClass );
3268	
3269				if ( column.bSortable !== false ) {
3270					cell
3271						.attr( 'tabindex', oSettings.iTabIndex )
3272						.attr( 'aria-controls', oSettings.sTableId );
3273	
3274					_fnSortAttachListener( oSettings, column.nTh, i );
3275				}
3276			}
3277	
3278			if ( column.sTitle != cell[0].innerHTML ) {
3279				cell.html( column.sTitle );
3280			}
3281	
3282			_fnRenderer( oSettings, 'header' )(
3283				oSettings, cell, column, classes
3284			);
3285		}
3286	
3287		if ( createHeader ) {
3288			_fnDetectHeader( oSettings.aoHeader, thead );
3289		}
3290		
3291		/* ARIA role for the rows */
3292	 	$(thead).find('>tr').attr('role', 'row');
3293	
3294		/* Deal with the footer - add classes if required */
3295		$(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3296		$(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3297	
3298		// Cache the footer cells. Note that we only take the cells from the first
3299		// row in the footer. If there is more than one row the user wants to
3300		// interact with, they need to use the table().foot() method. Note also this
3301		// allows cells to be used for multiple columns using colspan
3302		if ( tfoot !== null ) {
3303			var cells = oSettings.aoFooter[0];
3304	
3305			for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3306				column = columns[i];
3307				column.nTf = cells[i].cell;
3308	
3309				if ( column.sClass ) {
3310					$(column.nTf).addClass( column.sClass );
3311				}
3312			}
3313		}
3314	}
3315	
3316	
3317	/**
3318	 * Draw the header (or footer) element based on the column visibility states. The
3319	 * methodology here is to use the layout array from _fnDetectHeader, modified for
3320	 * the instantaneous column visibility, to construct the new layout. The grid is
3321	 * traversed over cell at a time in a rows x columns grid fashion, although each
3322	 * cell insert can cover multiple elements in the grid - which is tracks using the
3323	 * aApplied array. Cell inserts in the grid will only occur where there isn't
3324	 * already a cell in that position.
3325	 *  @param {object} oSettings dataTables settings object
3326	 *  @param array {objects} aoSource Layout array from _fnDetectHeader
3327	 *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3328	 *  @memberof DataTable#oApi
3329	 */
3330	function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3331	{
3332		var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3333		var aoLocal = [];
3334		var aApplied = [];
3335		var iColumns = oSettings.aoColumns.length;
3336		var iRowspan, iColspan;
3337	
3338		if ( ! aoSource )
3339		{
3340			return;
3341		}
3342	
3343		if (  bIncludeHidden === undefined )
3344		{
3345			bIncludeHidden = false;
3346		}
3347	
3348		/* Make a copy of the master layout array, but without the visible columns in it */
3349		for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3350		{
3351			aoLocal[i] = aoSource[i].slice();
3352			aoLocal[i].nTr = aoSource[i].nTr;
3353	
3354			/* Remove any columns which are currently hidden */
3355			for ( j=iColumns-1 ; j>=0 ; j-- )
3356			{
3357				if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3358				{
3359					aoLocal[i].splice( j, 1 );
3360				}
3361			}
3362	
3363			/* Prep the applied array - it needs an element for each row */
3364			aApplied.push( [] );
3365		}
3366	
3367		for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3368		{
3369			nLocalTr = aoLocal[i].nTr;
3370	
3371			/* All cells are going to be replaced, so empty out the row */
3372			if ( nLocalTr )
3373			{
3374				while( (n = nLocalTr.firstChild) )
3375				{
3376					nLocalTr.removeChild( n );
3377				}
3378			}
3379	
3380			for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3381			{
3382				iRowspan = 1;
3383				iColspan = 1;
3384	
3385				/* Check to see if there is already a cell (row/colspan) covering our target
3386				 * insert point. If there is, then there is nothing to do.
3387				 */
3388				if ( aApplied[i][j] === undefined )
3389				{
3390					nLocalTr.appendChild( aoLocal[i][j].cell );
3391					aApplied[i][j] = 1;
3392	
3393					/* Expand the cell to cover as many rows as needed */
3394					while ( aoLocal[i+iRowspan] !== undefined &&
3395					        aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3396					{
3397						aApplied[i+iRowspan][j] = 1;
3398						iRowspan++;
3399					}
3400	
3401					/* Expand the cell to cover as many columns as needed */
3402					while ( aoLocal[i][j+iColspan] !== undefined &&
3403					        aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3404					{
3405						/* Must update the applied array over the rows for the columns */
3406						for ( k=0 ; k<iRowspan ; k++ )
3407						{
3408							aApplied[i+k][j+iColspan] = 1;
3409						}
3410						iColspan++;
3411					}
3412	
3413					/* Do the actual expansion in the DOM */
3414					$(aoLocal[i][j].cell)
3415						.attr('rowspan', iRowspan)
3416						.attr('colspan', iColspan);
3417				}
3418			}
3419		}
3420	}
3421	
3422	
3423	/**
3424	 * Insert the required TR nodes into the table for display
3425	 *  @param {object} oSettings dataTables settings object
3426	 *  @memberof DataTable#oApi
3427	 */
3428	function _fnDraw( oSettings )
3429	{
3430		/* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3431		var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3432		if ( $.inArray( false, aPreDraw ) !== -1 )
3433		{
3434			_fnProcessingDisplay( oSettings, false );
3435			return;
3436		}
3437	
3438		var i, iLen, n;
3439		var anRows = [];
3440		var iRowCount = 0;
3441		var asStripeClasses = oSettings.asStripeClasses;
3442		var iStripes = asStripeClasses.length;
3443		var iOpenRows = oSettings.aoOpenRows.length;
3444		var oLang = oSettings.oLanguage;
3445		var iInitDisplayStart = oSettings.iInitDisplayStart;
3446		var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3447		var aiDisplay = oSettings.aiDisplay;
3448	
3449		oSettings.bDrawing = true;
3450	
3451		/* Check and see if we have an initial draw position from state saving */
3452		if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3453		{
3454			oSettings._iDisplayStart = bServerSide ?
3455				iInitDisplayStart :
3456				iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3457					0 :
3458					iInitDisplayStart;
3459	
3460			oSettings.iInitDisplayStart = -1;
3461		}
3462	
3463		var iDisplayStart = oSettings._iDisplayStart;
3464		var iDisplayEnd = oSettings.fnDisplayEnd();
3465	
3466		/* Server-side processing draw intercept */
3467		if ( oSettings.bDeferLoading )
3468		{
3469			oSettings.bDeferLoading = false;
3470			oSettings.iDraw++;
3471			_fnProcessingDisplay( oSettings, false );
3472		}
3473		else if ( !bServerSide )
3474		{
3475			oSettings.iDraw++;
3476		}
3477		else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3478		{
3479			return;
3480		}
3481	
3482		if ( aiDisplay.length !== 0 )
3483		{
3484			var iStart = bServerSide ? 0 : iDisplayStart;
3485			var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3486	
3487			for ( var j=iStart ; j<iEnd ; j++ )
3488			{
3489				var iDataIndex = aiDisplay[j];
3490				var aoData = oSettings.aoData[ iDataIndex ];
3491				if ( aoData.nTr === null )
3492				{
3493					_fnCreateTr( oSettings, iDataIndex );
3494				}
3495	
3496				var nRow = aoData.nTr;
3497	
3498				/* Remove the old striping classes and then add the new one */
3499				if ( iStripes !== 0 )
3500				{
3501					var sStripe = asStripeClasses[ iRowCount % iStripes ];
3502					if ( aoData._sRowStripe != sStripe )
3503					{
3504						$(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3505						aoData._sRowStripe = sStripe;
3506					}
3507				}
3508	
3509				// Row callback functions - might want to manipulate the row
3510				// iRowCount and j are not currently documented. Are they at all
3511				// useful?
3512				_fnCallbackFire( oSettings, 'aoRowCallback', null,
3513					[nRow, aoData._aData, iRowCount, j
vendor: 9,503 bytes, lines 3513-3867
3513] );
3514	
3515				anRows.push( nRow );
3516				iRowCount++;
3517			}
3518		}
3519		else
3520		{
3521			/* Table is empty - create a row with an empty message in it */
3522			var sZero = oLang.sZeroRecords;
3523			if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3524			{
3525				sZero = oLang.sLoadingRecords;
3526			}
3527			else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3528			{
3529				sZero = oLang.sEmptyTable;
3530			}
3531	
3532			anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3533				.append( $('<td />', {
3534					'valign':  'top',
3535					'colSpan': _fnVisbleColumns( oSettings ),
3536					'class':   oSettings.oClasses.sRowEmpty
3537				} ).html( sZero ) )[0];
3538		}
3539	
3540		/* Header and footer callbacks */
3541		_fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3542			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3543	
3544		_fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3545			_fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3546	
3547		var body = $(oSettings.nTBody);
3548	
3549		body.children().detach();
3550		body.append( $(anRows) );
3551	
3552		/* Call all required callback functions for the end of a draw */
3553		_fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3554	
3555		/* Draw is complete, sorting and filtering must be as well */
3556		oSettings.bSorted = false;
3557		oSettings.bFiltered = false;
3558		oSettings.bDrawing = false;
3559	}
3560	
3561	
3562	/**
3563	 * Redraw the table - taking account of the various features which are enabled
3564	 *  @param {object} oSettings dataTables settings object
3565	 *  @param {boolean} [holdPosition] Keep the current paging position. By default
3566	 *    the paging is reset to the first page
3567	 *  @memberof DataTable#oApi
3568	 */
3569	function _fnReDraw( settings, holdPosition )
3570	{
3571		var
3572			features = settings.oFeatures,
3573			sort     = features.bSort,
3574			filter   = features.bFilter;
3575	
3576		if ( sort ) {
3577			_fnSort( settings );
3578		}
3579	
3580		if ( filter ) {
3581			_fnFilterComplete( settings, settings.oPreviousSearch );
3582		}
3583		else {
3584			// No filtering, so we want to just use the display master
3585			settings.aiDisplay = settings.aiDisplayMaster.slice();
3586		}
3587	
3588		if ( holdPosition !== true ) {
3589			settings._iDisplayStart = 0;
3590		}
3591	
3592		// Let any modules know about the draw hold position state (used by
3593		// scrolling internally)
3594		settings._drawHold = holdPosition;
3595	
3596		_fnDraw( settings );
3597	
3598		settings._drawHold = false;
3599	}
3600	
3601	
3602	/**
3603	 * Add the options to the page HTML for the table
3604	 *  @param {object} oSettings dataTables settings object
3605	 *  @memberof DataTable#oApi
3606	 */
3607	function _fnAddOptionsHtml ( oSettings )
3608	{
3609		var classes = oSettings.oClasses;
3610		var table = $(oSettings.nTable);
3611		var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3612		var features = oSettings.oFeatures;
3613	
3614		// All DataTables are wrapped in a div
3615		var insert = $('<div/>', {
3616			id:      oSettings.sTableId+'_wrapper',
3617			'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3618		} );
3619	
3620		oSettings.nHolding = holding[0];
3621		oSettings.nTableWrapper = insert[0];
3622		oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3623	
3624		/* Loop over the user set positioning and place the elements as needed */
3625		var aDom = oSettings.sDom.split('');
3626		var featureNode, cOption, nNewNode, cNext, sAttr, j;
3627		for ( var i=0 ; i<aDom.length ; i++ )
3628		{
3629			featureNode = null;
3630			cOption = aDom[i];
3631	
3632			if ( cOption == '<' )
3633			{
3634				/* New container div */
3635				nNewNode = $('<div/>')[0];
3636	
3637				/* Check to see if we should append an id and/or a class name to the container */
3638				cNext = aDom[i+1];
3639				if ( cNext == "'" || cNext == '"' )
3640				{
3641					sAttr = "";
3642					j = 2;
3643					while ( aDom[i+j] != cNext )
3644					{
3645						sAttr += aDom[i+j];
3646						j++;
3647					}
3648	
3649					/* Replace jQuery UI constants @todo depreciated */
3650					if ( sAttr == "H" )
3651					{
3652						sAttr = classes.sJUIHeader;
3653					}
3654					else if ( sAttr == "F" )
3655					{
3656						sAttr = classes.sJUIFooter;
3657					}
3658	
3659					/* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3660					 * breaks the string into parts and applies them as needed
3661					 */
3662					if ( sAttr.indexOf('.') != -1 )
3663					{
3664						var aSplit = sAttr.split('.');
3665						nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3666						nNewNode.className = aSplit[1];
3667					}
3668					else if ( sAttr.charAt(0) == "#" )
3669					{
3670						nNewNode.id = sAttr.substr(1, sAttr.length-1);
3671					}
3672					else
3673					{
3674						nNewNode.className = sAttr;
3675					}
3676	
3677					i += j; /* Move along the position array */
3678				}
3679	
3680				insert.append( nNewNode );
3681				insert = $(nNewNode);
3682			}
3683			else if ( cOption == '>' )
3684			{
3685				/* End container div */
3686				insert = insert.parent();
3687			}
3688			// @todo Move options into their own plugins?
3689			else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3690			{
3691				/* Length */
3692				featureNode = _fnFeatureHtmlLength( oSettings );
3693			}
3694			else if ( cOption == 'f' && features.bFilter )
3695			{
3696				/* Filter */
3697				featureNode = _fnFeatureHtmlFilter( oSettings );
3698			}
3699			else if ( cOption == 'r' && features.bProcessing )
3700			{
3701				/* pRocessing */
3702				featureNode = _fnFeatureHtmlProcessing( oSettings );
3703			}
3704			else if ( cOption == 't' )
3705			{
3706				/* Table */
3707				featureNode = _fnFeatureHtmlTable( oSettings );
3708			}
3709			else if ( cOption ==  'i' && features.bInfo )
3710			{
3711				/* Info */
3712				featureNode = _fnFeatureHtmlInfo( oSettings );
3713			}
3714			else if ( cOption == 'p' && features.bPaginate )
3715			{
3716				/* Pagination */
3717				featureNode = _fnFeatureHtmlPaginate( oSettings );
3718			}
3719			else if ( DataTable.ext.feature.length !== 0 )
3720			{
3721				/* Plug-in features */
3722				var aoFeatures = DataTable.ext.feature;
3723				for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3724				{
3725					if ( cOption == aoFeatures[k].cFeature )
3726					{
3727						featureNode = aoFeatures[k].fnInit( oSettings );
3728						break;
3729					}
3730				}
3731			}
3732	
3733			/* Add to the 2D features array */
3734			if ( featureNode )
3735			{
3736				var aanFeatures = oSettings.aanFeatures;
3737	
3738				if ( ! aanFeatures[cOption] )
3739				{
3740					aanFeatures[cOption] = [];
3741				}
3742	
3743				aanFeatures[cOption].push( featureNode );
3744				insert.append( featureNode );
3745			}
3746		}
3747	
3748		/* Built our DOM structure - replace the holding div with what we want */
3749		holding.replaceWith( insert );
3750		oSettings.nHolding = null;
3751	}
3752	
3753	
3754	/**
3755	 * Use the DOM source to create up an array of header cells. The idea here is to
3756	 * create a layout grid (array) of rows x columns, which contains a reference
3757	 * to the cell that that point in the grid (regardless of col/rowspan), such that
3758	 * any column / row could be removed and the new grid constructed
3759	 *  @param array {object} aLayout Array to store the calculated layout in
3760	 *  @param {node} nThead The header/footer element for the table
3761	 *  @memberof DataTable#oApi
3762	 */
3763	function _fnDetectHeader ( aLayout, nThead )
3764	{
3765		var nTrs = $(nThead).children('tr');
3766		var nTr, nCell;
3767		var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3768		var bUnique;
3769		var fnShiftCol = function ( a, i, j ) {
3770			var k = a[i];
3771	                while ( k[j] ) {
3772				j++;
3773			}
3774			return j;
3775		};
3776	
3777		aLayout.splice( 0, aLayout.length );
3778	
3779		/* We know how many rows there are in the layout - so prep it */
3780		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3781		{
3782			aLayout.push( [] );
3783		}
3784	
3785		/* Calculate a layout array */
3786		for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3787		{
3788			nTr = nTrs[i];
3789			iColumn = 0;
3790	
3791			/* For every cell in the row... */
3792			nCell = nTr.firstChild;
3793			while ( nCell ) {
3794				if ( nCell.nodeName.toUpperCase() == "TD" ||
3795				     nCell.nodeName.toUpperCase() == "TH" )
3796				{
3797					/* Get the col and rowspan attributes from the DOM and sanitise them */
3798					iColspan = nCell.getAttribute('colspan') * 1;
3799					iRowspan = nCell.getAttribute('rowspan') * 1;
3800					iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3801					iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3802	
3803					/* There might be colspan cells already in this row, so shift our target
3804					 * accordingly
3805					 */
3806					iColShifted = fnShiftCol( aLayout, i, iColumn );
3807	
3808					/* Cache calculation for unique columns */
3809					bUnique = iColspan === 1 ? true : false;
3810	
3811					/* If there is col / rowspan, copy the information into the layout grid */
3812					for ( l=0 ; l<iColspan ; l++ )
3813					{
3814						for ( k=0 ; k<iRowspan ; k++ )
3815						{
3816							aLayout[i+k][iColShifted+l] = {
3817								"cell": nCell,
3818								"unique": bUnique
3819							};
3820							aLayout[i+k].nTr = nTr;
3821						}
3822					}
3823				}
3824				nCell = nCell.nextSibling;
3825			}
3826		}
3827	}
3828	
3829	
3830	/**
3831	 * Get an array of unique th elements, one for each column
3832	 *  @param {object} oSettings dataTables settings object
3833	 *  @param {node} nHeader automatically detect the layout from this node - optional
3834	 *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3835	 *  @returns array {node} aReturn list of unique th's
3836	 *  @memberof DataTable#oApi
3837	 */
3838	function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3839	{
3840		var aReturn = [];
3841		if ( !aLayout )
3842		{
3843			aLayout = oSettings.aoHeader;
3844			if ( nHeader )
3845			{
3846				aLayout = [];
3847				_fnDetectHeader( aLayout, nHeader );
3848			}
3849		}
3850	
3851		for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3852		{
3853			for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3854			{
3855				if ( aLayout[i][j].unique &&
3856					 (!aReturn[j] || !oSettings.bSortCellsTop) )
3857				{
3858					aReturn[j] = aLayout[i][j].cell;
3859				}
3860			}
3861		}
3862	
3863		return aReturn;
3864	}
3865	
3866	/**
3867	 * 
3867Create an Ajax call based on the table's settings, taking into account that
3868	 * parameters can have multiple forms, and backwards compatibility.
3869	 *
3870	 * @param {object} oSettings dataTables settings object
3871	 * @param {array} data Data to send to the server, required by
3872	 *     DataTables - may be augmented by developer callbacks
3873	 * @param {function} fn Callback function to run when data is obtained
3874	 */
3875	function _fnBuildAjax( oSettings, data, fn )
3876	{
3877		// Compatibility with 1.9-, allow fnServerData and event to manipulate
3878		_fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3879	
3880		// Convert to object based for 1.10+ if using the old array scheme which can
3881		// come from server-side processing or serverParams
3882		if ( data && $.isArray(data) ) {
3883			var tmp = {};
3884			var rbracket = /(.*?)\[\]$/;
3885	
3886			$.each( data, function (key, val) {
3887				var match = val.name.match(rbracket);
3888	
3889				if ( match ) {
3890					// Support for arrays
3891					var name = match[0];
3892	
3893					if ( ! tmp[ name ] ) {
3894						tmp[ name ] = [];
3895					}
3896					tmp[ name ].push( val.value );
3897				}
3898				else {
3899					tmp[val.name] = val.value;
3900				}
3901			} );
3902			data = tmp;
3903		}
3904	
3905		var ajaxData;
3906		var ajax = oSettings.ajax;
3907		var instance = oSettings.oInstance;
3908		var callback = function ( json ) {
3909			_fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3910			fn( json );
3911		};
3912	
3913		if ( $.isPlainObject( ajax ) && ajax.data )
3914		{
3915			ajaxData = ajax.data;
3916	
3917			var newData = $.isFunction( ajaxData ) ?
3918				ajaxData( data, oSettings ) :  // fn can manipulate data or return
3919				ajaxData;                      // an object object or array to merge
3920	
3921			// If the function returned something, use that alone
3922			data = $.isFunction( ajaxData ) && newData ?
3923				newData :
3924				$.extend( true, data, newData );
3925	
3926			// Remove the data property as we've resolved it already and don't want
3927			// jQuery to do it again (it is restored at the end of the function)
3928			delete ajax.data;
3929		}
3930	
3931		var baseAjax = {
3932			"data": data,
3933			"success": function (json) {
3934				var error = json.error || json.sError;
3935				if ( error ) {
3936					_fnLog( oSettings, 0, error );
3937				}
3938	
3939				oSettings.json = json;
3940				callback( json );
3941			},
3942			"dataType": "json",
3943			"cache": false,
3944			"type": oSettings.sServerMethod,
3945			"error": function (xhr, error, thrown) {
3946				var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3947	
3948				if ( $.inArray( true, ret ) === -1 ) {
3949					if ( error == "parsererror" ) {
3950						_fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3951					}
3952					else if ( xhr.readyState === 4 ) {
3953						_fnLog( oSettings, 0, 'Ajax error', 7 );
3954					}
3955				}
3956	
3957				_fnProcessingDisplay( oSettings, false );
3958			}
3959		};
3960	
3961		// Store the data submitted for the API
3962		oSettings.oAjaxData = data;
3963	
3964		// Allow plug-ins and external processes to modify the data
3965		_fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3966	
3967		if ( oSettings.fnServerData )
3968		{
3969			// DataTables 1.9- compatibility
3970			oSettings.fnServerData.call( instance,
3971				oSettings.sAjaxSource,
3972				$.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3973					return { name: key, value: val };
3974				} ),
3975				callback,
3976				oSettings
3977			);
3978		}
3979		else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3980		{
3981			// DataTables 1.9- compatibility
3982			oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3983				url: ajax || oSettings.sAjaxSource
3984			} ) );
3985		}
3986		else if ( $.isFunction( ajax ) )
3987		{
3988			// Is a function - let the caller define what needs to be done
3989			oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3990		}
3991		else
3992		{
3993			// Object to extend the base settings
3994			oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3995	
3996			// Restore for next time around
3997			ajax.data = ajaxData;
3998		}
3999	}
4000	
4001	
4002	/**
4003	 * Update the table using an Ajax call
4004	 *  @param {object} settings dataTables settings object
4005	 *  @returns {boolean} Block the table drawing or not
4006	 *  @memberof DataTable#oApi
4007	 */
4008	function _fnAjaxUpdate( settings )
4009	{
4010		if ( settings.bAjaxDataGet ) {
4011			settings.iDraw++;
4012			_fnProcessingDisplay( settings, true );
4013	
4014			_fnBuildAjax(
4015				settings,
4016				_fnAjaxParameters( settings ),
4017				function(json) {
4018					_fnAjaxUpdateDraw( settings, json );
4019				}
4020			);
4021	
4022			return false;
vendor: 3,908 bytes, lines 4023-4149
4023		}
4024		return true;
4025	}
4026	
4027	
4028	/**
4029	 * Build up the parameters in an object needed for a server-side processing
4030	 * request. Note that this is basically done twice, is different ways - a modern
4031	 * method which is used by default in DataTables 1.10 which uses objects and
4032	 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
4033	 * the sAjaxSource option is used in the initialisation, or the legacyAjax
4034	 * option is set.
4035	 *  @param {object} oSettings dataTables settings object
4036	 *  @returns {bool} block the table drawing or not
4037	 *  @memberof DataTable#oApi
4038	 */
4039	function _fnAjaxParameters( settings )
4040	{
4041		var
4042			columns = settings.aoColumns,
4043			columnCount = columns.length,
4044			features = settings.oFeatures,
4045			preSearch = settings.oPreviousSearch,
4046			preColSearch = settings.aoPreSearchCols,
4047			i, data = [], dataProp, column, columnSearch,
4048			sort = _fnSortFlatten( settings ),
4049			displayStart = settings._iDisplayStart,
4050			displayLength = features.bPaginate !== false ?
4051				settings._iDisplayLength :
4052				-1;
4053	
4054		var param = function ( name, value ) {
4055			data.push( { 'name': name, 'value': value } );
4056		};
4057	
4058		// DataTables 1.9- compatible method
4059		param( 'sEcho',          settings.iDraw );
4060		param( 'iColumns',       columnCount );
4061		param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4062		param( 'iDisplayStart',  displayStart );
4063		param( 'iDisplayLength', displayLength );
4064	
4065		// DataTables 1.10+ method
4066		var d = {
4067			draw:    settings.iDraw,
4068			columns: [],
4069			order:   [],
4070			start:   displayStart,
4071			length:  displayLength,
4072			search:  {
4073				value: preSearch.sSearch,
4074				regex: preSearch.bRegex
4075			}
4076		};
4077	
4078		for ( i=0 ; i<columnCount ; i++ ) {
4079			column = columns[i];
4080			columnSearch = preColSearch[i];
4081			dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4082	
4083			d.columns.push( {
4084				data:       dataProp,
4085				name:       column.sName,
4086				searchable: column.bSearchable,
4087				orderable:  column.bSortable,
4088				search:     {
4089					value: columnSearch.sSearch,
4090					regex: columnSearch.bRegex
4091				}
4092			} );
4093	
4094			param( "mDataProp_"+i, dataProp );
4095	
4096			if ( features.bFilter ) {
4097				param( 'sSearch_'+i,     columnSearch.sSearch );
4098				param( 'bRegex_'+i,      columnSearch.bRegex );
4099				param( 'bSearchable_'+i, column.bSearchable );
4100			}
4101	
4102			if ( features.bSort ) {
4103				param( 'bSortable_'+i, column.bSortable );
4104			}
4105		}
4106	
4107		if ( features.bFilter ) {
4108			param( 'sSearch', preSearch.sSearch );
4109			param( 'bRegex', preSearch.bRegex );
4110		}
4111	
4112		if ( features.bSort ) {
4113			$.each( sort, function ( i, val ) {
4114				d.order.push( { column: val.col, dir: val.dir } );
4115	
4116				param( 'iSortCol_'+i, val.col );
4117				param( 'sSortDir_'+i, val.dir );
4118			} );
4119	
4120			param( 'iSortingCols', sort.length );
4121		}
4122	
4123		// If the legacy.ajax parameter is null, then we automatically decide which
4124		// form to use, based on sAjaxSource
4125		var legacy = DataTable.ext.legacy.ajax;
4126		if ( legacy === null ) {
4127			return settings.sAjaxSource ? data : d;
4128		}
4129	
4130		// Otherwise, if legacy has been specified then we use that to decide on the
4131		// form
4132		return legacy ? data : d;
4133	}
4134	
4135	
4136	/**
4137	 * Data the data from the server (nuking the old) and redraw the table
4138	 *  @param {object} oSettings dataTables settings object
4139	 *  @param {object} json json data return from the server.
4140	 *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4141	 *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4142	 *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4143	 *  @param {array} json.aaData The data to display on this page
4144	 *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4145	 *  @memberof DataTable#oApi
4146	 */
4147	function _fnAjaxUpdateDraw ( settings, json )
4148	{
4149		// v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4150		// Support both
4151		var compat = function ( old, modern ) {
4152			return json[old] !== undefined ? json[old] : json[modern];
4153		};
4154	
4155		var data = _fnAjaxDataSrc( settings, json );
4156		var draw            = compat( 'sEcho',                'draw' );
4157		var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4158		var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4159	
4160		if ( draw ) {
4161			// Protect against out of sequence returns
4162			if ( draw*1 < settings.iDraw ) {
4163				return;
4164			}
4165			settings.iDraw = draw * 1;
4166		}
4167	
4168		_fnClearTable( settings );
4169		settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4170		settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4171	
4172		for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4173			_fnAddData( settings, data[i] );
4174		}
4175		settings.aiDisplay = settings.aiDisplayMaster.slice();
4176	
4177		settings.bAjaxDataGet = false;
4178		_fnDraw( settings );
4179	
4180		if ( ! settings._bInitComplete ) {
4181			_fnInitComplete( settings, json );
4182		}
4183	
4184		settings.bAjaxDataGet = true;
4185		_fnProcessingDisplay( settings, false );
4186	}
4187	
4188	
4189	/**
4190	 * Get the data from the JSON data source to use for drawing a table. Using
4191	 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4192	 * source object, or from a processing function.
4193	 *  @param {object} oSettings dataTables settings object
4194	 *  @param  {object} json Data source object / array from the server
4195	 *  @return {array} Array of data to use
4196	 */
4197	function _fnAjaxDataSrc ( oSettings, json )
4198	{
4199		var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4200			oSettings.ajax.dataSrc :
4201			oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4202	
4203		// Compatibility with 1.9-. In order to read from aaData, check if the
4204		// default has been changed, if not, check for aaData
4205		if ( dataSrc === 'data' ) {
4206			return json.aaData || json[dataSrc];
4207		}
4208	
4209		return dataSrc !== "" ?
4210			_fnGetObjectDataFn( dataSrc )( json ) :
4211			json;
4212	}
4213	
4214	/**
4215	 * Generate the node required for filtering text
4216	 *  @returns {node} Filter control element
4217	 *  @param {object} oSettings dataTables settings object
4218	 *  @memberof DataTable#oApi
4219	 */
4220	function _fnFeatureHtmlFilter ( settings )
4221	{
4222		var classes = settings.oClasses;
4223		var tableId = settings.sTableId;
4224		var language = settings.oLanguage;
4225		var previousSearch = settings.oPreviousSearch;
4226		var features = settings.aanFeatures;
4227		var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4228	
4229		var str = language.sSearch;
4230		str = str.match(/_INPUT_/) ?
4231			str.replace('_INPUT_', input) :
4232			str+input;
4233	
4234		var filter = $('<div/>', {
4235				'id': ! features.f ? tableId+'_filter' : null,
4236				'class': classes.sFilter
4237			} )
4238			.append( $('<label/>' ).append( str ) );
4239	
4240		var searchFn = function() {
4241			/* Update all other filter input elements for the new display */
4242			var n = features.f;
4243			var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4244	
4245			/* Now do the filter */
4246			if ( val != previousSearch.sSearch ) {
4247				_fnFilterComplete( settings, {
4248					"sSearch": val,
4249					"bRegex": previousSearch.bRegex,
4250					"bSmart": previousSearch.bSmart ,
4251					"bCaseInsensitive": previousSearch.bCaseInsensitive
4252				} );
4253	
4254				// Need to redraw, without resorting
4255				settings._iDisplayStart = 0;
4256				_fnDraw( settings );
4257			}
4258		};
4259	
4260		var searchDelay = settings.searchDelay !== null ?
4261			settings.searchDelay :
4262			_fnDataSource( settings ) === 'ssp' ?
4263				400 :
4264				0;
4265	
4266		var jqFilter = $('input', filter)
4267			.val( previousSearch.sSearch )
4268			.attr( 'placeholder', language.sSearchPlaceholder )
4269			.on(
4270				'keyup.DT search.DT input.DT paste.DT cut.DT',
4271				searchDelay ?
4272					_fnThrottle( searchFn, searchDelay ) :
4273					searchFn
4274			)
4275			.on( 'keypress.DT', function(e) {
4276				/* Prevent form submission */
4277				if ( e.keyCode == 13 ) {
4278					return false;
4279				}
4280			} )
4281			.attr('aria-controls', tableId);
4282	
4283		// Update the input elements whenever the table is filtered
4284		$(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4285			if ( settings === s ) {
4286				// IE9 throws an 'unknown error' if document.activeElement is used
4287				// inside an iframe or frame...
vendor: 35,087 bytes, lines 4288-5502
4288				try {
4289					if ( jqFilter[0] !== document.activeElement ) {
4290						jqFilter.val( previousSearch.sSearch );
4291					}
4292				}
4293				catch ( e ) {}
4294			}
4295		} );
4296	
4297		return filter[0];
4298	}
4299	
4300	
4301	/**
4302	 * Filter the table using both the global filter and column based filtering
4303	 *  @param {object} oSettings dataTables settings object
4304	 *  @param {object} oSearch search information
4305	 *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4306	 *  @memberof DataTable#oApi
4307	 */
4308	function _fnFilterComplete ( oSettings, oInput, iForce )
4309	{
4310		var oPrevSearch = oSettings.oPreviousSearch;
4311		var aoPrevSearch = oSettings.aoPreSearchCols;
4312		var fnSaveFilter = function ( oFilter ) {
4313			/* Save the filtering values */
4314			oPrevSearch.sSearch = oFilter.sSearch;
4315			oPrevSearch.bRegex = oFilter.bRegex;
4316			oPrevSearch.bSmart = oFilter.bSmart;
4317			oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4318		};
4319		var fnRegex = function ( o ) {
4320			// Backwards compatibility with the bEscapeRegex option
4321			return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4322		};
4323	
4324		// Resolve any column types that are unknown due to addition or invalidation
4325		// @todo As per sort - can this be moved into an event handler?
4326		_fnColumnTypes( oSettings );
4327	
4328		/* In server-side processing all filtering is done by the server, so no point hanging around here */
4329		if ( _fnDataSource( oSettings ) != 'ssp' )
4330		{
4331			/* Global filter */
4332			_fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4333			fnSaveFilter( oInput );
4334	
4335			/* Now do the individual column filter */
4336			for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4337			{
4338				_fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4339					aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4340			}
4341	
4342			/* Custom filtering */
4343			_fnFilterCustom( oSettings );
4344		}
4345		else
4346		{
4347			fnSaveFilter( oInput );
4348		}
4349	
4350		/* Tell the draw function we have been filtering */
4351		oSettings.bFiltered = true;
4352		_fnCallbackFire( oSettings, null, 'search', [oSettings] );
4353	}
4354	
4355	
4356	/**
4357	 * Apply custom filtering functions
4358	 *  @param {object} oSettings dataTables settings object
4359	 *  @memberof DataTable#oApi
4360	 */
4361	function _fnFilterCustom( settings )
4362	{
4363		var filters = DataTable.ext.search;
4364		var displayRows = settings.aiDisplay;
4365		var row, rowIdx;
4366	
4367		for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4368			var rows = [];
4369	
4370			// Loop over each row and see if it should be included
4371			for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4372				rowIdx = displayRows[ j ];
4373				row = settings.aoData[ rowIdx ];
4374	
4375				if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4376					rows.push( rowIdx );
4377				}
4378			}
4379	
4380			// So the array reference doesn't break set the results into the
4381			// existing array
4382			displayRows.length = 0;
4383			$.merge( displayRows, rows );
4384		}
4385	}
4386	
4387	
4388	/**
4389	 * Filter the table on a per-column basis
4390	 *  @param {object} oSettings dataTables settings object
4391	 *  @param {string} sInput string to filter on
4392	 *  @param {int} iColumn column to filter
4393	 *  @param {bool} bRegex treat search string as a regular expression or not
4394	 *  @param {bool} bSmart use smart filtering or not
4395	 *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4396	 *  @memberof DataTable#oApi
4397	 */
4398	function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4399	{
4400		if ( searchStr === '' ) {
4401			return;
4402		}
4403	
4404		var data;
4405		var out = [];
4406		var display = settings.aiDisplay;
4407		var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4408	
4409		for ( var i=0 ; i<display.length ; i++ ) {
4410			data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4411	
4412			if ( rpSearch.test( data ) ) {
4413				out.push( display[i] );
4414			}
4415		}
4416	
4417		settings.aiDisplay = out;
4418	}
4419	
4420	
4421	/**
4422	 * Filter the data table based on user input and draw the table
4423	 *  @param {object} settings dataTables settings object
4424	 *  @param {string} input string to filter on
4425	 *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4426	 *  @param {bool} regex treat as a regular expression or not
4427	 *  @param {bool} smart perform smart filtering or not
4428	 *  @param {bool} caseInsensitive Do case insenstive matching or not
4429	 *  @memberof DataTable#oApi
4430	 */
4431	function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4432	{
4433		var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4434		var prevSearch = settings.oPreviousSearch.sSearch;
4435		var displayMaster = settings.aiDisplayMaster;
4436		var display, invalidated, i;
4437		var filtered = [];
4438	
4439		// Need to take account of custom filtering functions - always filter
4440		if ( DataTable.ext.search.length !== 0 ) {
4441			force = true;
4442		}
4443	
4444		// Check if any of the rows were invalidated
4445		invalidated = _fnFilterData( settings );
4446	
4447		// If the input is blank - we just want the full data set
4448		if ( input.length <= 0 ) {
4449			settings.aiDisplay = displayMaster.slice();
4450		}
4451		else {
4452			// New search - start from the master array
4453			if ( invalidated ||
4454				 force ||
4455				 prevSearch.length > input.length ||
4456				 input.indexOf(prevSearch) !== 0 ||
4457				 settings.bSorted // On resort, the display master needs to be
4458				                  // re-filtered since indexes will have changed
4459			) {
4460				settings.aiDisplay = displayMaster.slice();
4461			}
4462	
4463			// Search the display array
4464			display = settings.aiDisplay;
4465	
4466			for ( i=0 ; i<display.length ; i++ ) {
4467				if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4468					filtered.push( display[i] );
4469				}
4470			}
4471	
4472			settings.aiDisplay = filtered;
4473		}
4474	}
4475	
4476	
4477	/**
4478	 * Build a regular expression object suitable for searching a table
4479	 *  @param {string} sSearch string to search for
4480	 *  @param {bool} bRegex treat as a regular expression or not
4481	 *  @param {bool} bSmart perform smart filtering or not
4482	 *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4483	 *  @returns {RegExp} constructed object
4484	 *  @memberof DataTable#oApi
4485	 */
4486	function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4487	{
4488		search = regex ?
4489			search :
4490			_fnEscapeRegex( search );
4491		
4492		if ( smart ) {
4493			/* For smart filtering we want to allow the search to work regardless of
4494			 * word order. We also want double quoted text to be preserved, so word
4495			 * order is important - a la google. So this is what we want to
4496			 * generate:
4497			 * 
4498			 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4499			 */
4500			var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4501				if ( word.charAt(0) === '"' ) {
4502					var m = word.match( /^"(.*)"$/ );
4503					word = m ? m[1] : word;
4504				}
4505	
4506				return word.replace('"', '');
4507			} );
4508	
4509			search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4510		}
4511	
4512		return new RegExp( search, caseInsensitive ? 'i' : '' );
4513	}
4514	
4515	
4516	/**
4517	 * Escape a string such that it can be used in a regular expression
4518	 *  @param {string} sVal string to escape
4519	 *  @returns {string} escaped string
4520	 *  @memberof DataTable#oApi
4521	 */
4522	var _fnEscapeRegex = DataTable.util.escapeRegex;
4523	
4524	var __filter_div = $('<div>')[0];
4525	var __filter_div_textContent = __filter_div.textContent !== undefined;
4526	
4527	// Update the filtering data for each row if needed (by invalidation or first run)
4528	function _fnFilterData ( settings )
4529	{
4530		var columns = settings.aoColumns;
4531		var column;
4532		var i, j, ien, jen, filterData, cellData, row;
4533		var fomatters = DataTable.ext.type.search;
4534		var wasInvalidated = false;
4535	
4536		for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4537			row = settings.aoData[i];
4538	
4539			if ( ! row._aFilterData ) {
4540				filterData = [];
4541	
4542				for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4543					column = columns[j];
4544	
4545					if ( column.bSearchable ) {
4546						cellData = _fnGetCellData( settings, i, j, 'filter' );
4547	
4548						if ( fomatters[ column.sType ] ) {
4549							cellData = fomatters[ column.sType ]( cellData );
4550						}
4551	
4552						// Search in DataTables 1.10 is string based. In 1.11 this
4553						// should be altered to also allow strict type checking.
4554						if ( cellData === null ) {
4555							cellData = '';
4556						}
4557	
4558						if ( typeof cellData !== 'string' && cellData.toString ) {
4559							cellData = cellData.toString();
4560						}
4561					}
4562					else {
4563						cellData = '';
4564					}
4565	
4566					// If it looks like there is an HTML entity in the string,
4567					// attempt to decode it so sorting works as expected. Note that
4568					// we could use a single line of jQuery to do this, but the DOM
4569					// method used here is much faster http://jsperf.com/html-decode
4570					if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4571						__filter_div.innerHTML = cellData;
4572						cellData = __filter_div_textContent ?
4573							__filter_div.textContent :
4574							__filter_div.innerText;
4575					}
4576	
4577					if ( cellData.replace ) {
4578						cellData = cellData.replace(/[\r\n]/g, '');
4579					}
4580	
4581					filterData.push( cellData );
4582				}
4583	
4584				row._aFilterData = filterData;
4585				row._sFilterRow = filterData.join('  ');
4586				wasInvalidated = true;
4587			}
4588		}
4589	
4590		return wasInvalidated;
4591	}
4592	
4593	
4594	/**
4595	 * Convert from the internal Hungarian notation to camelCase for external
4596	 * interaction
4597	 *  @param {object} obj Object to convert
4598	 *  @returns {object} Inverted object
4599	 *  @memberof DataTable#oApi
4600	 */
4601	function _fnSearchToCamel ( obj )
4602	{
4603		return {
4604			search:          obj.sSearch,
4605			smart:           obj.bSmart,
4606			regex:           obj.bRegex,
4607			caseInsensitive: obj.bCaseInsensitive
4608		};
4609	}
4610	
4611	
4612	
4613	/**
4614	 * Convert from camelCase notation to the internal Hungarian. We could use the
4615	 * Hungarian convert function here, but this is cleaner
4616	 *  @param {object} obj Object to convert
4617	 *  @returns {object} Inverted object
4618	 *  @memberof DataTable#oApi
4619	 */
4620	function _fnSearchToHung ( obj )
4621	{
4622		return {
4623			sSearch:          obj.search,
4624			bSmart:           obj.smart,
4625			bRegex:           obj.regex,
4626			bCaseInsensitive: obj.caseInsensitive
4627		};
4628	}
4629	
4630	/**
4631	 * Generate the node required for the info display
4632	 *  @param {object} oSettings dataTables settings object
4633	 *  @returns {node} Information element
4634	 *  @memberof DataTable#oApi
4635	 */
4636	function _fnFeatureHtmlInfo ( settings )
4637	{
4638		var
4639			tid = settings.sTableId,
4640			nodes = settings.aanFeatures.i,
4641			n = $('<div/>', {
4642				'class': settings.oClasses.sInfo,
4643				'id': ! nodes ? tid+'_info' : null
4644			} );
4645	
4646		if ( ! nodes ) {
4647			// Update display on each draw
4648			settings.aoDrawCallback.push( {
4649				"fn": _fnUpdateInfo,
4650				"sName": "information"
4651			} );
4652	
4653			n
4654				.attr( 'role', 'status' )
4655				.attr( 'aria-live', 'polite' );
4656	
4657			// Table is described by our info div
4658			$(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4659		}
4660	
4661		return n[0];
4662	}
4663	
4664	
4665	/**
4666	 * Update the information elements in the display
4667	 *  @param {object} settings dataTables settings object
4668	 *  @memberof DataTable#oApi
4669	 */
4670	function _fnUpdateInfo ( settings )
4671	{
4672		/* Show information about the table */
4673		var nodes = settings.aanFeatures.i;
4674		if ( nodes.length === 0 ) {
4675			return;
4676		}
4677	
4678		var
4679			lang  = settings.oLanguage,
4680			start = settings._iDisplayStart+1,
4681			end   = settings.fnDisplayEnd(),
4682			max   = settings.fnRecordsTotal(),
4683			total = settings.fnRecordsDisplay(),
4684			out   = total ?
4685				lang.sInfo :
4686				lang.sInfoEmpty;
4687	
4688		if ( total !== max ) {
4689			/* Record set after filtering */
4690			out += ' ' + lang.sInfoFiltered;
4691		}
4692	
4693		// Convert the macros
4694		out += lang.sInfoPostFix;
4695		out = _fnInfoMacros( settings, out );
4696	
4697		var callback = lang.fnInfoCallback;
4698		if ( callback !== null ) {
4699			out = callback.call( settings.oInstance,
4700				settings, start, end, max, total, out
4701			);
4702		}
4703	
4704		$(nodes).html( out );
4705	}
4706	
4707	
4708	function _fnInfoMacros ( settings, str )
4709	{
4710		// When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4711		// internally
4712		var
4713			formatter  = settings.fnFormatNumber,
4714			start      = settings._iDisplayStart+1,
4715			len        = settings._iDisplayLength,
4716			vis        = settings.fnRecordsDisplay(),
4717			all        = len === -1;
4718	
4719		return str.
4720			replace(/_START_/g, formatter.call( settings, start ) ).
4721			replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4722			replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4723			replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4724			replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4725			replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4726	}
4727	
4728	
4729	
4730	/**
4731	 * Draw the table for the first time, adding all required features
4732	 *  @param {object} settings dataTables settings object
4733	 *  @memberof DataTable#oApi
4734	 */
4735	function _fnInitialise ( settings )
4736	{
4737		var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4738		var columns = settings.aoColumns, column;
4739		var features = settings.oFeatures;
4740		var deferLoading = settings.bDeferLoading; // value modified by the draw
4741	
4742		/* Ensure that the table data is fully initialised */
4743		if ( ! settings.bInitialised ) {
4744			setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4745			return;
4746		}
4747	
4748		/* Show the display HTML options */
4749		_fnAddOptionsHtml( settings );
4750	
4751		/* Build and draw the header / footer for the table */
4752		_fnBuildHead( settings );
4753		_fnDrawHead( settings, settings.aoHeader );
4754		_fnDrawHead( settings, settings.aoFooter );
4755	
4756		/* Okay to show that something is going on now */
4757		_fnProcessingDisplay( settings, true );
4758	
4759		/* Calculate sizes for columns */
4760		if ( features.bAutoWidth ) {
4761			_fnCalculateColumnWidths( settings );
4762		}
4763	
4764		for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4765			column = columns[i];
4766	
4767			if ( column.sWidth ) {
4768				column.nTh.style.width = _fnStringToCss( column.sWidth );
4769			}
4770		}
4771	
4772		_fnCallbackFire( settings, null, 'preInit', [settings] );
4773	
4774		// If there is default sorting required - let's do it. The sort function
4775		// will do the drawing for us. Otherwise we draw the table regardless of the
4776		// Ajax source - this allows the table to look initialised for Ajax sourcing
4777		// data (show 'loading' message possibly)
4778		_fnReDraw( settings );
4779	
4780		// Server-side processing init complete is done by _fnAjaxUpdateDraw
4781		var dataSrc = _fnDataSource( settings );
4782		if ( dataSrc != 'ssp' || deferLoading ) {
4783			// if there is an ajax source load the data
4784			if ( dataSrc == 'ajax' ) {
4785				_fnBuildAjax( settings, [], function(json) {
4786					var aData = _fnAjaxDataSrc( settings, json );
4787	
4788					// Got the data - add it to the table
4789					for ( i=0 ; i<aData.length ; i++ ) {
4790						_fnAddData( settings, aData[i] );
4791					}
4792	
4793					// Reset the init display for cookie saving. We've already done
4794					// a filter, and therefore cleared it before. So we need to make
4795					// it appear 'fresh'
4796					settings.iInitDisplayStart = iAjaxStart;
4797	
4798					_fnReDraw( settings );
4799	
4800					_fnProcessingDisplay( settings, false );
4801					_fnInitComplete( settings, json );
4802				}, settings );
4803			}
4804			else {
4805				_fnProcessingDisplay( settings, false );
4806				_fnInitComplete( settings );
4807			}
4808		}
4809	}
4810	
4811	
4812	/**
4813	 * Draw the table for the first time, adding all required features
4814	 *  @param {object} oSettings dataTables settings object
4815	 *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4816	 *    with client-side processing (optional)
4817	 *  @memberof DataTable#oApi
4818	 */
4819	function _fnInitComplete ( settings, json )
4820	{
4821		settings._bInitComplete = true;
4822	
4823		// When data was added after the initialisation (data or Ajax) we need to
4824		// calculate the column sizing
4825		if ( json || settings.oInit.aaData ) {
4826			_fnAdjustColumnSizing( settings );
4827		}
4828	
4829		_fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4830		_fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4831	}
4832	
4833	
4834	function _fnLengthChange ( settings, val )
4835	{
4836		var len = parseInt( val, 10 );
4837		settings._iDisplayLength = len;
4838	
4839		_fnLengthOverflow( settings );
4840	
4841		// Fire length change event
4842		_fnCallbackFire( settings, null, 'length', [settings, len] );
4843	}
4844	
4845	
4846	/**
4847	 * Generate the node required for user display length changing
4848	 *  @param {object} settings dataTables settings object
4849	 *  @returns {node} Display length feature node
4850	 *  @memberof DataTable#oApi
4851	 */
4852	function _fnFeatureHtmlLength ( settings )
4853	{
4854		var
4855			classes  = settings.oClasses,
4856			tableId  = settings.sTableId,
4857			menu     = settings.aLengthMenu,
4858			d2       = $.isArray( menu[0] ),
4859			lengths  = d2 ? menu[0] : menu,
4860			language = d2 ? menu[1] : menu;
4861	
4862		var select = $('<select/>', {
4863			'name':          tableId+'_length',
4864			'aria-controls': tableId,
4865			'class':         classes.sLengthSelect
4866		} );
4867	
4868		for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4869			select[0][ i ] = new Option(
4870				typeof language[i] === 'number' ?
4871					settings.fnFormatNumber( language[i] ) :
4872					language[i],
4873				lengths[i]
4874			);
4875		}
4876	
4877		var div = $('<div><label/></div>').addClass( classes.sLength );
4878		if ( ! settings.aanFeatures.l ) {
4879			div[0].id = tableId+'_length';
4880		}
4881	
4882		div.children().append(
4883			settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4884		);
4885	
4886		// Can't use `select` variable as user might provide their own and the
4887		// reference is broken by the use of outerHTML
4888		$('select', div)
4889			.val( settings._iDisplayLength )
4890			.on( 'change.DT', function(e) {
4891				_fnLengthChange( settings, $(this).val() );
4892				_fnDraw( settings );
4893			} );
4894	
4895		// Update node value whenever anything changes the table's length
4896		$(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4897			if ( settings === s ) {
4898				$('select', div).val( len );
4899			}
4900		} );
4901	
4902		return div[0];
4903	}
4904	
4905	
4906	
4907	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4908	 * Note that most of the paging logic is done in
4909	 * DataTable.ext.pager
4910	 */
4911	
4912	/**
4913	 * Generate the node required for default pagination
4914	 *  @param {object} oSettings dataTables settings object
4915	 *  @returns {node} Pagination feature node
4916	 *  @memberof DataTable#oApi
4917	 */
4918	function _fnFeatureHtmlPaginate ( settings )
4919	{
4920		var
4921			type   = settings.sPaginationType,
4922			plugin = DataTable.ext.pager[ type ],
4923			modern = typeof plugin === 'function',
4924			redraw = function( settings ) {
4925				_fnDraw( settings );
4926			},
4927			node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4928			features = settings.aanFeatures;
4929	
4930		if ( ! modern ) {
4931			plugin.fnInit( settings, node, redraw );
4932		}
4933	
4934		/* Add a draw callback for the pagination on first instance, to update the paging display */
4935		if ( ! features.p )
4936		{
4937			node.id = settings.sTableId+'_paginate';
4938	
4939			settings.aoDrawCallback.push( {
4940				"fn": function( settings ) {
4941					if ( modern ) {
4942						var
4943							start      = settings._iDisplayStart,
4944							len        = settings._iDisplayLength,
4945							visRecords = settings.fnRecordsDisplay(),
4946							all        = len === -1,
4947							page = all ? 0 : Math.ceil( start / len ),
4948							pages = all ? 1 : Math.ceil( visRecords / len ),
4949							buttons = plugin(page, pages),
4950							i, ien;
4951	
4952						for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4953							_fnRenderer( settings, 'pageButton' )(
4954								settings, features.p[i], i, buttons, page, pages
4955							);
4956						}
4957					}
4958					else {
4959						plugin.fnUpdate( settings, redraw );
4960					}
4961				},
4962				"sName": "pagination"
4963			} );
4964		}
4965	
4966		return node;
4967	}
4968	
4969	
4970	/**
4971	 * Alter the display settings to change the page
4972	 *  @param {object} settings DataTables settings object
4973	 *  @param {string|int} action Paging action to take: "first", "previous",
4974	 *    "next" or "last" or page number to jump to (integer)
4975	 *  @param [bool] redraw Automatically draw the update or not
4976	 *  @returns {bool} true page has changed, false - no change
4977	 *  @memberof DataTable#oApi
4978	 */
4979	function _fnPageChange ( settings, action, redraw )
4980	{
4981		var
4982			start     = settings._iDisplayStart,
4983			len       = settings._iDisplayLength,
4984			records   = settings.fnRecordsDisplay();
4985	
4986		if ( records === 0 || len === -1 )
4987		{
4988			start = 0;
4989		}
4990		else if ( typeof action === "number" )
4991		{
4992			start = action * len;
4993	
4994			if ( start > records )
4995			{
4996				start = 0;
4997			}
4998		}
4999		else if ( action == "first" )
5000		{
5001			start = 0;
5002		}
5003		else if ( action == "previous" )
5004		{
5005			start = len >= 0 ?
5006				start - len :
5007				0;
5008	
5009			if ( start < 0 )
5010			{
5011			  start = 0;
5012			}
5013		}
5014		else if ( action == "next" )
5015		{
5016			if ( start + len < records )
5017			{
5018				start += len;
5019			}
5020		}
5021		else if ( action == "last" )
5022		{
5023			start = Math.floor( (records-1) / len) * len;
5024		}
5025		else
5026		{
5027			_fnLog( settings, 0, "Unknown paging action: "+action, 5 );
5028		}
5029	
5030		var changed = settings._iDisplayStart !== start;
5031		settings._iDisplayStart = start;
5032	
5033		if ( changed ) {
5034			_fnCallbackFire( settings, null, 'page', [settings] );
5035	
5036			if ( redraw ) {
5037				_fnDraw( settings );
5038			}
5039		}
5040	
5041		return changed;
5042	}
5043	
5044	
5045	
5046	/**
5047	 * Generate the node required for the processing node
5048	 *  @param {object} settings dataTables settings object
5049	 *  @returns {node} Processing element
5050	 *  @memberof DataTable#oApi
5051	 */
5052	function _fnFeatureHtmlProcessing ( settings )
5053	{
5054		return $('<div/>', {
5055				'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5056				'class': settings.oClasses.sProcessing
5057			} )
5058			.html( settings.oLanguage.sProcessing )
5059			.insertBefore( settings.nTable )[0];
5060	}
5061	
5062	
5063	/**
5064	 * Display or hide the processing indicator
5065	 *  @param {object} settings dataTables settings object
5066	 *  @param {bool} show Show the processing indicator (true) or not (false)
5067	 *  @memberof DataTable#oApi
5068	 */
5069	function _fnProcessingDisplay ( settings, show )
5070	{
5071		if ( settings.oFeatures.bProcessing ) {
5072			$(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5073		}
5074	
5075		_fnCallbackFire( settings, null, 'processing', [settings, show] );
5076	}
5077	
5078	/**
5079	 * Add any control elements for the table - specifically scrolling
5080	 *  @param {object} settings dataTables settings object
5081	 *  @returns {node} Node to add to the DOM
5082	 *  @memberof DataTable#oApi
5083	 */
5084	function _fnFeatureHtmlTable ( settings )
5085	{
5086		var table = $(settings.nTable);
5087	
5088		// Add the ARIA grid role to the table
5089		table.attr( 'role', 'grid' );
5090	
5091		// Scrolling from here on in
5092		var scroll = settings.oScroll;
5093	
5094		if ( scroll.sX === '' && scroll.sY === '' ) {
5095			return settings.nTable;
5096		}
5097	
5098		var scrollX = scroll.sX;
5099		var scrollY = scroll.sY;
5100		var classes = settings.oClasses;
5101		var caption = table.children('caption');
5102		var captionSide = caption.length ? caption[0]._captionSide : null;
5103		var headerClone = $( table[0].cloneNode(false) );
5104		var footerClone = $( table[0].cloneNode(false) );
5105		var footer = table.children('tfoot');
5106		var _div = '<div/>';
5107		var size = function ( s ) {
5108			return !s ? null : _fnStringToCss( s );
5109		};
5110	
5111		if ( ! footer.length ) {
5112			footer = null;
5113		}
5114	
5115		/*
5116		 * The HTML structure that we want to generate in this function is:
5117		 *  div - scroller
5118		 *    div - scroll head
5119		 *      div - scroll head inner
5120		 *        table - scroll head table
5121		 *          thead - thead
5122		 *    div - scroll body
5123		 *      table - table (master table)
5124		 *        thead - thead clone for sizing
5125		 *        tbody - tbody
5126		 *    div - scroll foot
5127		 *      div - scroll foot inner
5128		 *        table - scroll foot table
5129		 *          tfoot - tfoot
5130		 */
5131		var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5132			.append(
5133				$(_div, { 'class': classes.sScrollHead } )
5134					.css( {
5135						overflow: 'hidden',
5136						position: 'relative',
5137						border: 0,
5138						width: scrollX ? size(scrollX) : '100%'
5139					} )
5140					.append(
5141						$(_div, { 'class': classes.sScrollHeadInner } )
5142							.css( {
5143								'box-sizing': 'content-box',
5144								width: scroll.sXInner || '100%'
5145							} )
5146							.append(
5147								headerClone
5148									.removeAttr('id')
5149									.css( 'margin-left', 0 )
5150									.append( captionSide === 'top' ? caption : null )
5151									.append(
5152										table.children('thead')
5153									)
5154							)
5155					)
5156			)
5157			.append(
5158				$(_div, { 'class': classes.sScrollBody } )
5159					.css( {
5160						position: 'relative',
5161						overflow: 'auto',
5162						width: size( scrollX )
5163					} )
5164					.append( table )
5165			);
5166	
5167		if ( footer ) {
5168			scroller.append(
5169				$(_div, { 'class': classes.sScrollFoot } )
5170					.css( {
5171						overflow: 'hidden',
5172						border: 0,
5173						width: scrollX ? size(scrollX) : '100%'
5174					} )
5175					.append(
5176						$(_div, { 'class': classes.sScrollFootInner } )
5177							.append(
5178								footerClone
5179									.removeAttr('id')
5180									.css( 'margin-left', 0 )
5181									.append( captionSide === 'bottom' ? caption : null )
5182									.append(
5183										table.children('tfoot')
5184									)
5185							)
5186					)
5187			);
5188		}
5189	
5190		var children = scroller.children();
5191		var scrollHead = children[0];
5192		var scrollBody = children[1];
5193		var scrollFoot = footer ? children[2] : null;
5194	
5195		// When the body is scrolled, then we also want to scroll the headers
5196		if ( scrollX ) {
5197			$(scrollBody).on( 'scroll.DT', function (e) {
5198				var scrollLeft = this.scrollLeft;
5199	
5200				scrollHead.scrollLeft = scrollLeft;
5201	
5202				if ( footer ) {
5203					scrollFoot.scrollLeft = scrollLeft;
5204				}
5205			} );
5206		}
5207	
5208		$(scrollBody).css(
5209			scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5210			scrollY
5211		);
5212	
5213		settings.nScrollHead = scrollHead;
5214		settings.nScrollBody = scrollBody;
5215		settings.nScrollFoot = scrollFoot;
5216	
5217		// On redraw - align columns
5218		settings.aoDrawCallback.push( {
5219			"fn": _fnScrollDraw,
5220			"sName": "scrolling"
5221		} );
5222	
5223		return scroller[0];
5224	}
5225	
5226	
5227	
5228	/**
5229	 * Update the header, footer and body tables for resizing - i.e. column
5230	 * alignment.
5231	 *
5232	 * Welcome to the most horrible function DataTables. The process that this
5233	 * function follows is basically:
5234	 *   1. Re-create the table inside the scrolling div
5235	 *   2. Take live measurements from the DOM
5236	 *   3. Apply the measurements to align the columns
5237	 *   4. Clean up
5238	 *
5239	 *  @param {object} settings dataTables settings object
5240	 *  @memberof DataTable#oApi
5241	 */
5242	function _fnScrollDraw ( settings )
5243	{
5244		// Given that this is such a monster function, a lot of variables are use
5245		// to try and keep the minimised size as small as possible
5246		var
5247			scroll         = settings.oScroll,
5248			scrollX        = scroll.sX,
5249			scrollXInner   = scroll.sXInner,
5250			scrollY        = scroll.sY,
5251			barWidth       = scroll.iBarWidth,
5252			divHeader      = $(settings.nScrollHead),
5253			divHeaderStyle = divHeader[0].style,
5254			divHeaderInner = divHeader.children('div'),
5255			divHeaderInnerStyle = divHeaderInner[0].style,
5256			divHeaderTable = divHeaderInner.children('table'),
5257			divBodyEl      = settings.nScrollBody,
5258			divBody        = $(divBodyEl),
5259			divBodyStyle   = divBodyEl.style,
5260			divFooter      = $(settings.nScrollFoot),
5261			divFooterInner = divFooter.children('div'),
5262			divFooterTable = divFooterInner.children('table'),
5263			header         = $(settings.nTHead),
5264			table          = $(settings.nTable),
5265			tableEl        = table[0],
5266			tableStyle     = tableEl.style,
5267			footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5268			browser        = settings.oBrowser,
5269			ie67           = browser.bScrollOversize,
5270			dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5271			headerTrgEls, footerTrgEls,
5272			headerSrcEls, footerSrcEls,
5273			headerCopy, footerCopy,
5274			headerWidths=[], footerWidths=[],
5275			headerContent=[], footerContent=[],
5276			idx, correction, sanityWidth,
5277			zeroOut = function(nSizer) {
5278				var style = nSizer.style;
5279				style.paddingTop = "0";
5280				style.paddingBottom = "0";
5281				style.borderTopWidth = "0";
5282				style.borderBottomWidth = "0";
5283				style.height = 0;
5284			};
5285	
5286		// If the scrollbar visibility has changed from the last draw, we need to
5287		// adjust the column sizes as the table width will have changed to account
5288		// for the scrollbar
5289		var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5290		
5291		if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5292			settings.scrollBarVis = scrollBarVis;
5293			_fnAdjustColumnSizing( settings );
5294			return; // adjust column sizing will call this function again
5295		}
5296		else {
5297			settings.scrollBarVis = scrollBarVis;
5298		}
5299	
5300		/*
5301		 * 1. Re-create the table inside the scrolling div
5302		 */
5303	
5304		// Remove the old minimised thead and tfoot elements in the inner table
5305		table.children('thead, tfoot').remove();
5306	
5307		if ( footer ) {
5308			footerCopy = footer.clone().prependTo( table );
5309			footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5310			footerSrcEls = footerCopy.find('tr');
5311		}
5312	
5313		// Clone the current header and footer elements and then place it into the inner table
5314		headerCopy = header.clone().prependTo( table );
5315		headerTrgEls = header.find('tr'); // original header is in its own table
5316		headerSrcEls = headerCopy.find('tr');
5317		headerCopy.find('th, td').removeAttr('tabindex');
5318	
5319	
5320		/*
5321		 * 2. Take live measurements from the DOM - do not alter the DOM itself!
5322		 */
5323	
5324		// Remove old sizing and apply the calculated column widths
5325		// Get the unique column headers in the newly created (cloned) header. We want to apply the
5326		// calculated sizes to this header
5327		if ( ! scrollX )
5328		{
5329			divBodyStyle.width = '100%';
5330			divHeader[0].style.width = '100%';
5331		}
5332	
5333		$.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5334			idx = _fnVisibleToColumnIndex( settings, i );
5335			el.style.width = settings.aoColumns[idx].sWidth;
5336		} );
5337	
5338		if ( footer ) {
5339			_fnApplyToChildren( function(n) {
5340				n.style.width = "";
5341			}, footerSrcEls );
5342		}
5343	
5344		// Size the table as a whole
5345		sanityWidth = table.outerWidth();
5346		if ( scrollX === "" ) {
5347			// No x scrolling
5348			tableStyle.width = "100%";
5349	
5350			// IE7 will make the width of the table when 100% include the scrollbar
5351			// - which is shouldn't. When there is a scrollbar we need to take this
5352			// into account.
5353			if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5354				divBody.css('overflow-y') == "scroll")
5355			) {
5356				tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5357			}
5358	
5359			// Recalculate the sanity width
5360			sanityWidth = table.outerWidth();
5361		}
5362		else if ( scrollXInner !== "" ) {
5363			// legacy x scroll inner has been given - use it
5364			tableStyle.width = _fnStringToCss(scrollXInner);
5365	
5366			// Recalculate the sanity width
5367			sanityWidth = table.outerWidth();
5368		}
5369	
5370		// Hidden header should have zero height, so remove padding and borders. Then
5371		// set the width based on the real headers
5372	
5373		// Apply all styles in one pass
5374		_fnApplyToChildren( zeroOut, headerSrcEls );
5375	
5376		// Read all widths in next pass
5377		_fnApplyToChildren( function(nSizer) {
5378			headerContent.push( nSizer.innerHTML );
5379			headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5380		}, headerSrcEls );
5381	
5382		// Apply all widths in final pass
5383		_fnApplyToChildren( function(nToSize, i) {
5384			// Only apply widths to the DataTables detected header cells - this
5385			// prevents complex headers from having contradictory sizes applied
5386			if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5387				nToSize.style.width = headerWidths[i];
5388			}
5389		}, headerTrgEls );
5390	
5391		$(headerSrcEls).height(0);
5392	
5393		/* Same again with the footer if we have one */
5394		if ( footer )
5395		{
5396			_fnApplyToChildren( zeroOut, footerSrcEls );
5397	
5398			_fnApplyToChildren( function(nSizer) {
5399				footerContent.push( nSizer.innerHTML );
5400				footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5401			}, footerSrcEls );
5402	
5403			_fnApplyToChildren( function(nToSize, i) {
5404				nToSize.style.width = footerWidths[i];
5405			}, footerTrgEls );
5406	
5407			$(footerSrcEls).height(0);
5408		}
5409	
5410	
5411		/*
5412		 * 3. Apply the measurements
5413		 */
5414	
5415		// "Hide" the header and footer that we used for the sizing. We need to keep
5416		// the content of the cell so that the width applied to the header and body
5417		// both match, but we want to hide it completely. We want to also fix their
5418		// width to what they currently are
5419		_fnApplyToChildren( function(nSizer, i) {
5420			nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
5421			nSizer.style.width = headerWidths[i];
5422		}, headerSrcEls );
5423	
5424		if ( footer )
5425		{
5426			_fnApplyToChildren( function(nSizer, i) {
5427				nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
5428				nSizer.style.width = footerWidths[i];
5429			}, footerSrcEls );
5430		}
5431	
5432		// Sanity check that the table is of a sensible width. If not then we are going to get
5433		// misalignment - try to prevent this by not allowing the table to shrink below its min width
5434		if ( table.outerWidth() < sanityWidth )
5435		{
5436			// The min width depends upon if we have a vertical scrollbar visible or not */
5437			correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5438				divBody.css('overflow-y') == "scroll")) ?
5439					sanityWidth+barWidth :
5440					sanityWidth;
5441	
5442			// IE6/7 are a law unto themselves...
5443			if ( ie67 && (divBodyEl.scrollHeight >
5444				divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5445			) {
5446				tableStyle.width = _fnStringToCss( correction-barWidth );
5447			}
5448	
5449			// And give the user a warning that we've stopped the table getting too small
5450			if ( scrollX === "" || scrollXInner !== "" ) {
5451				_fnLog( settings, 1, 'Possible column misalignment', 6 );
5452			}
5453		}
5454		else
5455		{
5456			correction = '100%';
5457		}
5458	
5459		// Apply to the container elements
5460		divBodyStyle.width = _fnStringToCss( correction );
5461		divHeaderStyle.width = _fnStringToCss( correction );
5462	
5463		if ( footer ) {
5464			settings.nScrollFoot.style.width = _fnStringToCss( correction );
5465		}
5466	
5467	
5468		/*
5469		 * 4. Clean up
5470		 */
5471		if ( ! scrollY ) {
5472			/* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5473			 * the scrollbar height from the visible display, rather than adding it on. We need to
5474			 * set the height in order to sort this. Don't want to do it in any other browsers.
5475			 */
5476			if ( ie67 ) {
5477				divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5478			}
5479		}
5480	
5481		/* Finally set the width's of the header and footer tables */
5482		var iOuterWidth = table.outerWidth();
5483		divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5484		divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5485	
5486		// Figure out if there are scrollbar present - if so then we need a the header and footer to
5487		// provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5488		var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5489		var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5490		divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5491	
5492		if ( footer ) {
5493			divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5494			divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5495			divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5496		}
5497	
5498		// Correct DOM ordering for colgroup - comes before the thead
5499		table.children('colgroup').insertBefore( table.children('thead') );
5500	
5501		/* Adjust the position of the header in case we loose the y-scrollbar */
5502		divBody.scroll(
vendor: 11,594 bytes, lines 5502-5900
5502);
5503	
5504		// If sorting or filtering has occurred, jump the scrolling back to the top
5505		// only if we aren't holding the position
5506		if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5507			divBodyEl.scrollTop = 0;
5508		}
5509	}
5510	
5511	
5512	
5513	/**
5514	 * Apply a given function to the display child nodes of an element array (typically
5515	 * TD children of TR rows
5516	 *  @param {function} fn Method to apply to the objects
5517	 *  @param array {nodes} an1 List of elements to look through for display children
5518	 *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5519	 *  @memberof DataTable#oApi
5520	 */
5521	function _fnApplyToChildren( fn, an1, an2 )
5522	{
5523		var index=0, i=0, iLen=an1.length;
5524		var nNode1, nNode2;
5525	
5526		while ( i < iLen ) {
5527			nNode1 = an1[i].firstChild;
5528			nNode2 = an2 ? an2[i].firstChild : null;
5529	
5530			while ( nNode1 ) {
5531				if ( nNode1.nodeType === 1 ) {
5532					if ( an2 ) {
5533						fn( nNode1, nNode2, index );
5534					}
5535					else {
5536						fn( nNode1, index );
5537					}
5538	
5539					index++;
5540				}
5541	
5542				nNode1 = nNode1.nextSibling;
5543				nNode2 = an2 ? nNode2.nextSibling : null;
5544			}
5545	
5546			i++;
5547		}
5548	}
5549	
5550	
5551	
5552	var __re_html_remove = /<.*?>/g;
5553	
5554	
5555	/**
5556	 * Calculate the width of columns for the table
5557	 *  @param {object} oSettings dataTables settings object
5558	 *  @memberof DataTable#oApi
5559	 */
5560	function _fnCalculateColumnWidths ( oSettings )
5561	{
5562		var
5563			table = oSettings.nTable,
5564			columns = oSettings.aoColumns,
5565			scroll = oSettings.oScroll,
5566			scrollY = scroll.sY,
5567			scrollX = scroll.sX,
5568			scrollXInner = scroll.sXInner,
5569			columnCount = columns.length,
5570			visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5571			headerCells = $('th', oSettings.nTHead),
5572			tableWidthAttr = table.getAttribute('width'), // from DOM element
5573			tableContainer = table.parentNode,
5574			userInputs = false,
5575			i, column, columnIdx, width, outerWidth,
5576			browser = oSettings.oBrowser,
5577			ie67 = browser.bScrollOversize;
5578	
5579		var styleWidth = table.style.width;
5580		if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5581			tableWidthAttr = styleWidth;
5582		}
5583	
5584		/* Convert any user input sizes into pixel sizes */
5585		for ( i=0 ; i<visibleColumns.length ; i++ ) {
5586			column = columns[ visibleColumns[i] ];
5587	
5588			if ( column.sWidth !== null ) {
5589				column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5590	
5591				userInputs = true;
5592			}
5593		}
5594	
5595		/* If the number of columns in the DOM equals the number that we have to
5596		 * process in DataTables, then we can use the offsets that are created by
5597		 * the web- browser. No custom sizes can be set in order for this to happen,
5598		 * nor scrolling used
5599		 */
5600		if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5601		     columnCount == _fnVisbleColumns( oSettings ) &&
5602		     columnCount == headerCells.length
5603		) {
5604			for ( i=0 ; i<columnCount ; i++ ) {
5605				var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5606	
5607				if ( colIdx !== null ) {
5608					columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5609				}
5610			}
5611		}
5612		else
5613		{
5614			// Otherwise construct a single row, worst case, table with the widest
5615			// node in the data, assign any user defined widths, then insert it into
5616			// the DOM and allow the browser to do all the hard work of calculating
5617			// table widths
5618			var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5619				.css( 'visibility', 'hidden' )
5620				.removeAttr( 'id' );
5621	
5622			// Clean up the table body
5623			tmpTable.find('tbody tr').remove();
5624			var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5625	
5626			// Clone the table header and footer - we can't use the header / footer
5627			// from the cloned table, since if scrolling is active, the table's
5628			// real header and footer are contained in different table tags
5629			tmpTable.find('thead, tfoot').remove();
5630			tmpTable
5631				.append( $(oSettings.nTHead).clone() )
5632				.append( $(oSettings.nTFoot).clone() );
5633	
5634			// Remove any assigned widths from the footer (from scrolling)
5635			tmpTable.find('tfoot th, tfoot td').css('width', '');
5636	
5637			// Apply custom sizing to the cloned header
5638			headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5639	
5640			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5641				column = columns[ visibleColumns[i] ];
5642	
5643				headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5644					_fnStringToCss( column.sWidthOrig ) :
5645					'';
5646	
5647				// For scrollX we need to force the column width otherwise the
5648				// browser will collapse it. If this width is smaller than the
5649				// width the column requires, then it will have no effect
5650				if ( column.sWidthOrig && scrollX ) {
5651					$( headerCells[i] ).append( $('<div/>').css( {
5652						width: column.sWidthOrig,
5653						margin: 0,
5654						padding: 0,
5655						border: 0,
5656						height: 1
5657					} ) );
5658				}
5659			}
5660	
5661			// Find the widest cell for each column and put it into the table
5662			if ( oSettings.aoData.length ) {
5663				for ( i=0 ; i<visibleColumns.length ; i++ ) {
5664					columnIdx = visibleColumns[i];
5665					column = columns[ columnIdx ];
5666	
5667					$( _fnGetWidestNode( oSettings, columnIdx ) )
5668						.clone( false )
5669						.append( column.sContentPadding )
5670						.appendTo( tr );
5671				}
5672			}
5673	
5674			// Tidy the temporary table - remove name attributes so there aren't
5675			// duplicated in the dom (radio elements for example)
5676			$('[name]', tmpTable).removeAttr('name');
5677	
5678			// Table has been built, attach to the document so we can work with it.
5679			// A holding element is used, positioned at the top of the container
5680			// with minimal height, so it has no effect on if the container scrolls
5681			// or not. Otherwise it might trigger scrolling when it actually isn't
5682			// needed
5683			var holder = $('<div/>').css( scrollX || scrollY ?
5684					{
5685						position: 'absolute',
5686						top: 0,
5687						left: 0,
5688						height: 1,
5689						right: 0,
5690						overflow: 'hidden'
5691					} :
5692					{}
5693				)
5694				.append( tmpTable )
5695				.appendTo( tableContainer );
5696	
5697			// When scrolling (X or Y) we want to set the width of the table as 
5698			// appropriate. However, when not scrolling leave the table width as it
5699			// is. This results in slightly different, but I think correct behaviour
5700			if ( scrollX && scrollXInner ) {
5701				tmpTable.width( scrollXInner );
5702			}
5703			else if ( scrollX ) {
5704				tmpTable.css( 'width', 'auto' );
5705				tmpTable.removeAttr('width');
5706	
5707				// If there is no width attribute or style, then allow the table to
5708				// collapse
5709				if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5710					tmpTable.width( tableContainer.clientWidth );
5711				}
5712			}
5713			else if ( scrollY ) {
5714				tmpTable.width( tableContainer.clientWidth );
5715			}
5716			else if ( tableWidthAttr ) {
5717				tmpTable.width( tableWidthAttr );
5718			}
5719	
5720			// Get the width of each column in the constructed table - we need to
5721			// know the inner width (so it can be assigned to the other table's
5722			// cells) and the outer width so we can calculate the full width of the
5723			// table. This is safe since DataTables requires a unique cell for each
5724			// column, but if ever a header can span multiple columns, this will
5725			// need to be modified.
5726			var total = 0;
5727			for ( i=0 ; i<visibleColumns.length ; i++ ) {
5728				var cell = $(headerCells[i]);
5729				var border = cell.outerWidth() - cell.width();
5730	
5731				// Use getBounding... where possible (not IE8-) because it can give
5732				// sub-pixel accuracy, which we then want to round up!
5733				var bounding = browser.bBounding ?
5734					Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5735					cell.outerWidth();
5736	
5737				// Total is tracked to remove any sub-pixel errors as the outerWidth
5738				// of the table might not equal the total given here (IE!).
5739				total += bounding;
5740	
5741				// Width for each column to use
5742				columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5743			}
5744	
5745			table.style.width = _fnStringToCss( total );
5746	
5747			// Finished with the table - ditch it
5748			holder.remove();
5749		}
5750	
5751		// If there is a width attr, we want to attach an event listener which
5752		// allows the table sizing to automatically adjust when the window is
5753		// resized. Use the width attr rather than CSS, since we can't know if the
5754		// CSS is a relative value or absolute - DOM read is always px.
5755		if ( tableWidthAttr ) {
5756			table.style.width = _fnStringToCss( tableWidthAttr );
5757		}
5758	
5759		if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5760			var bindResize = function () {
5761				$(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5762					_fnAdjustColumnSizing( oSettings );
5763				} ) );
5764			};
5765	
5766			// IE6/7 will crash if we bind a resize event handler on page load.
5767			// To be removed in 1.11 which drops IE6/7 support
5768			if ( ie67 ) {
5769				setTimeout( bindResize, 1000 );
5770			}
5771			else {
5772				bindResize();
5773			}
5774	
5775			oSettings._reszEvt = true;
5776		}
5777	}
5778	
5779	
5780	/**
5781	 * Throttle the calls to a function. Arguments and context are maintained for
5782	 * the throttled function
5783	 *  @param {function} fn Function to be called
5784	 *  @param {int} [freq=200] call frequency in mS
5785	 *  @returns {function} wrapped function
5786	 *  @memberof DataTable#oApi
5787	 */
5788	var _fnThrottle = DataTable.util.throttle;
5789	
5790	
5791	/**
5792	 * Convert a CSS unit width to pixels (e.g. 2em)
5793	 *  @param {string} width width to be converted
5794	 *  @param {node} parent parent to get the with for (required for relative widths) - optional
5795	 *  @returns {int} width in pixels
5796	 *  @memberof DataTable#oApi
5797	 */
5798	function _fnConvertToWidth ( width, parent )
5799	{
5800		if ( ! width ) {
5801			return 0;
5802		}
5803	
5804		var n = $('<div/>')
5805			.css( 'width', _fnStringToCss( width ) )
5806			.appendTo( parent || document.body );
5807	
5808		var val = n[0].offsetWidth;
5809		n.remove();
5810	
5811		return val;
5812	}
5813	
5814	
5815	/**
5816	 * Get the widest node
5817	 *  @param {object} settings dataTables settings object
5818	 *  @param {int} colIdx column of interest
5819	 *  @returns {node} widest table node
5820	 *  @memberof DataTable#oApi
5821	 */
5822	function _fnGetWidestNode( settings, colIdx )
5823	{
5824		var idx = _fnGetMaxLenString( settings, colIdx );
5825		if ( idx < 0 ) {
5826			return null;
5827		}
5828	
5829		var data = settings.aoData[ idx ];
5830		return ! data.nTr ? // Might not have been created when deferred rendering
5831			$('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5832			data.anCells[ colIdx ];
5833	}
5834	
5835	
5836	/**
5837	 * Get the maximum strlen for each data column
5838	 *  @param {object} settings dataTables settings object
5839	 *  @param {int} colIdx column of interest
5840	 *  @returns {string} max string length for each column
5841	 *  @memberof DataTable#oApi
5842	 */
5843	function _fnGetMaxLenString( settings, colIdx )
5844	{
5845		var s, max=-1, maxIdx = -1;
5846	
5847		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5848			s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5849			s = s.replace( __re_html_remove, '' );
5850			s = s.replace( /&nbsp;/g, ' ' );
5851	
5852			if ( s.length > max ) {
5853				max = s.length;
5854				maxIdx = i;
5855			}
5856		}
5857	
5858		return maxIdx;
5859	}
5860	
5861	
5862	/**
5863	 * Append a CSS unit (only if required) to a string
5864	 *  @param {string} value to css-ify
5865	 *  @returns {string} value with css unit
5866	 *  @memberof DataTable#oApi
5867	 */
5868	function _fnStringToCss( s )
5869	{
5870		if ( s === null ) {
5871			return '0px';
5872		}
5873	
5874		if ( typeof s == 'number' ) {
5875			return s < 0 ?
5876				'0px' :
5877				s+'px';
5878		}
5879	
5880		// Check it has a unit character already
5881		return s.match(/\d$/) ?
5882			s+'px' :
5883			s;
5884	}
5885	
5886	
5887	
5888	function _fnSortFlatten ( settings )
5889	{
5890		var
5891			i, iLen, k, kLen,
5892			aSort = [],
5893			aiOrig = [],
5894			aoColumns = settings.aoColumns,
5895			aDataSort, iCol, sType, srcCol,
5896			fixed = settings.aaSortingFixed,
5897			fixedObj = $.isPlainObject( fixed ),
5898			nestedSort = [],
5899			add = function ( a ) {
5900				if ( a.length && ! 
vendor: 27,493 bytes, lines 5900-6884
5900$.isArray( a[0] ) ) {
5901					// 1D array
5902					nestedSort.push( a );
5903				}
5904				else {
5905					// 2D array
5906					$.merge( nestedSort, a );
5907				}
5908			};
5909	
5910		// Build the sort array, with pre-fix and post-fix options if they have been
5911		// specified
5912		if ( $.isArray( fixed ) ) {
5913			add( fixed );
5914		}
5915	
5916		if ( fixedObj && fixed.pre ) {
5917			add( fixed.pre );
5918		}
5919	
5920		add( settings.aaSorting );
5921	
5922		if (fixedObj && fixed.post ) {
5923			add( fixed.post );
5924		}
5925	
5926		for ( i=0 ; i<nestedSort.length ; i++ )
5927		{
5928			srcCol = nestedSort[i][0];
5929			aDataSort = aoColumns[ srcCol ].aDataSort;
5930	
5931			for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5932			{
5933				iCol = aDataSort[k];
5934				sType = aoColumns[ iCol ].sType || 'string';
5935	
5936				if ( nestedSort[i]._idx === undefined ) {
5937					nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5938				}
5939	
5940				aSort.push( {
5941					src:       srcCol,
5942					col:       iCol,
5943					dir:       nestedSort[i][1],
5944					index:     nestedSort[i]._idx,
5945					type:      sType,
5946					formatter: DataTable.ext.type.order[ sType+"-pre" ]
5947				} );
5948			}
5949		}
5950	
5951		return aSort;
5952	}
5953	
5954	/**
5955	 * Change the order of the table
5956	 *  @param {object} oSettings dataTables settings object
5957	 *  @memberof DataTable#oApi
5958	 *  @todo This really needs split up!
5959	 */
5960	function _fnSort ( oSettings )
5961	{
5962		var
5963			i, ien, iLen, j, jLen, k, kLen,
5964			sDataType, nTh,
5965			aiOrig = [],
5966			oExtSort = DataTable.ext.type.order,
5967			aoData = oSettings.aoData,
5968			aoColumns = oSettings.aoColumns,
5969			aDataSort, data, iCol, sType, oSort,
5970			formatters = 0,
5971			sortCol,
5972			displayMaster = oSettings.aiDisplayMaster,
5973			aSort;
5974	
5975		// Resolve any column types that are unknown due to addition or invalidation
5976		// @todo Can this be moved into a 'data-ready' handler which is called when
5977		//   data is going to be used in the table?
5978		_fnColumnTypes( oSettings );
5979	
5980		aSort = _fnSortFlatten( oSettings );
5981	
5982		for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5983			sortCol = aSort[i];
5984	
5985			// Track if we can use the fast sort algorithm
5986			if ( sortCol.formatter ) {
5987				formatters++;
5988			}
5989	
5990			// Load the data needed for the sort, for each cell
5991			_fnSortData( oSettings, sortCol.col );
5992		}
5993	
5994		/* No sorting required if server-side or no sorting array */
5995		if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5996		{
5997			// Create a value - key array of the current row positions such that we can use their
5998			// current position during the sort, if values match, in order to perform stable sorting
5999			for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
6000				aiOrig[ displayMaster[i] ] = i;
6001			}
6002	
6003			/* Do the sort - here we want multi-column sorting based on a given data source (column)
6004			 * and sorting function (from oSort) in a certain direction. It's reasonably complex to
6005			 * follow on it's own, but this is what we want (example two column sorting):
6006			 *  fnLocalSorting = function(a,b){
6007			 *    var iTest;
6008			 *    iTest = oSort['string-asc']('data11', 'data12');
6009			 *      if (iTest !== 0)
6010			 *        return iTest;
6011			 *    iTest = oSort['numeric-desc']('data21', 'data22');
6012			 *    if (iTest !== 0)
6013			 *      return iTest;
6014			 *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
6015			 *  }
6016			 * Basically we have a test for each sorting column, if the data in that column is equal,
6017			 * test the next column. If all columns match, then we use a numeric sort on the row
6018			 * positions in the original data array to provide a stable sort.
6019			 *
6020			 * Note - I know it seems excessive to have two sorting methods, but the first is around
6021			 * 15% faster, so the second is only maintained for backwards compatibility with sorting
6022			 * methods which do not have a pre-sort formatting function.
6023			 */
6024			if ( formatters === aSort.length ) {
6025				// All sort types have formatting functions
6026				displayMaster.sort( function ( a, b ) {
6027					var
6028						x, y, k, test, sort,
6029						len=aSort.length,
6030						dataA = aoData[a]._aSortData,
6031						dataB = aoData[b]._aSortData;
6032	
6033					for ( k=0 ; k<len ; k++ ) {
6034						sort = aSort[k];
6035	
6036						x = dataA[ sort.col ];
6037						y = dataB[ sort.col ];
6038	
6039						test = x<y ? -1 : x>y ? 1 : 0;
6040						if ( test !== 0 ) {
6041							return sort.dir === 'asc' ? test : -test;
6042						}
6043					}
6044	
6045					x = aiOrig[a];
6046					y = aiOrig[b];
6047					return x<y ? -1 : x>y ? 1 : 0;
6048				} );
6049			}
6050			else {
6051				// Depreciated - remove in 1.11 (providing a plug-in option)
6052				// Not all sort types have formatting methods, so we have to call their sorting
6053				// methods.
6054				displayMaster.sort( function ( a, b ) {
6055					var
6056						x, y, k, l, test, sort, fn,
6057						len=aSort.length,
6058						dataA = aoData[a]._aSortData,
6059						dataB = aoData[b]._aSortData;
6060	
6061					for ( k=0 ; k<len ; k++ ) {
6062						sort = aSort[k];
6063	
6064						x = dataA[ sort.col ];
6065						y = dataB[ sort.col ];
6066	
6067						fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6068						test = fn( x, y );
6069						if ( test !== 0 ) {
6070							return test;
6071						}
6072					}
6073	
6074					x = aiOrig[a];
6075					y = aiOrig[b];
6076					return x<y ? -1 : x>y ? 1 : 0;
6077				} );
6078			}
6079		}
6080	
6081		/* Tell the draw function that we have sorted the data */
6082		oSettings.bSorted = true;
6083	}
6084	
6085	
6086	function _fnSortAria ( settings )
6087	{
6088		var label;
6089		var nextSort;
6090		var columns = settings.aoColumns;
6091		var aSort = _fnSortFlatten( settings );
6092		var oAria = settings.oLanguage.oAria;
6093	
6094		// ARIA attributes - need to loop all columns, to update all (removing old
6095		// attributes as needed)
6096		for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6097		{
6098			var col = columns[i];
6099			var asSorting = col.asSorting;
6100			var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6101			var th = col.nTh;
6102	
6103			// IE7 is throwing an error when setting these properties with jQuery's
6104			// attr() and removeAttr() methods...
6105			th.removeAttribute('aria-sort');
6106	
6107			/* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6108			if ( col.bSortable ) {
6109				if ( aSort.length > 0 && aSort[0].col == i ) {
6110					th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6111					nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6112				}
6113				else {
6114					nextSort = asSorting[0];
6115				}
6116	
6117				label = sTitle + ( nextSort === "asc" ?
6118					oAria.sSortAscending :
6119					oAria.sSortDescending
6120				);
6121			}
6122			else {
6123				label = sTitle;
6124			}
6125	
6126			th.setAttribute('aria-label', label);
6127		}
6128	}
6129	
6130	
6131	/**
6132	 * Function to run on user sort request
6133	 *  @param {object} settings dataTables settings object
6134	 *  @param {node} attachTo node to attach the handler to
6135	 *  @param {int} colIdx column sorting index
6136	 *  @param {boolean} [append=false] Append the requested sort to the existing
6137	 *    sort if true (i.e. multi-column sort)
6138	 *  @param {function} [callback] callback function
6139	 *  @memberof DataTable#oApi
6140	 */
6141	function _fnSortListener ( settings, colIdx, append, callback )
6142	{
6143		var col = settings.aoColumns[ colIdx ];
6144		var sorting = settings.aaSorting;
6145		var asSorting = col.asSorting;
6146		var nextSortIdx;
6147		var next = function ( a, overflow ) {
6148			var idx = a._idx;
6149			if ( idx === undefined ) {
6150				idx = $.inArray( a[1], asSorting );
6151			}
6152	
6153			return idx+1 < asSorting.length ?
6154				idx+1 :
6155				overflow ?
6156					null :
6157					0;
6158		};
6159	
6160		// Convert to 2D array if needed
6161		if ( typeof sorting[0] === 'number' ) {
6162			sorting = settings.aaSorting = [ sorting ];
6163		}
6164	
6165		// If appending the sort then we are multi-column sorting
6166		if ( append && settings.oFeatures.bSortMulti ) {
6167			// Are we already doing some kind of sort on this column?
6168			var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6169	
6170			if ( sortIdx !== -1 ) {
6171				// Yes, modify the sort
6172				nextSortIdx = next( sorting[sortIdx], true );
6173	
6174				if ( nextSortIdx === null && sorting.length === 1 ) {
6175					nextSortIdx = 0; // can't remove sorting completely
6176				}
6177	
6178				if ( nextSortIdx === null ) {
6179					sorting.splice( sortIdx, 1 );
6180				}
6181				else {
6182					sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6183					sorting[sortIdx]._idx = nextSortIdx;
6184				}
6185			}
6186			else {
6187				// No sort on this column yet
6188				sorting.push( [ colIdx, asSorting[0], 0 ] );
6189				sorting[sorting.length-1]._idx = 0;
6190			}
6191		}
6192		else if ( sorting.length && sorting[0][0] == colIdx ) {
6193			// Single column - already sorting on this column, modify the sort
6194			nextSortIdx = next( sorting[0] );
6195	
6196			sorting.length = 1;
6197			sorting[0][1] = asSorting[ nextSortIdx ];
6198			sorting[0]._idx = nextSortIdx;
6199		}
6200		else {
6201			// Single column - sort only on this column
6202			sorting.length = 0;
6203			sorting.push( [ colIdx, asSorting[0] ] );
6204			sorting[0]._idx = 0;
6205		}
6206	
6207		// Run the sort by calling a full redraw
6208		_fnReDraw( settings );
6209	
6210		// callback used for async user interaction
6211		if ( typeof callback == 'function' ) {
6212			callback( settings );
6213		}
6214	}
6215	
6216	
6217	/**
6218	 * Attach a sort handler (click) to a node
6219	 *  @param {object} settings dataTables settings object
6220	 *  @param {node} attachTo node to attach the handler to
6221	 *  @param {int} colIdx column sorting index
6222	 *  @param {function} [callback] callback function
6223	 *  @memberof DataTable#oApi
6224	 */
6225	function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6226	{
6227		var col = settings.aoColumns[ colIdx ];
6228	
6229		_fnBindAction( attachTo, {}, function (e) {
6230			/* If the column is not sortable - don't to anything */
6231			if ( col.bSortable === false ) {
6232				return;
6233			}
6234	
6235			// If processing is enabled use a timeout to allow the processing
6236			// display to be shown - otherwise to it synchronously
6237			if ( settings.oFeatures.bProcessing ) {
6238				_fnProcessingDisplay( settings, true );
6239	
6240				setTimeout( function() {
6241					_fnSortListener( settings, colIdx, e.shiftKey, callback );
6242	
6243					// In server-side processing, the draw callback will remove the
6244					// processing display
6245					if ( _fnDataSource( settings ) !== 'ssp' ) {
6246						_fnProcessingDisplay( settings, false );
6247					}
6248				}, 0 );
6249			}
6250			else {
6251				_fnSortListener( settings, colIdx, e.shiftKey, callback );
6252			}
6253		} );
6254	}
6255	
6256	
6257	/**
6258	 * Set the sorting classes on table's body, Note: it is safe to call this function
6259	 * when bSort and bSortClasses are false
6260	 *  @param {object} oSettings dataTables settings object
6261	 *  @memberof DataTable#oApi
6262	 */
6263	function _fnSortingClasses( settings )
6264	{
6265		var oldSort = settings.aLastSort;
6266		var sortClass = settings.oClasses.sSortColumn;
6267		var sort = _fnSortFlatten( settings );
6268		var features = settings.oFeatures;
6269		var i, ien, colIdx;
6270	
6271		if ( features.bSort && features.bSortClasses ) {
6272			// Remove old sorting classes
6273			for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6274				colIdx = oldSort[i].src;
6275	
6276				// Remove column sorting
6277				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6278					.removeClass( sortClass + (i<2 ? i+1 : 3) );
6279			}
6280	
6281			// Add new column sorting
6282			for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6283				colIdx = sort[i].src;
6284	
6285				$( _pluck( settings.aoData, 'anCells', colIdx ) )
6286					.addClass( sortClass + (i<2 ? i+1 : 3) );
6287			}
6288		}
6289	
6290		settings.aLastSort = sort;
6291	}
6292	
6293	
6294	// Get the data to sort a column, be it from cache, fresh (populating the
6295	// cache), or from a sort formatter
6296	function _fnSortData( settings, idx )
6297	{
6298		// Custom sorting function - provided by the sort data type
6299		var column = settings.aoColumns[ idx ];
6300		var customSort = DataTable.ext.order[ column.sSortDataType ];
6301		var customData;
6302	
6303		if ( customSort ) {
6304			customData = customSort.call( settings.oInstance, settings, idx,
6305				_fnColumnIndexToVisible( settings, idx )
6306			);
6307		}
6308	
6309		// Use / populate cache
6310		var row, cellData;
6311		var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6312	
6313		for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6314			row = settings.aoData[i];
6315	
6316			if ( ! row._aSortData ) {
6317				row._aSortData = [];
6318			}
6319	
6320			if ( ! row._aSortData[idx] || customSort ) {
6321				cellData = customSort ?
6322					customData[i] : // If there was a custom sort function, use data from there
6323					_fnGetCellData( settings, i, idx, 'sort' );
6324	
6325				row._aSortData[ idx ] = formatter ?
6326					formatter( cellData ) :
6327					cellData;
6328			}
6329		}
6330	}
6331	
6332	
6333	
6334	/**
6335	 * Save the state of a table
6336	 *  @param {object} oSettings dataTables settings object
6337	 *  @memberof DataTable#oApi
6338	 */
6339	function _fnSaveState ( settings )
6340	{
6341		if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6342		{
6343			return;
6344		}
6345	
6346		/* Store the interesting variables */
6347		var state = {
6348			time:    +new Date(),
6349			start:   settings._iDisplayStart,
6350			length:  settings._iDisplayLength,
6351			order:   $.extend( true, [], settings.aaSorting ),
6352			search:  _fnSearchToCamel( settings.oPreviousSearch ),
6353			columns: $.map( settings.aoColumns, function ( col, i ) {
6354				return {
6355					visible: col.bVisible,
6356					search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6357				};
6358			} )
6359		};
6360	
6361		_fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6362	
6363		settings.oSavedState = state;
6364		settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6365	}
6366	
6367	
6368	/**
6369	 * Attempt to load a saved table state
6370	 *  @param {object} oSettings dataTables settings object
6371	 *  @param {object} oInit DataTables init object so we can override settings
6372	 *  @param {function} callback Callback to execute when the state has been loaded
6373	 *  @memberof DataTable#oApi
6374	 */
6375	function _fnLoadState ( settings, oInit, callback )
6376	{
6377		var i, ien;
6378		var columns = settings.aoColumns;
6379		var loaded = function ( s ) {
6380			if ( ! s || ! s.time ) {
6381				callback();
6382				return;
6383			}
6384	
6385			// Allow custom and plug-in manipulation functions to alter the saved data set and
6386			// cancelling of loading by returning false
6387			var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6388			if ( $.inArray( false, abStateLoad ) !== -1 ) {
6389				callback();
6390				return;
6391			}
6392	
6393			// Reject old data
6394			var duration = settings.iStateDuration;
6395			if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6396				callback();
6397				return;
6398			}
6399	
6400			// Number of columns have changed - all bets are off, no restore of settings
6401			if ( s.columns && columns.length !== s.columns.length ) {
6402				callback();
6403				return;
6404			}
6405	
6406			// Store the saved state so it might be accessed at any time
6407			settings.oLoadedState = $.extend( true, {}, s );
6408	
6409			// Restore key features - todo - for 1.11 this needs to be done by
6410			// subscribed events
6411			if ( s.start !== undefined ) {
6412				settings._iDisplayStart    = s.start;
6413				settings.iInitDisplayStart = s.start;
6414			}
6415			if ( s.length !== undefined ) {
6416				settings._iDisplayLength   = s.length;
6417			}
6418	
6419			// Order
6420			if ( s.order !== undefined ) {
6421				settings.aaSorting = [];
6422				$.each( s.order, function ( i, col ) {
6423					settings.aaSorting.push( col[0] >= columns.length ?
6424						[ 0, col[1] ] :
6425						col
6426					);
6427				} );
6428			}
6429	
6430			// Search
6431			if ( s.search !== undefined ) {
6432				$.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6433			}
6434	
6435			// Columns
6436			//
6437			if ( s.columns ) {
6438				for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6439					var col = s.columns[i];
6440	
6441					// Visibility
6442					if ( col.visible !== undefined ) {
6443						columns[i].bVisible = col.visible;
6444					}
6445	
6446					// Search
6447					if ( col.search !== undefined ) {
6448						$.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6449					}
6450				}
6451			}
6452	
6453			_fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6454			callback();
6455		}
6456	
6457		if ( ! settings.oFeatures.bStateSave ) {
6458			callback();
6459			return;
6460		}
6461	
6462		var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6463	
6464		if ( state !== undefined ) {
6465			loaded( state );
6466		}
6467		// otherwise, wait for the loaded callback to be executed
6468	}
6469	
6470	
6471	/**
6472	 * Return the settings object for a particular table
6473	 *  @param {node} table table we are using as a dataTable
6474	 *  @returns {object} Settings object - or null if not found
6475	 *  @memberof DataTable#oApi
6476	 */
6477	function _fnSettingsFromNode ( table )
6478	{
6479		var settings = DataTable.settings;
6480		var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6481	
6482		return idx !== -1 ?
6483			settings[ idx ] :
6484			null;
6485	}
6486	
6487	
6488	/**
6489	 * Log an error message
6490	 *  @param {object} settings dataTables settings object
6491	 *  @param {int} level log error messages, or display them to the user
6492	 *  @param {string} msg error message
6493	 *  @param {int} tn Technical note id to get more information about the error.
6494	 *  @memberof DataTable#oApi
6495	 */
6496	function _fnLog( settings, level, msg, tn )
6497	{
6498		msg = 'DataTables warning: '+
6499			(settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6500	
6501		if ( tn ) {
6502			msg += '. For more information about this error, please see '+
6503			'http://datatables.net/tn/'+tn;
6504		}
6505	
6506		if ( ! level  ) {
6507			// Backwards compatibility pre 1.10
6508			var ext = DataTable.ext;
6509			var type = ext.sErrMode || ext.errMode;
6510	
6511			if ( settings ) {
6512				_fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6513			}
6514	
6515			if ( type == 'alert' ) {
6516				alert( msg );
6517			}
6518			else if ( type == 'throw' ) {
6519				throw new Error(msg);
6520			}
6521			else if ( typeof type == 'function' ) {
6522				type( settings, tn, msg );
6523			}
6524		}
6525		else if ( window.console && console.log ) {
6526			console.log( msg );
6527		}
6528	}
6529	
6530	
6531	/**
6532	 * See if a property is defined on one object, if so assign it to the other object
6533	 *  @param {object} ret target object
6534	 *  @param {object} src source object
6535	 *  @param {string} name property
6536	 *  @param {string} [mappedName] name to map too - optional, name used if not given
6537	 *  @memberof DataTable#oApi
6538	 */
6539	function _fnMap( ret, src, name, mappedName )
6540	{
6541		if ( $.isArray( name ) ) {
6542			$.each( name, function (i, val) {
6543				if ( $.isArray( val ) ) {
6544					_fnMap( ret, src, val[0], val[1] );
6545				}
6546				else {
6547					_fnMap( ret, src, val );
6548				}
6549			} );
6550	
6551			return;
6552		}
6553	
6554		if ( mappedName === undefined ) {
6555			mappedName = name;
6556		}
6557	
6558		if ( src[name] !== undefined ) {
6559			ret[mappedName] = src[name];
6560		}
6561	}
6562	
6563	
6564	/**
6565	 * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6566	 * shallow copy arrays. The reason we need to do this, is that we don't want to
6567	 * deep copy array init values (such as aaSorting) since the dev wouldn't be
6568	 * able to override them, but we do want to deep copy arrays.
6569	 *  @param {object} out Object to extend
6570	 *  @param {object} extender Object from which the properties will be applied to
6571	 *      out
6572	 *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6573	 *      independent copy with the exception of the `data` or `aaData` parameters
6574	 *      if they are present. This is so you can pass in a collection to
6575	 *      DataTables and have that used as your data source without breaking the
6576	 *      references
6577	 *  @returns {object} out Reference, just for convenience - out === the return.
6578	 *  @memberof DataTable#oApi
6579	 *  @todo This doesn't take account of arrays inside the deep copied objects.
6580	 */
6581	function _fnExtend( out, extender, breakRefs )
6582	{
6583		var val;
6584	
6585		for ( var prop in extender ) {
6586			if ( extender.hasOwnProperty(prop) ) {
6587				val = extender[prop];
6588	
6589				if ( $.isPlainObject( val ) ) {
6590					if ( ! $.isPlainObject( out[prop] ) ) {
6591						out[prop] = {};
6592					}
6593					$.extend( true, out[prop], val );
6594				}
6595				else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6596					out[prop] = val.slice();
6597				}
6598				else {
6599					out[prop] = val;
6600				}
6601			}
6602		}
6603	
6604		return out;
6605	}
6606	
6607	
6608	/**
6609	 * Bind an event handers to allow a click or return key to activate the callback.
6610	 * This is good for accessibility since a return on the keyboard will have the
6611	 * same effect as a click, if the element has focus.
6612	 *  @param {element} n Element to bind the action to
6613	 *  @param {object} oData Data object to pass to the triggered function
6614	 *  @param {function} fn Callback function for when the event is triggered
6615	 *  @memberof DataTable#oApi
6616	 */
6617	function _fnBindAction( n, oData, fn )
6618	{
6619		$(n)
6620			.on( 'click.DT', oData, function (e) {
6621					n.blur(); // Remove focus outline for mouse users
6622					fn(e);
6623				} )
6624			.on( 'keypress.DT', oData, function (e){
6625					if ( e.which === 13 ) {
6626						e.preventDefault();
6627						fn(e);
6628					}
6629				} )
6630			.on( 'selectstart.DT', function () {
6631					/* Take the brutal approach to cancelling text selection */
6632					return false;
6633				} );
6634	}
6635	
6636	
6637	/**
6638	 * Register a callback function. Easily allows a callback function to be added to
6639	 * an array store of callback functions that can then all be called together.
6640	 *  @param {object} oSettings dataTables settings object
6641	 *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6642	 *  @param {function} fn Function to be called back
6643	 *  @param {string} sName Identifying name for the callback (i.e. a label)
6644	 *  @memberof DataTable#oApi
6645	 */
6646	function _fnCallbackReg( oSettings, sStore, fn, sName )
6647	{
6648		if ( fn )
6649		{
6650			oSettings[sStore].push( {
6651				"fn": fn,
6652				"sName": sName
6653			} );
6654		}
6655	}
6656	
6657	
6658	/**
6659	 * Fire callback functions and trigger events. Note that the loop over the
6660	 * callback array store is done backwards! Further note that you do not want to
6661	 * fire off triggers in time sensitive applications (for example cell creation)
6662	 * as its slow.
6663	 *  @param {object} settings dataTables settings object
6664	 *  @param {string} callbackArr Name of the array storage for the callbacks in
6665	 *      oSettings
6666	 *  @param {string} eventName Name of the jQuery custom event to trigger. If
6667	 *      null no trigger is fired
6668	 *  @param {array} args Array of arguments to pass to the callback function /
6669	 *      trigger
6670	 *  @memberof DataTable#oApi
6671	 */
6672	function _fnCallbackFire( settings, callbackArr, eventName, args )
6673	{
6674		var ret = [];
6675	
6676		if ( callbackArr ) {
6677			ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6678				return val.fn.apply( settings.oInstance, args );
6679			} );
6680		}
6681	
6682		if ( eventName !== null ) {
6683			var e = $.Event( eventName+'.dt' );
6684	
6685			$(settings.nTable).trigger( e, args );
6686	
6687			ret.push( e.result );
6688		}
6689	
6690		return ret;
6691	}
6692	
6693	
6694	function _fnLengthOverflow ( settings )
6695	{
6696		var
6697			start = settings._iDisplayStart,
6698			end = settings.fnDisplayEnd(),
6699			len = settings._iDisplayLength;
6700	
6701		/* If we have space to show extra rows (backing up from the end point - then do so */
6702		if ( start >= end )
6703		{
6704			start = end - len;
6705		}
6706	
6707		// Keep the start record on the current page
6708		start -= (start % len);
6709	
6710		if ( len === -1 || start < 0 )
6711		{
6712			start = 0;
6713		}
6714	
6715		settings._iDisplayStart = start;
6716	}
6717	
6718	
6719	function _fnRenderer( settings, type )
6720	{
6721		var renderer = settings.renderer;
6722		var host = DataTable.ext.renderer[type];
6723	
6724		if ( $.isPlainObject( renderer ) && renderer[type] ) {
6725			// Specific renderer for this type. If available use it, otherwise use
6726			// the default.
6727			return host[renderer[type]] || host._;
6728		}
6729		else if ( typeof renderer === 'string' ) {
6730			// Common renderer - if there is one available for this type use it,
6731			// otherwise use the default
6732			return host[renderer] || host._;
6733		}
6734	
6735		// Use the default
6736		return host._;
6737	}
6738	
6739	
6740	/**
6741	 * Detect the data source being used for the table. Used to simplify the code
6742	 * a little (ajax) and to make it compress a little smaller.
6743	 *
6744	 *  @param {object} settings dataTables settings object
6745	 *  @returns {string} Data source
6746	 *  @memberof DataTable#oApi
6747	 */
6748	function _fnDataSource ( settings )
6749	{
6750		if ( settings.oFeatures.bServerSide ) {
6751			return 'ssp';
6752		}
6753		else if ( settings.ajax || settings.sAjaxSource ) {
6754			return 'ajax';
6755		}
6756		return 'dom';
6757	}
6758	
6759
6760	
6761	
6762	/**
6763	 * Computed structure of the DataTables API, defined by the options passed to
6764	 * `DataTable.Api.register()` when building the API.
6765	 *
6766	 * The structure is built in order to speed creation and extension of the Api
6767	 * objects since the extensions are effectively pre-parsed.
6768	 *
6769	 * The array is an array of objects with the following structure, where this
6770	 * base array represents the Api prototype base:
6771	 *
6772	 *     [
6773	 *       {
6774	 *         name:      'data'                -- string   - Property name
6775	 *         val:       function () {},       -- function - Api method (or undefined if just an object
6776	 *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6777	 *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6778	 *       },
6779	 *       {
6780	 *         name:     'row'
6781	 *         val:       {},
6782	 *         methodExt: [ ... ],
6783	 *         propExt:   [
6784	 *           {
6785	 *             name:      'data'
6786	 *             val:       function () {},
6787	 *             methodExt: [ ... ],
6788	 *             propExt:   [ ... ]
6789	 *           },
6790	 *           ...
6791	 *         ]
6792	 *       }
6793	 *     ]
6794	 *
6795	 * @type {Array}
6796	 * @ignore
6797	 */
6798	var __apiStruct = [];
6799	
6800	
6801	/**
6802	 * `Array.prototype` reference.
6803	 *
6804	 * @type object
6805	 * @ignore
6806	 */
6807	var __arrayProto = Array.prototype;
6808	
6809	
6810	/**
6811	 * Abstraction for `context` parameter of the `Api` constructor to allow it to
6812	 * take several different forms for ease of use.
6813	 *
6814	 * Each of the input parameter types will be converted to a DataTables settings
6815	 * object where possible.
6816	 *
6817	 * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6818	 *   of:
6819	 *
6820	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6821	 *     with be found and used.
6822	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6823	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6824	 *   * `object` - DataTables settings object
6825	 *   * `DataTables.Api` - API instance
6826	 * @return {array|null} Matching DataTables settings objects. `null` or
6827	 *   `undefined` is returned if no matching DataTable is found.
6828	 * @ignore
6829	 */
6830	var _toSettings = function ( mixed )
6831	{
6832		var idx, jq;
6833		var settings = DataTable.settings;
6834		var tables = $.map( settings, function (el, i) {
6835			return el.nTable;
6836		} );
6837	
6838		if ( ! mixed ) {
6839			return [];
6840		}
6841		else if ( mixed.nTable && mixed.oApi ) {
6842			// DataTables settings object
6843			return [ mixed ];
6844		}
6845		else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6846			// Table node
6847			idx = $.inArray( mixed, tables );
6848			return idx !== -1 ? [ settings[idx] ] : null;
6849		}
6850		else if ( mixed && typeof mixed.settings === 'function' ) {
6851			return mixed.settings().toArray();
6852		}
6853		else if ( typeof mixed === 'string' ) {
6854			// jQuery selector
6855			jq = $(mixed);
6856		}
6857		else if ( mixed instanceof $ ) {
6858			// jQuery object (also DataTables instance)
6859			jq = mixed;
6860		}
6861	
6862		if ( jq ) {
6863			return jq.map( function(i) {
6864				idx = $.inArray( this, tables );
6865				return idx !== -1 ? settings[idx] : null;
6866			} ).toArray();
6867		}
6868	};
6869	
6870	
6871	/**
6872	 * DataTables API class - used to control and interface with  one or more
6873	 * DataTables enhanced tables.
6874	 *
6875	 * The API class is heavily based on jQuery, presenting a chainable interface
6876	 * that you can use to interact with tables. Each instance of the API class has
6877	 * a "context" - i.e. the tables that it will operate on. This could be a single
6878	 * table, all tables on a page or a sub-set thereof.
6879	 *
6880	 * Additionally the API is designed to allow you to easily work with the data in
6881	 * the tables, retrieving and manipulating it as required. This is done by
6882	 * presenting the API class as an array like interface. The contents of the
6883	 * array depend upon the actions requested by each method (for example
6884	 * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6885	 * return an array of objects or arrays depending upon your table's
6886	 * configuration). The API object has a number of array like methods (`push`,
6887	 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6888	 * `unique` etc) to assist your working with the data held in a table.
6889	 *
6890	 * Most methods (those which return an Api instance) are chainable, which means
6891	 * the return from a method call also has all of the methods available that the
6892	 * top level object had. For example, these two calls are equivalent:
6893	 *
6894	 *     // Not chained
6895	 *     api.row.add( {...} );
6896	 *     api.draw();
6897	 *
6898	 *     // Chained
6899	 *     api.row.add( {...} ).draw();
6900	 *
6901	 * @class DataTable.Api
6902	 * @param {array|object|string|jQuery} context DataTable identifier. This is
6903	 *   used to define which DataTables enhanced tables this API will operate on.
6904	 *   Can be one of:
6905	 *
6906	 *   * `string` - jQuery selector. Any DataTables' matching the given selector
6907	 *     with be found and used.
6908	 *   * `node` - `TABLE` node which has already been formed into a DataTable.
6909	 *   * `jQuery` - A jQuery object of `TABLE` nodes.
6910	 *   * `object` - DataTables settings object
6911	 * @param {array} [data] Data to initialise the Api instance with.
6912	 *
6913	 * @example
6914	 *   // Direct initialisation during DataTables construction
6915	 *   var api = $('#example').DataTable();
6916	 *
6917	 * @example
6918	 *   // Initialisation using a DataTables jQuery object
6919	 *   var api = $('#example').dataTable().api();
6920	 *
6921	 * @example
6922	 *   // Initialisation as a constructor
6923	 *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6924	 */
6925	_Api = function ( context, data )
6926	{
6927		if ( ! (this instanceof _Api) ) {
6928			return new _Api( context, data );
6929		}
6930	
6931		var settings = [];
6932		var ctxSettings = function ( o ) {
6933			var a = _toSettings( o );
6934			if ( a ) {
6935				settings = settings.concat( a );
6936			}
6937		};
6938	
6939		if ( $.isArray( context ) ) {
6940			for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6941				ctxSettings( context[i] );
6942			}
6943		}
6944		else {
6945			ctxSettings( context );
6946		}
6947	
6948		// Remove duplicates
6949		this.context = _unique( settings );
6950	
6951		// Initial data
6952		if ( data ) {
6953			$.merge( this, data );
6954		}
6955	
6956		// selector
6957		this.selector = {
6958			rows: null,
6959			cols: null,
6960			opts: null
6961		};
6962	
6963		_Api.extend( this, this, __apiStruct );
6964	};
6965	
6966	DataTable.Api = _Api;
6967	
6968	// Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6969	// isPlainObject.
6970	$.extend( _Api.prototype, {
6971		any: function ()
6972		{
6973			return this.count() !== 0;
6974		},
6975	
6976	
6977		concat:  __arrayProto.concat,
6978	
6979	
6980		context: [], // array of table settings objects
6981	
6982	
6983		count: function ()
6984		{
6985			return this.flatten().length;
6986		},
6987	
6988	
6989		each: function ( fn )
6990		{
6991			for ( var i=0, ien=this.length ; i<ien; i++ ) {
6992				fn.call( this, this[i], i, this );
6993			}
6994	
6995			return this;
6996		},
6997	
6998	
6999		eq: function ( idx )
7000		{
7001			var ctx = this.context;
7002	
7003			return ctx.length > idx ?
7004				new _Api( ctx[idx], this[idx] ) :
7005				null;
7006		},
7007	
7008	
7009		filter: function ( fn )
7010		{
7011			var a = [];
7012	
7013			if ( __arrayProto.filter ) {
7014				a = __arrayProto.filter.call( this, fn, this );
7015			}
7016			else {
7017				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7018				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7019					if ( fn.call( this, this[i], i, this ) ) {
7020						a.push( this[i] );
7021					}
7022				}
7023			}
7024	
7025			return new _Api( this.context, a );
7026		},
7027	
7028	
7029		flatten: function ()
7030		{
7031			var a = [];
7032			return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
7033		},
7034	
7035	
7036		join:    __arrayProto.join,
7037	
7038	
7039		indexOf: __arrayProto.indexOf || function (obj, start)
7040		{
7041			for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7042				if ( this[i] === obj ) {
7043					return i;
7044				}
7045			}
7046			return -1;
7047		},
7048	
7049		iterator: function ( flatten, type, fn, alwaysNew ) {
7050			var
7051				a = [], ret,
7052				i, ien, j, jen,
7053				context = this.context,
7054				rows, items, item,
7055				selector = this.selector;
7056	
7057			// Argument shifting
7058			if ( typeof flatten === 'string' ) {
7059				alwaysNew = fn;
7060				fn = type;
7061				type = flatten;
7062				flatten = false;
7063			}
7064	
7065			for ( i=0, ien=context.length ; i<ien ; i++ ) {
7066				var apiInst = new _Api( context[i] );
7067	
7068				if ( type === 'table' ) {
7069					ret = fn.call( apiInst, context[i], i );
7070	
7071					if ( ret !== undefined ) {
7072						a.push( ret );
7073					}
7074				}
7075				else if ( type === 'columns' || type === 'rows' ) {
7076					// this has same length as context - one entry for each table
7077					ret = fn.call( apiInst, context[i], this[i], i );
7078	
7079					if ( ret !== undefined ) {
7080						a.push( ret );
7081					}
7082				}
7083				else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7084					// columns and rows share the same structure.
7085					// 'this' is an array of column indexes for each context
7086					items = this[i];
7087	
7088					if ( type === 'column-rows' ) {
7089						rows = _selector_row_indexes( context[i], selector.opts );
7090					}
7091	
7092					for ( j=0, jen=items.length ; j<jen ; j++ ) {
7093						item = items[j];
7094	
7095						if ( type === 'cell' ) {
7096							ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7097						}
7098						else {
7099							ret = fn.call( apiInst, context[i], item, i, j, rows );
7100						}
7101	
7102						if ( ret !== undefined ) {
7103							a.push( ret );
7104						}
7105					}
7106				}
7107			}
7108	
7109			if ( a.length || alwaysNew ) {
7110				var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7111				var apiSelector = api.selector;
7112				apiSelector.rows = selector.rows;
7113				apiSelector.cols = selector.cols;
7114				apiSelector.opts = selector.opts;
7115				return api;
7116			}
7117			return this;
7118		},
7119	
7120	
7121		lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7122		{
7123			// Bit cheeky...
7124			return this.indexOf.apply( this.toArray.reverse(), arguments );
7125		},
7126	
7127	
7128		length:  0,
7129	
7130	
7131		map: function ( fn )
7132		{
7133			var a = [];
7134	
7135			if ( __arrayProto.map ) {
7136				a = __arrayProto.map.call( this, fn, this );
7137			}
7138			else {
7139				// Compatibility for browsers without EMCA-252-5 (JS 1.6)
7140				for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7141					a.push( fn.call( this, this[i], i ) );
7142				}
7143			}
7144	
7145			return new _Api( this.context, a );
7146		},
7147	
7148	
7149		pluck: function ( prop )
7150		{
7151			return this.map( function ( el ) {
7152				return el[ prop ];
7153			} );
7154		},
7155	
7156		pop:     __arrayProto.pop,
7157	
7158	
7159		push:    __arrayProto.push,
7160	
7161	
7162		// Does not return an API instance
7163		reduce: __arrayProto.reduce || function ( fn, init )
7164		{
7165			return _fnReduce( this, fn, init, 0, this.length, 1 );
7166		},
7167	
7168	
7169		reduceRight: __arrayProto.reduceRight || function ( fn, init )
7170		{
7171			return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7172		},
7173	
7174	
7175		reverse: __arrayProto.reverse,
7176	
7177	
7178		// Object with rows, columns and opts
7179		selector: null,
7180	
7181	
7182		shift:   __arrayProto.shift,
7183	
7184	
7185		slice: function () {
7186			return new _Api( this.context, this );
7187		},
7188	
7189	
7190		sort:    __arrayProto.sort, // ? name - order?
7191	
7192	
7193		splice:  __arrayProto.splice,
7194	
7195	
7196		toArray: function ()
7197		{
7198			return __arrayProto.slice.call( this );
7199		},
7200	
7201	
7202		to$: function ()
7203		{
7204			return $( this );
7205		},
7206	
7207	
7208		toJQuery: function ()
7209		{
7210			return $( this );
7211		},
7212	
7213	
7214		unique: function ()
7215		{
7216			return new _Api( this.context, _unique(this) );
7217		},
7218	
7219	
7220		unshift: __arrayProto.unshift
7221	} );
7222	
7223	
7224	_Api.extend = function ( scope, obj, ext )
7225	{
7226		// Only extend API instances and static properties of the API
7227		if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7228			return;
7229		}
7230	
7231		var
7232			i, ien,
7233			j, jen,
7234			struct, inner,
7235			methodScoping = function ( scope, fn, struc ) {
7236				return function () {
7237					var ret = fn.apply( scope, arguments );
7238	
7239					// Method extension
7240					_Api.extend( ret, ret, struc.methodExt );
7241					return ret;
7242				};
7243			};
7244	
7245		for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7246			struct = ext[i];
7247	
7248			// Value
7249			obj[ struct.name ] = typeof struct.val === 'function' ?
7250				methodScoping( scope, struct.val, struct ) :
7251				$.isPlainObject( struct.val ) ?
7252					{} :
7253					struct.val;
7254	
7255			obj[ struct.name ].__dt_wrapper = true;
7256	
7257			// Property extension
7258			_Api.extend( scope, obj[ struct.name ], struct.propExt );
7259		}
7260	};
7261	
7262	
7263	// @todo - Is there need for an augment function?
7264	// _Api.augment = function ( inst, name )
7265	// {
7266	// 	// Find src object in the structure from the name
7267	// 	var parts = name.split('.');
7268	
7269	// 	_Api.extend( inst, obj );
7270	// };
7271	
7272	
7273	//     [
7274	//       {
7275	//         name:      'data'                -- string   - Property name
7276	//         val:       function () {},       -- function - Api method (or undefined if just an object
7277	//         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7278	//         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7279	//       },
7280	//       {
7281	//         name:     'row'
7282	//         val:       {},
7283	//         methodExt: [ ... ],
7284	//         propExt:   [
7285	//           {
7286	//             name:      'data'
7287	//             val:       function () {},
7288	//             methodExt: [ ... ],
7289	//             propExt:   [ ... ]
7290	//           },
7291	//           ...
7292	//         ]
7293	//       }
7294	//     ]
7295	
7296	_Api.register = _api_register = function ( name, val )
7297	{
7298		if ( $.isArray( name ) ) {
7299			for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7300				_Api.register( name[j], val );
7301			}
7302			return;
7303		}
7304	
7305		var
7306			i, ien,
7307			heir = name.split('.'),
7308			struct = __apiStruct,
7309			key, method;
7310	
7311		var find = function ( src, name ) {
7312			for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7313				if ( src[i].name === name ) {
7314					return src[i];
7315				}
7316			}
7317			return null;
7318		};
7319	
7320		for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7321			method = heir[i].indexOf('()') !== -1;
7322			key = method ?
vendor: 2,581 bytes, lines 7323-7421
7323				heir[i].replace('()', '') :
7324				heir[i];
7325	
7326			var src = find( struct, key );
7327			if ( ! src ) {
7328				src = {
7329					name:      key,
7330					val:       {},
7331					methodExt: [],
7332					propExt:   []
7333				};
7334				struct.push( src );
7335			}
7336	
7337			if ( i === ien-1 ) {
7338				src.val = val;
7339			}
7340			else {
7341				struct = method ?
7342					src.methodExt :
7343					src.propExt;
7344			}
7345		}
7346	};
7347	
7348	
7349	_Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7350		_Api.register( pluralName, val );
7351	
7352		_Api.register( singularName, function () {
7353			var ret = val.apply( this, arguments );
7354	
7355			if ( ret === this ) {
7356				// Returned item is the API instance that was passed in, return it
7357				return this;
7358			}
7359			else if ( ret instanceof _Api ) {
7360				// New API instance returned, want the value from the first item
7361				// in the returned array for the singular result.
7362				return ret.length ?
7363					$.isArray( ret[0] ) ?
7364						new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7365						ret[0] :
7366					undefined;
7367			}
7368	
7369			// Non-API return - just fire it back
7370			return ret;
7371		} );
7372	};
7373	
7374	
7375	/**
7376	 * Selector for HTML tables. Apply the given selector to the give array of
7377	 * DataTables settings objects.
7378	 *
7379	 * @param {string|integer} [selector] jQuery selector string or integer
7380	 * @param  {array} Array of DataTables settings objects to be filtered
7381	 * @return {array}
7382	 * @ignore
7383	 */
7384	var __table_selector = function ( selector, a )
7385	{
7386		// Integer is used to pick out a table by index
7387		if ( typeof selector === 'number' ) {
7388			return [ a[ selector ] ];
7389		}
7390	
7391		// Perform a jQuery selector on the table nodes
7392		var nodes = $.map( a, function (el, i) {
7393			return el.nTable;
7394		} );
7395	
7396		return $(nodes)
7397			.filter( selector )
7398			.map( function (i) {
7399				// Need to translate back from the table node to the settings
7400				var idx = $.inArray( this, nodes );
7401				return a[ idx ];
7402			} )
7403			.toArray();
7404	};
7405	
7406	
7407	
7408	/**
7409	 * Context selector for the API's context (i.e. the tables the API instance
7410	 * refers to.
7411	 *
7412	 * @name    DataTable.Api#tables
7413	 * @param {string|integer} [selector] Selector to pick which tables the iterator
7414	 *   should operate on. If not given, all tables in the current context are
7415	 *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7416	 *   select multiple tables or as an integer to select a single table.
7417	 * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7418	 */
7419	_api_register( 'tables()', function ( selector ) {
7420		// A new instance is created if there was a selector specified
7421		return selector
vendor: 9,632 bytes, lines 7421-7769
7421 ?
7422			new _Api( __table_selector( selector, this.context ) ) :
7423			this;
7424	} );
7425	
7426	
7427	_api_register( 'table()', function ( selector ) {
7428		var tables = this.tables( selector );
7429		var ctx = tables.context;
7430	
7431		// Truncate to the first matched table
7432		return ctx.length ?
7433			new _Api( ctx[0] ) :
7434			tables;
7435	} );
7436	
7437	
7438	_api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7439		return this.iterator( 'table', function ( ctx ) {
7440			return ctx.nTable;
7441		}, 1 );
7442	} );
7443	
7444	
7445	_api_registerPlural( 'tables().body()', 'table().body()' , function () {
7446		return this.iterator( 'table', function ( ctx ) {
7447			return ctx.nTBody;
7448		}, 1 );
7449	} );
7450	
7451	
7452	_api_registerPlural( 'tables().header()', 'table().header()' , function () {
7453		return this.iterator( 'table', function ( ctx ) {
7454			return ctx.nTHead;
7455		}, 1 );
7456	} );
7457	
7458	
7459	_api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7460		return this.iterator( 'table', function ( ctx ) {
7461			return ctx.nTFoot;
7462		}, 1 );
7463	} );
7464	
7465	
7466	_api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7467		return this.iterator( 'table', function ( ctx ) {
7468			return ctx.nTableWrapper;
7469		}, 1 );
7470	} );
7471	
7472	
7473	
7474	/**
7475	 * Redraw the tables in the current context.
7476	 */
7477	_api_register( 'draw()', function ( paging ) {
7478		return this.iterator( 'table', function ( settings ) {
7479			if ( paging === 'page' ) {
7480				_fnDraw( settings );
7481			}
7482			else {
7483				if ( typeof paging === 'string' ) {
7484					paging = paging === 'full-hold' ?
7485						false :
7486						true;
7487				}
7488	
7489				_fnReDraw( settings, paging===false );
7490			}
7491		} );
7492	} );
7493	
7494	
7495	
7496	/**
7497	 * Get the current page index.
7498	 *
7499	 * @return {integer} Current page index (zero based)
7500	 *//**
7501	 * Set the current page.
7502	 *
7503	 * Note that if you attempt to show a page which does not exist, DataTables will
7504	 * not throw an error, but rather reset the paging.
7505	 *
7506	 * @param {integer|string} action The paging action to take. This can be one of:
7507	 *  * `integer` - The page index to jump to
7508	 *  * `string` - An action to take:
7509	 *    * `first` - Jump to first page.
7510	 *    * `next` - Jump to the next page
7511	 *    * `previous` - Jump to previous page
7512	 *    * `last` - Jump to the last page.
7513	 * @returns {DataTables.Api} this
7514	 */
7515	_api_register( 'page()', function ( action ) {
7516		if ( action === undefined ) {
7517			return this.page.info().page; // not an expensive call
7518		}
7519	
7520		// else, have an action to take on all tables
7521		return this.iterator( 'table', function ( settings ) {
7522			_fnPageChange( settings, action );
7523		} );
7524	} );
7525	
7526	
7527	/**
7528	 * Paging information for the first table in the current context.
7529	 *
7530	 * If you require paging information for another table, use the `table()` method
7531	 * with a suitable selector.
7532	 *
7533	 * @return {object} Object with the following properties set:
7534	 *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7535	 *  * `pages` - Total number of pages
7536	 *  * `start` - Display index for the first record shown on the current page
7537	 *  * `end` - Display index for the last record shown on the current page
7538	 *  * `length` - Display length (number of records). Note that generally `start
7539	 *    + length = end`, but this is not always true, for example if there are
7540	 *    only 2 records to show on the final page, with a length of 10.
7541	 *  * `recordsTotal` - Full data set length
7542	 *  * `recordsDisplay` - Data set length once the current filtering criterion
7543	 *    are applied.
7544	 */
7545	_api_register( 'page.info()', function ( action ) {
7546		if ( this.context.length === 0 ) {
7547			return undefined;
7548		}
7549	
7550		var
7551			settings   = this.context[0],
7552			start      = settings._iDisplayStart,
7553			len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7554			visRecords = settings.fnRecordsDisplay(),
7555			all        = len === -1;
7556	
7557		return {
7558			"page":           all ? 0 : Math.floor( start / len ),
7559			"pages":          all ? 1 : Math.ceil( visRecords / len ),
7560			"start":          start,
7561			"end":            settings.fnDisplayEnd(),
7562			"length":         len,
7563			"recordsTotal":   settings.fnRecordsTotal(),
7564			"recordsDisplay": visRecords,
7565			"serverSide":     _fnDataSource( settings ) === 'ssp'
7566		};
7567	} );
7568	
7569	
7570	/**
7571	 * Get the current page length.
7572	 *
7573	 * @return {integer} Current page length. Note `-1` indicates that all records
7574	 *   are to be shown.
7575	 *//**
7576	 * Set the current page length.
7577	 *
7578	 * @param {integer} Page length to set. Use `-1` to show all records.
7579	 * @returns {DataTables.Api} this
7580	 */
7581	_api_register( 'page.len()', function ( len ) {
7582		// Note that we can't call this function 'length()' because `length`
7583		// is a Javascript property of functions which defines how many arguments
7584		// the function expects.
7585		if ( len === undefined ) {
7586			return this.context.length !== 0 ?
7587				this.context[0]._iDisplayLength :
7588				undefined;
7589		}
7590	
7591		// else, set the page length
7592		return this.iterator( 'table', function ( settings ) {
7593			_fnLengthChange( settings, len );
7594		} );
7595	} );
7596	
7597	
7598	
7599	var __reload = function ( settings, holdPosition, callback ) {
7600		// Use the draw event to trigger a callback
7601		if ( callback ) {
7602			var api = new _Api( settings );
7603	
7604			api.one( 'draw', function () {
7605				callback( api.ajax.json() );
7606			} );
7607		}
7608	
7609		if ( _fnDataSource( settings ) == 'ssp' ) {
7610			_fnReDraw( settings, holdPosition );
7611		}
7612		else {
7613			_fnProcessingDisplay( settings, true );
7614	
7615			// Cancel an existing request
7616			var xhr = settings.jqXHR;
7617			if ( xhr && xhr.readyState !== 4 ) {
7618				xhr.abort();
7619			}
7620	
7621			// Trigger xhr
7622			_fnBuildAjax( settings, [], function( json ) {
7623				_fnClearTable( settings );
7624	
7625				var data = _fnAjaxDataSrc( settings, json );
7626				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7627					_fnAddData( settings, data[i] );
7628				}
7629	
7630				_fnReDraw( settings, holdPosition );
7631				_fnProcessingDisplay( settings, false );
7632			} );
7633		}
7634	};
7635	
7636	
7637	/**
7638	 * Get the JSON response from the last Ajax request that DataTables made to the
7639	 * server. Note that this returns the JSON from the first table in the current
7640	 * context.
7641	 *
7642	 * @return {object} JSON received from the server.
7643	 */
7644	_api_register( 'ajax.json()', function () {
7645		var ctx = this.context;
7646	
7647		if ( ctx.length > 0 ) {
7648			return ctx[0].json;
7649		}
7650	
7651		// else return undefined;
7652	} );
7653	
7654	
7655	/**
7656	 * Get the data submitted in the last Ajax request
7657	 */
7658	_api_register( 'ajax.params()', function () {
7659		var ctx = this.context;
7660	
7661		if ( ctx.length > 0 ) {
7662			return ctx[0].oAjaxData;
7663		}
7664	
7665		// else return undefined;
7666	} );
7667	
7668	
7669	/**
7670	 * Reload tables from the Ajax data source. Note that this function will
7671	 * automatically re-draw the table when the remote data has been loaded.
7672	 *
7673	 * @param {boolean} [reset=true] Reset (default) or hold the current paging
7674	 *   position. A full re-sort and re-filter is performed when this method is
7675	 *   called, which is why the pagination reset is the default action.
7676	 * @returns {DataTables.Api} this
7677	 */
7678	_api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7679		return this.iterator( 'table', function (settings) {
7680			__reload( settings, resetPaging===false, callback );
7681		} );
7682	} );
7683	
7684	
7685	/**
7686	 * Get the current Ajax URL. Note that this returns the URL from the first
7687	 * table in the current context.
7688	 *
7689	 * @return {string} Current Ajax source URL
7690	 *//**
7691	 * Set the Ajax URL. Note that this will set the URL for all tables in the
7692	 * current context.
7693	 *
7694	 * @param {string} url URL to set.
7695	 * @returns {DataTables.Api} this
7696	 */
7697	_api_register( 'ajax.url()', function ( url ) {
7698		var ctx = this.context;
7699	
7700		if ( url === undefined ) {
7701			// get
7702			if ( ctx.length === 0 ) {
7703				return undefined;
7704			}
7705			ctx = ctx[0];
7706	
7707			return ctx.ajax ?
7708				$.isPlainObject( ctx.ajax ) ?
7709					ctx.ajax.url :
7710					ctx.ajax :
7711				ctx.sAjaxSource;
7712		}
7713	
7714		// set
7715		return this.iterator( 'table', function ( settings ) {
7716			if ( $.isPlainObject( settings.ajax ) ) {
7717				settings.ajax.url = url;
7718			}
7719			else {
7720				settings.ajax = url;
7721			}
7722			// No need to consider sAjaxSource here since DataTables gives priority
7723			// to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7724			// value of `sAjaxSource` redundant.
7725		} );
7726	} );
7727	
7728	
7729	/**
7730	 * Load data from the newly set Ajax URL. Note that this method is only
7731	 * available when `ajax.url()` is used to set a URL. Additionally, this method
7732	 * has the same effect as calling `ajax.reload()` but is provided for
7733	 * convenience when setting a new URL. Like `ajax.reload()` it will
7734	 * automatically redraw the table once the remote data has been loaded.
7735	 *
7736	 * @returns {DataTables.Api} this
7737	 */
7738	_api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7739		// Same as a reload, but makes sense to present it for easy access after a
7740		// url change
7741		return this.iterator( 'table', function ( ctx ) {
7742			__reload( ctx, resetPaging===false, callback );
7743		} );
7744	} );
7745	
7746	
7747	
7748	
7749	var _selector_run = function ( type, selector, selectFn, settings, opts )
7750	{
7751		var
7752			out = [], res,
7753			a, i, ien, j, jen,
7754			selectorType = typeof selector;
7755	
7756		// Can't just check for isArray here, as an API or jQuery instance might be
7757		// given with their array like look
7758		if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7759			selector = [ selector ];
7760		}
7761	
7762		for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7763			// Only split on simple strings - complex expressions will be jQuery selectors
7764			a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7765				selector[i].split(',') :
7766				[ selector[i] ];
7767	
7768			for ( j=0, jen=a.length ; j<jen ; j++ ) {
7769				res = selectFn( typeof a[j] === 'string' ? 
vendor: 30,662 bytes, lines 7769-8942
7769$.trim(a[j]) : a[j] );
7770	
7771				if ( res && res.length ) {
7772					out = out.concat( res );
7773				}
7774			}
7775		}
7776	
7777		// selector extensions
7778		var ext = _ext.selector[ type ];
7779		if ( ext.length ) {
7780			for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7781				out = ext[i]( settings, opts, out );
7782			}
7783		}
7784	
7785		return _unique( out );
7786	};
7787	
7788	
7789	var _selector_opts = function ( opts )
7790	{
7791		if ( ! opts ) {
7792			opts = {};
7793		}
7794	
7795		// Backwards compatibility for 1.9- which used the terminology filter rather
7796		// than search
7797		if ( opts.filter && opts.search === undefined ) {
7798			opts.search = opts.filter;
7799		}
7800	
7801		return $.extend( {
7802			search: 'none',
7803			order: 'current',
7804			page: 'all'
7805		}, opts );
7806	};
7807	
7808	
7809	var _selector_first = function ( inst )
7810	{
7811		// Reduce the API instance to the first item found
7812		for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7813			if ( inst[i].length > 0 ) {
7814				// Assign the first element to the first item in the instance
7815				// and truncate the instance and context
7816				inst[0] = inst[i];
7817				inst[0].length = 1;
7818				inst.length = 1;
7819				inst.context = [ inst.context[i] ];
7820	
7821				return inst;
7822			}
7823		}
7824	
7825		// Not found - return an empty instance
7826		inst.length = 0;
7827		return inst;
7828	};
7829	
7830	
7831	var _selector_row_indexes = function ( settings, opts )
7832	{
7833		var
7834			i, ien, tmp, a=[],
7835			displayFiltered = settings.aiDisplay,
7836			displayMaster = settings.aiDisplayMaster;
7837	
7838		var
7839			search = opts.search,  // none, applied, removed
7840			order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7841			page   = opts.page;    // all, current
7842	
7843		if ( _fnDataSource( settings ) == 'ssp' ) {
7844			// In server-side processing mode, most options are irrelevant since
7845			// rows not shown don't exist and the index order is the applied order
7846			// Removed is a special case - for consistency just return an empty
7847			// array
7848			return search === 'removed' ?
7849				[] :
7850				_range( 0, displayMaster.length );
7851		}
7852		else if ( page == 'current' ) {
7853			// Current page implies that order=current and fitler=applied, since it is
7854			// fairly senseless otherwise, regardless of what order and search actually
7855			// are
7856			for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7857				a.push( displayFiltered[i] );
7858			}
7859		}
7860		else if ( order == 'current' || order == 'applied' ) {
7861			a = search == 'none' ?
7862				displayMaster.slice() :                      // no search
7863				search == 'applied' ?
7864					displayFiltered.slice() :                // applied search
7865					$.map( displayMaster, function (el, i) { // removed search
7866						return $.inArray( el, displayFiltered ) === -1 ? el : null;
7867					} );
7868		}
7869		else if ( order == 'index' || order == 'original' ) {
7870			for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7871				if ( search == 'none' ) {
7872					a.push( i );
7873				}
7874				else { // applied | removed
7875					tmp = $.inArray( i, displayFiltered );
7876	
7877					if ((tmp === -1 && search == 'removed') ||
7878						(tmp >= 0   && search == 'applied') )
7879					{
7880						a.push( i );
7881					}
7882				}
7883			}
7884		}
7885	
7886		return a;
7887	};
7888	
7889	
7890	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7891	 * Rows
7892	 *
7893	 * {}          - no selector - use all available rows
7894	 * {integer}   - row aoData index
7895	 * {node}      - TR node
7896	 * {string}    - jQuery selector to apply to the TR elements
7897	 * {array}     - jQuery array of nodes, or simply an array of TR nodes
7898	 *
7899	 */
7900	
7901	
7902	var __row_selector = function ( settings, selector, opts )
7903	{
7904		var rows;
7905		var run = function ( sel ) {
7906			var selInt = _intVal( sel );
7907			var i, ien;
7908	
7909			// Short cut - selector is a number and no options provided (default is
7910			// all records, so no need to check if the index is in there, since it
7911			// must be - dev error if the index doesn't exist).
7912			if ( selInt !== null && ! opts ) {
7913				return [ selInt ];
7914			}
7915	
7916			if ( ! rows ) {
7917				rows = _selector_row_indexes( settings, opts );
7918			}
7919	
7920			if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7921				// Selector - integer
7922				return [ selInt ];
7923			}
7924			else if ( sel === null || sel === undefined || sel === '' ) {
7925				// Selector - none
7926				return rows;
7927			}
7928	
7929			// Selector - function
7930			if ( typeof sel === 'function' ) {
7931				return $.map( rows, function (idx) {
7932					var row = settings.aoData[ idx ];
7933					return sel( idx, row._aData, row.nTr ) ? idx : null;
7934				} );
7935			}
7936	
7937			// Get nodes in the order from the `rows` array with null values removed
7938			var nodes = _removeEmpty(
7939				_pluck_order( settings.aoData, rows, 'nTr' )
7940			);
7941	
7942			// Selector - node
7943			if ( sel.nodeName ) {
7944				if ( sel._DT_RowIndex !== undefined ) {
7945					return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
7946				}
7947				else if ( sel._DT_CellIndex ) {
7948					return [ sel._DT_CellIndex.row ];
7949				}
7950				else {
7951					var host = $(sel).closest('*[data-dt-row]');
7952					return host.length ?
7953						[ host.data('dt-row') ] :
7954						[];
7955				}
7956			}
7957	
7958			// ID selector. Want to always be able to select rows by id, regardless
7959			// of if the tr element has been created or not, so can't rely upon
7960			// jQuery here - hence a custom implementation. This does not match
7961			// Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7962			// but to select it using a CSS selector engine (like Sizzle or
7963			// querySelect) it would need to need to be escaped for some characters.
7964			// DataTables simplifies this for row selectors since you can select
7965			// only a row. A # indicates an id any anything that follows is the id -
7966			// unescaped.
7967			if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7968				// get row index from id
7969				var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7970				if ( rowObj !== undefined ) {
7971					return [ rowObj.idx ];
7972				}
7973	
7974				// need to fall through to jQuery in case there is DOM id that
7975				// matches
7976			}
7977	
7978			// Selector - jQuery selector string, array of nodes or jQuery object/
7979			// As jQuery's .filter() allows jQuery objects to be passed in filter,
7980			// it also allows arrays, so this will cope with all three options
7981			return $(nodes)
7982				.filter( sel )
7983				.map( function () {
7984					return this._DT_RowIndex;
7985				} )
7986				.toArray();
7987		};
7988	
7989		return _selector_run( 'row', selector, run, settings, opts );
7990	};
7991	
7992	
7993	_api_register( 'rows()', function ( selector, opts ) {
7994		// argument shifting
7995		if ( selector === undefined ) {
7996			selector = '';
7997		}
7998		else if ( $.isPlainObject( selector ) ) {
7999			opts = selector;
8000			selector = '';
8001		}
8002	
8003		opts = _selector_opts( opts );
8004	
8005		var inst = this.iterator( 'table', function ( settings ) {
8006			return __row_selector( settings, selector, opts );
8007		}, 1 );
8008	
8009		// Want argument shifting here and in __row_selector?
8010		inst.selector.rows = selector;
8011		inst.selector.opts = opts;
8012	
8013		return inst;
8014	} );
8015	
8016	_api_register( 'rows().nodes()', function () {
8017		return this.iterator( 'row', function ( settings, row ) {
8018			return settings.aoData[ row ].nTr || undefined;
8019		}, 1 );
8020	} );
8021	
8022	_api_register( 'rows().data()', function () {
8023		return this.iterator( true, 'rows', function ( settings, rows ) {
8024			return _pluck_order( settings.aoData, rows, '_aData' );
8025		}, 1 );
8026	} );
8027	
8028	_api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
8029		return this.iterator( 'row', function ( settings, row ) {
8030			var r = settings.aoData[ row ];
8031			return type === 'search' ? r._aFilterData : r._aSortData;
8032		}, 1 );
8033	} );
8034	
8035	_api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
8036		return this.iterator( 'row', function ( settings, row ) {
8037			_fnInvalidate( settings, row, src );
8038		} );
8039	} );
8040	
8041	_api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8042		return this.iterator( 'row', function ( settings, row ) {
8043			return row;
8044		}, 1 );
8045	} );
8046	
8047	_api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8048		var a = [];
8049		var context = this.context;
8050	
8051		// `iterator` will drop undefined values, but in this case we want them
8052		for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8053			for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8054				var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8055				a.push( (hash === true ? '#' : '' )+ id );
8056			}
8057		}
8058	
8059		return new _Api( context, a );
8060	} );
8061	
8062	_api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8063		var that = this;
8064	
8065		this.iterator( 'row', function ( settings, row, thatIdx ) {
8066			var data = settings.aoData;
8067			var rowData = data[ row ];
8068			var i, ien, j, jen;
8069			var loopRow, loopCells;
8070	
8071			data.splice( row, 1 );
8072	
8073			// Update the cached indexes
8074			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8075				loopRow = data[i];
8076				loopCells = loopRow.anCells;
8077	
8078				// Rows
8079				if ( loopRow.nTr !== null ) {
8080					loopRow.nTr._DT_RowIndex = i;
8081				}
8082	
8083				// Cells
8084				if ( loopCells !== null ) {
8085					for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8086						loopCells[j]._DT_CellIndex.row = i;
8087					}
8088				}
8089			}
8090	
8091			// Delete from the display arrays
8092			_fnDeleteIndex( settings.aiDisplayMaster, row );
8093			_fnDeleteIndex( settings.aiDisplay, row );
8094			_fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8095	
8096			// For server-side processing tables - subtract the deleted row from the count
8097			if ( settings._iRecordsDisplay > 0 ) {
8098				settings._iRecordsDisplay--;
8099			}
8100	
8101			// Check for an 'overflow' they case for displaying the table
8102			_fnLengthOverflow( settings );
8103	
8104			// Remove the row's ID reference if there is one
8105			var id = settings.rowIdFn( rowData._aData );
8106			if ( id !== undefined ) {
8107				delete settings.aIds[ id ];
8108			}
8109		} );
8110	
8111		this.iterator( 'table', function ( settings ) {
8112			for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8113				settings.aoData[i].idx = i;
8114			}
8115		} );
8116	
8117		return this;
8118	} );
8119	
8120	
8121	_api_register( 'rows.add()', function ( rows ) {
8122		var newRows = this.iterator( 'table', function ( settings ) {
8123				var row, i, ien;
8124				var out = [];
8125	
8126				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8127					row = rows[i];
8128	
8129					if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8130						out.push( _fnAddTr( settings, row )[0] );
8131					}
8132					else {
8133						out.push( _fnAddData( settings, row ) );
8134					}
8135				}
8136	
8137				return out;
8138			}, 1 );
8139	
8140		// Return an Api.rows() extended instance, so rows().nodes() etc can be used
8141		var modRows = this.rows( -1 );
8142		modRows.pop();
8143		$.merge( modRows, newRows );
8144	
8145		return modRows;
8146	} );
8147	
8148	
8149	
8150	
8151	
8152	/**
8153	 *
8154	 */
8155	_api_register( 'row()', function ( selector, opts ) {
8156		return _selector_first( this.rows( selector, opts ) );
8157	} );
8158	
8159	
8160	_api_register( 'row().data()', function ( data ) {
8161		var ctx = this.context;
8162	
8163		if ( data === undefined ) {
8164			// Get
8165			return ctx.length && this.length ?
8166				ctx[0].aoData[ this[0] ]._aData :
8167				undefined;
8168		}
8169	
8170		// Set
8171		ctx[0].aoData[ this[0] ]._aData = data;
8172	
8173		// Automatically invalidate
8174		_fnInvalidate( ctx[0], this[0], 'data' );
8175	
8176		return this;
8177	} );
8178	
8179	
8180	_api_register( 'row().node()', function () {
8181		var ctx = this.context;
8182	
8183		return ctx.length && this.length ?
8184			ctx[0].aoData[ this[0] ].nTr || null :
8185			null;
8186	} );
8187	
8188	
8189	_api_register( 'row.add()', function ( row ) {
8190		// Allow a jQuery object to be passed in - only a single row is added from
8191		// it though - the first element in the set
8192		if ( row instanceof $ && row.length ) {
8193			row = row[0];
8194		}
8195	
8196		var rows = this.iterator( 'table', function ( settings ) {
8197			if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8198				return _fnAddTr( settings, row )[0];
8199			}
8200			return _fnAddData( settings, row );
8201		} );
8202	
8203		// Return an Api.rows() extended instance, with the newly added row selected
8204		return this.row( rows[0] );
8205	} );
8206	
8207	
8208	
8209	var __details_add = function ( ctx, row, data, klass )
8210	{
8211		// Convert to array of TR elements
8212		var rows = [];
8213		var addRow = function ( r, k ) {
8214			// Recursion to allow for arrays of jQuery objects
8215			if ( $.isArray( r ) || r instanceof $ ) {
8216				for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8217					addRow( r[i], k );
8218				}
8219				return;
8220			}
8221	
8222			// If we get a TR element, then just add it directly - up to the dev
8223			// to add the correct number of columns etc
8224			if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8225				rows.push( r );
8226			}
8227			else {
8228				// Otherwise create a row with a wrapper
8229				var created = $('<tr><td/></tr>').addClass( k );
8230				$('td', created)
8231					.addClass( k )
8232					.html( r )
8233					[0].colSpan = _fnVisbleColumns( ctx );
8234	
8235				rows.push( created[0] );
8236			}
8237		};
8238	
8239		addRow( data, klass );
8240	
8241		if ( row._details ) {
8242			row._details.detach();
8243		}
8244	
8245		row._details = $(rows);
8246	
8247		// If the children were already shown, that state should be retained
8248		if ( row._detailsShow ) {
8249			row._details.insertAfter( row.nTr );
8250		}
8251	};
8252	
8253	
8254	var __details_remove = function ( api, idx )
8255	{
8256		var ctx = api.context;
8257	
8258		if ( ctx.length ) {
8259			var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8260	
8261			if ( row && row._details ) {
8262				row._details.remove();
8263	
8264				row._detailsShow = undefined;
8265				row._details = undefined;
8266			}
8267		}
8268	};
8269	
8270	
8271	var __details_display = function ( api, show ) {
8272		var ctx = api.context;
8273	
8274		if ( ctx.length && api.length ) {
8275			var row = ctx[0].aoData[ api[0] ];
8276	
8277			if ( row._details ) {
8278				row._detailsShow = show;
8279	
8280				if ( show ) {
8281					row._details.insertAfter( row.nTr );
8282				}
8283				else {
8284					row._details.detach();
8285				}
8286	
8287				__details_events( ctx[0] );
8288			}
8289		}
8290	};
8291	
8292	
8293	var __details_events = function ( settings )
8294	{
8295		var api = new _Api( settings );
8296		var namespace = '.dt.DT_details';
8297		var drawEvent = 'draw'+namespace;
8298		var colvisEvent = 'column-visibility'+namespace;
8299		var destroyEvent = 'destroy'+namespace;
8300		var data = settings.aoData;
8301	
8302		api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8303	
8304		if ( _pluck( data, '_details' ).length > 0 ) {
8305			// On each draw, insert the required elements into the document
8306			api.on( drawEvent, function ( e, ctx ) {
8307				if ( settings !== ctx ) {
8308					return;
8309				}
8310	
8311				api.rows( {page:'current'} ).eq(0).each( function (idx) {
8312					// Internal data grab
8313					var row = data[ idx ];
8314	
8315					if ( row._detailsShow ) {
8316						row._details.insertAfter( row.nTr );
8317					}
8318				} );
8319			} );
8320	
8321			// Column visibility change - update the colspan
8322			api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8323				if ( settings !== ctx ) {
8324					return;
8325				}
8326	
8327				// Update the colspan for the details rows (note, only if it already has
8328				// a colspan)
8329				var row, visible = _fnVisbleColumns( ctx );
8330	
8331				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8332					row = data[i];
8333	
8334					if ( row._details ) {
8335						row._details.children('td[colspan]').attr('colspan', visible );
8336					}
8337				}
8338			} );
8339	
8340			// Table destroyed - nuke any child rows
8341			api.on( destroyEvent, function ( e, ctx ) {
8342				if ( settings !== ctx ) {
8343					return;
8344				}
8345	
8346				for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8347					if ( data[i]._details ) {
8348						__details_remove( api, i );
8349					}
8350				}
8351			} );
8352		}
8353	};
8354	
8355	// Strings for the method names to help minification
8356	var _emp = '';
8357	var _child_obj = _emp+'row().child';
8358	var _child_mth = _child_obj+'()';
8359	
8360	// data can be:
8361	//  tr
8362	//  string
8363	//  jQuery or array of any of the above
8364	_api_register( _child_mth, function ( data, klass ) {
8365		var ctx = this.context;
8366	
8367		if ( data === undefined ) {
8368			// get
8369			return ctx.length && this.length ?
8370				ctx[0].aoData[ this[0] ]._details :
8371				undefined;
8372		}
8373		else if ( data === true ) {
8374			// show
8375			this.child.show();
8376		}
8377		else if ( data === false ) {
8378			// remove
8379			__details_remove( this );
8380		}
8381		else if ( ctx.length && this.length ) {
8382			// set
8383			__details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8384		}
8385	
8386		return this;
8387	} );
8388	
8389	
8390	_api_register( [
8391		_child_obj+'.show()',
8392		_child_mth+'.show()' // only when `child()` was called with parameters (without
8393	], function ( show ) {   // it returns an object and this method is not executed)
8394		__details_display( this, true );
8395		return this;
8396	} );
8397	
8398	
8399	_api_register( [
8400		_child_obj+'.hide()',
8401		_child_mth+'.hide()' // only when `child()` was called with parameters (without
8402	], function () {         // it returns an object and this method is not executed)
8403		__details_display( this, false );
8404		return this;
8405	} );
8406	
8407	
8408	_api_register( [
8409		_child_obj+'.remove()',
8410		_child_mth+'.remove()' // only when `child()` was called with parameters (without
8411	], function () {           // it returns an object and this method is not executed)
8412		__details_remove( this );
8413		return this;
8414	} );
8415	
8416	
8417	_api_register( _child_obj+'.isShown()', function () {
8418		var ctx = this.context;
8419	
8420		if ( ctx.length && this.length ) {
8421			// _detailsShown as false or undefined will fall through to return false
8422			return ctx[0].aoData[ this[0] ]._detailsShow || false;
8423		}
8424		return false;
8425	} );
8426	
8427	
8428	
8429	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8430	 * Columns
8431	 *
8432	 * {integer}           - column index (>=0 count from left, <0 count from right)
8433	 * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8434	 * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8435	 * "{string}:name"     - column name
8436	 * "{string}"          - jQuery selector on column header nodes
8437	 *
8438	 */
8439	
8440	// can be an array of these items, comma separated list, or an array of comma
8441	// separated lists
8442	
8443	var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8444	
8445	
8446	// r1 and r2 are redundant - but it means that the parameters match for the
8447	// iterator callback in columns().data()
8448	var __columnData = function ( settings, column, r1, r2, rows ) {
8449		var a = [];
8450		for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8451			a.push( _fnGetCellData( settings, rows[row], column ) );
8452		}
8453		return a;
8454	};
8455	
8456	
8457	var __column_selector = function ( settings, selector, opts )
8458	{
8459		var
8460			columns = settings.aoColumns,
8461			names = _pluck( columns, 'sName' ),
8462			nodes = _pluck( columns, 'nTh' );
8463	
8464		var run = function ( s ) {
8465			var selInt = _intVal( s );
8466	
8467			// Selector - all
8468			if ( s === '' ) {
8469				return _range( columns.length );
8470			}
8471	
8472			// Selector - index
8473			if ( selInt !== null ) {
8474				return [ selInt >= 0 ?
8475					selInt : // Count from left
8476					columns.length + selInt // Count from right (+ because its a negative value)
8477				];
8478			}
8479	
8480			// Selector = function
8481			if ( typeof s === 'function' ) {
8482				var rows = _selector_row_indexes( settings, opts );
8483	
8484				return $.map( columns, function (col, idx) {
8485					return s(
8486							idx,
8487							__columnData( settings, idx, 0, 0, rows ),
8488							nodes[ idx ]
8489						) ? idx : null;
8490				} );
8491			}
8492	
8493			// jQuery or string selector
8494			var match = typeof s === 'string' ?
8495				s.match( __re_column_selector ) :
8496				'';
8497	
8498			if ( match ) {
8499				switch( match[2] ) {
8500					case 'visIdx':
8501					case 'visible':
8502						var idx = parseInt( match[1], 10 );
8503						// Visible index given, convert to column index
8504						if ( idx < 0 ) {
8505							// Counting from the right
8506							var visColumns = $.map( columns, function (col,i) {
8507								return col.bVisible ? i : null;
8508							} );
8509							return [ visColumns[ visColumns.length + idx ] ];
8510						}
8511						// Counting from the left
8512						return [ _fnVisibleToColumnIndex( settings, idx ) ];
8513	
8514					case 'name':
8515						// match by name. `names` is column index complete and in order
8516						return $.map( names, function (name, i) {
8517							return name === match[1] ? i : null;
8518						} );
8519	
8520					default:
8521						return [];
8522				}
8523			}
8524	
8525			// Cell in the table body
8526			if ( s.nodeName && s._DT_CellIndex ) {
8527				return [ s._DT_CellIndex.column ];
8528			}
8529	
8530			// jQuery selector on the TH elements for the columns
8531			var jqResult = $( nodes )
8532				.filter( s )
8533				.map( function () {
8534					return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8535				} )
8536				.toArray();
8537	
8538			if ( jqResult.length || ! s.nodeName ) {
8539				return jqResult;
8540			}
8541	
8542			// Otherwise a node which might have a `dt-column` data attribute, or be
8543			// a child or such an element
8544			var host = $(s).closest('*[data-dt-column]');
8545			return host.length ?
8546				[ host.data('dt-column') ] :
8547				[];
8548		};
8549	
8550		return _selector_run( 'column', selector, run, settings, opts );
8551	};
8552	
8553	
8554	var __setColumnVis = function ( settings, column, vis ) {
8555		var
8556			cols = settings.aoColumns,
8557			col  = cols[ column ],
8558			data = settings.aoData,
8559			row, cells, i, ien, tr;
8560	
8561		// Get
8562		if ( vis === undefined ) {
8563			return col.bVisible;
8564		}
8565	
8566		// Set
8567		// No change
8568		if ( col.bVisible === vis ) {
8569			return;
8570		}
8571	
8572		if ( vis ) {
8573			// Insert column
8574			// Need to decide if we should use appendChild or insertBefore
8575			var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8576	
8577			for ( i=0, ien=data.length ; i<ien ; i++ ) {
8578				tr = data[i].nTr;
8579				cells = data[i].anCells;
8580	
8581				if ( tr ) {
8582					// insertBefore can act like appendChild if 2nd arg is null
8583					tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8584				}
8585			}
8586		}
8587		else {
8588			// Remove column
8589			$( _pluck( settings.aoData, 'anCells', column ) ).detach();
8590		}
8591	
8592		// Common actions
8593		col.bVisible = vis;
8594		_fnDrawHead( settings, settings.aoHeader );
8595		_fnDrawHead( settings, settings.aoFooter );
8596	
8597		_fnSaveState( settings );
8598	};
8599	
8600	
8601	_api_register( 'columns()', function ( selector, opts ) {
8602		// argument shifting
8603		if ( selector === undefined ) {
8604			selector = '';
8605		}
8606		else if ( $.isPlainObject( selector ) ) {
8607			opts = selector;
8608			selector = '';
8609		}
8610	
8611		opts = _selector_opts( opts );
8612	
8613		var inst = this.iterator( 'table', function ( settings ) {
8614			return __column_selector( settings, selector, opts );
8615		}, 1 );
8616	
8617		// Want argument shifting here and in _row_selector?
8618		inst.selector.cols = selector;
8619		inst.selector.opts = opts;
8620	
8621		return inst;
8622	} );
8623	
8624	_api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8625		return this.iterator( 'column', function ( settings, column ) {
8626			return settings.aoColumns[column].nTh;
8627		}, 1 );
8628	} );
8629	
8630	_api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8631		return this.iterator( 'column', function ( settings, column ) {
8632			return settings.aoColumns[column].nTf;
8633		}, 1 );
8634	} );
8635	
8636	_api_registerPlural( 'columns().data()', 'column().data()', function () {
8637		return this.iterator( 'column-rows', __columnData, 1 );
8638	} );
8639	
8640	_api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8641		return this.iterator( 'column', function ( settings, column ) {
8642			return settings.aoColumns[column].mData;
8643		}, 1 );
8644	} );
8645	
8646	_api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8647		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8648			return _pluck_order( settings.aoData, rows,
8649				type === 'search' ? '_aFilterData' : '_aSortData', column
8650			);
8651		}, 1 );
8652	} );
8653	
8654	_api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8655		return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8656			return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8657		}, 1 );
8658	} );
8659	
8660	_api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8661		var ret = this.iterator( 'column', function ( settings, column ) {
8662			if ( vis === undefined ) {
8663				return settings.aoColumns[ column ].bVisible;
8664			} // else
8665			__setColumnVis( settings, column, vis );
8666		} );
8667	
8668		// Group the column visibility changes
8669		if ( vis !== undefined ) {
8670			// Second loop once the first is done for events
8671			this.iterator( 'column', function ( settings, column ) {
8672				_fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8673			} );
8674	
8675			if ( calc === undefined || calc ) {
8676				this.columns.adjust();
8677			}
8678		}
8679	
8680		return ret;
8681	} );
8682	
8683	_api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8684		return this.iterator( 'column', function ( settings, column ) {
8685			return type === 'visible' ?
8686				_fnColumnIndexToVisible( settings, column ) :
8687				column;
8688		}, 1 );
8689	} );
8690	
8691	_api_register( 'columns.adjust()', function () {
8692		return this.iterator( 'table', function ( settings ) {
8693			_fnAdjustColumnSizing( settings );
8694		}, 1 );
8695	} );
8696	
8697	_api_register( 'column.index()', function ( type, idx ) {
8698		if ( this.context.length !== 0 ) {
8699			var ctx = this.context[0];
8700	
8701			if ( type === 'fromVisible' || type === 'toData' ) {
8702				return _fnVisibleToColumnIndex( ctx, idx );
8703			}
8704			else if ( type === 'fromData' || type === 'toVisible' ) {
8705				return _fnColumnIndexToVisible( ctx, idx );
8706			}
8707		}
8708	} );
8709	
8710	_api_register( 'column()', function ( selector, opts ) {
8711		return _selector_first( this.columns( selector, opts ) );
8712	} );
8713	
8714	
8715	
8716	var __cell_selector = function ( settings, selector, opts )
8717	{
8718		var data = settings.aoData;
8719		var rows = _selector_row_indexes( settings, opts );
8720		var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8721		var allCells = $( [].concat.apply([], cells) );
8722		var row;
8723		var columns = settings.aoColumns.length;
8724		var a, i, ien, j, o, host;
8725	
8726		var run = function ( s ) {
8727			var fnSelector = typeof s === 'function';
8728	
8729			if ( s === null || s === undefined || fnSelector ) {
8730				// All cells and function selectors
8731				a = [];
8732	
8733				for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8734					row = rows[i];
8735	
8736					for ( j=0 ; j<columns ; j++ ) {
8737						o = {
8738							row: row,
8739							column: j
8740						};
8741	
8742						if ( fnSelector ) {
8743							// Selector - function
8744							host = data[ row ];
8745	
8746							if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8747								a.push( o );
8748							}
8749						}
8750						else {
8751							// Selector - all
8752							a.push( o );
8753						}
8754					}
8755				}
8756	
8757				return a;
8758			}
8759			
8760			// Selector - index
8761			if ( $.isPlainObject( s ) ) {
8762				return [s];
8763			}
8764	
8765			// Selector - jQuery filtered cells
8766			var jqResult = allCells
8767				.filter( s )
8768				.map( function (i, el) {
8769					return { // use a new object, in case someone changes the values
8770						row:    el._DT_CellIndex.row,
8771						column: el._DT_CellIndex.column
8772	 				};
8773				} )
8774				.toArray();
8775	
8776			if ( jqResult.length || ! s.nodeName ) {
8777				return jqResult;
8778			}
8779	
8780			// Otherwise the selector is a node, and there is one last option - the
8781			// element might be a child of an element which has dt-row and dt-column
8782			// data attributes
8783			host = $(s).closest('*[data-dt-row]');
8784			return host.length ?
8785				[ {
8786					row: host.data('dt-row'),
8787					column: host.data('dt-column')
8788				} ] :
8789				[];
8790		};
8791	
8792		return _selector_run( 'cell', selector, run, settings, opts );
8793	};
8794	
8795	
8796	
8797	
8798	_api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8799		// Argument shifting
8800		if ( $.isPlainObject( rowSelector ) ) {
8801			// Indexes
8802			if ( rowSelector.row === undefined ) {
8803				// Selector options in first parameter
8804				opts = rowSelector;
8805				rowSelector = null;
8806			}
8807			else {
8808				// Cell index objects in first parameter
8809				opts = columnSelector;
8810				columnSelector = null;
8811			}
8812		}
8813		if ( $.isPlainObject( columnSelector ) ) {
8814			opts = columnSelector;
8815			columnSelector = null;
8816		}
8817	
8818		// Cell selector
8819		if ( columnSelector === null || columnSelector === undefined ) {
8820			return this.iterator( 'table', function ( settings ) {
8821				return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8822			} );
8823		}
8824	
8825		// Row + column selector
8826		var columns = this.columns( columnSelector, opts );
8827		var rows = this.rows( rowSelector, opts );
8828		var a, i, ien, j, jen;
8829	
8830		var cells = this.iterator( 'table', function ( settings, idx ) {
8831			a = [];
8832	
8833			for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8834				for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8835					a.push( {
8836						row:    rows[idx][i],
8837						column: columns[idx][j]
8838					} );
8839				}
8840			}
8841	
8842			return a;
8843		}, 1 );
8844	
8845		$.extend( cells.selector, {
8846			cols: columnSelector,
8847			rows: rowSelector,
8848			opts: opts
8849		} );
8850	
8851		return cells;
8852	} );
8853	
8854	
8855	_api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8856		return this.iterator( 'cell', function ( settings, row, column ) {
8857			var data = settings.aoData[ row ];
8858	
8859			return data && data.anCells ?
8860				data.anCells[ column ] :
8861				undefined;
8862		}, 1 );
8863	} );
8864	
8865	
8866	_api_register( 'cells().data()', function () {
8867		return this.iterator( 'cell', function ( settings, row, column ) {
8868			return _fnGetCellData( settings, row, column );
8869		}, 1 );
8870	} );
8871	
8872	
8873	_api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8874		type = type === 'search' ? '_aFilterData' : '_aSortData';
8875	
8876		return this.iterator( 'cell', function ( settings, row, column ) {
8877			return settings.aoData[ row ][ type ][ column ];
8878		}, 1 );
8879	} );
8880	
8881	
8882	_api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8883		return this.iterator( 'cell', function ( settings, row, column ) {
8884			return _fnGetCellData( settings, row, column, type );
8885		}, 1 );
8886	} );
8887	
8888	
8889	_api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8890		return this.iterator( 'cell', function ( settings, row, column ) {
8891			return {
8892				row: row,
8893				column: column,
8894				columnVisible: _fnColumnIndexToVisible( settings, column )
8895			};
8896		}, 1 );
8897	} );
8898	
8899	
8900	_api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8901		return this.iterator( 'cell', function ( settings, row, column ) {
8902			_fnInvalidate( settings, row, src, column );
8903		} );
8904	} );
8905	
8906	
8907	
8908	_api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8909		return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8910	} );
8911	
8912	
8913	_api_register( 'cell().data()', function ( data ) {
8914		var ctx = this.context;
8915		var cell = this[0];
8916	
8917		if ( data === undefined ) {
8918			// Get
8919			return ctx.length && cell.length ?
8920				_fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8921				undefined;
8922		}
8923	
8924		// Set
8925		_fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8926		_fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8927	
8928		return this;
8929	} );
8930	
8931	
8932	
8933	/**
8934	 * Get current ordering (sorting) that has been applied to the table.
8935	 *
8936	 * @returns {array} 2D array containing the sorting information for the first
8937	 *   table in the current context. Each element in the parent array represents
8938	 *   a column being sorted upon (i.e. multi-sorting with two columns would have
8939	 *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8940	 *   the column index that the sorting condition applies to, the second is the
8941	 *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8942	 *   index of the sorting order from the `column.sorting` initialisation array.
8943	 *//**
8944	 * Set the ordering for the table.
8945	 *
8946	 * @param {integer} order Column index to sort upon.
8947	 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8948	 * @returns {DataTables.Api} this
8949	 *//**
8950	 * Set the ordering for the table.
8951	 *
8952	 * @param {array} order 1D array of sorting information to be applied.
8953	 * @param {array} [...] Optional additional sorting conditions
8954	 * @returns {DataTables.Api} this
8955	 *//**
8956	 * Set the ordering for the table.
8957	 *
8958	 * @param {array} order 2D array of sorting information to be applied.
8959	 * @returns {DataTables.Api} this
8960	 */
8961	_api_register( 'order()', function ( order, dir ) {
8962		var ctx = this.context;
8963	
8964		if ( order === undefined ) {
8965			// get
8966			return ctx.length !== 0 ?
8967				ctx[0].aaSorting :
8968				undefined;
8969		}
8970	
8971		// set
8972		if ( typeof order === 'number' ) {
8973			// Simple column / direction passed in
8974			order = [ [ order, dir ] ];
8975		}
8976		else if ( order.length && ! $.isArray( order[0] ) ) {
8977			// Arguments passed in (list of 1D arrays)
8978			order = Array.prototype.slice.call( arguments );
8979		}
8980		// otherwise a 2D array was passed in
8981	
8982		return this.iterator( 'table', function ( settings ) {
8983			settings.aaSorting = order.slice();
8984		} );
8985	} );
8986	
8987	
8988	/**
8989	 * Attach a sort listener to an element for a given column
8990	 *
8991	 * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8992	 *   listener to. This can take the form of a single DOM node, a jQuery
8993	 *   collection of nodes or a jQuery selector which will identify the node(s).
8994	 * @param {integer} column the column that a click on this node will sort on
8995	 * @param {function} [callback] callback function when sort is run
8996	 * @returns {DataTables.Api} this
8997	 */
8998	_api_register( 'order.listener()', function ( node, column, callback ) {
8999		return this.iterator( 'table', function ( settings ) {
9000			_fnSortAttachListener( settings, node, column, callback );
9001		} );
9002	} );
9003	
9004	
9005	_api_register( 'order.fixed()', function ( set ) {
9006		if ( ! set ) {
9007			var ctx = this.context;
9008			var fixed = ctx.length ?
9009				ctx[0].aaSortingFixed :
9010				undefined;
9011	
9012			return $.isArray( fixed ) ?
9013				{ pre: fixed } :
9014				fixed;
9015		}
9016	
9017		return this.iterator( 'table', function ( settings ) {
9018			settings.aaSortingFixed = $.extend( true, {}, set );
9019		} );
9020	} );
9021	
9022	
9023	// Order by the selected column(s)
9024	_api_register( [
9025		'columns().order()',
9026		'column().order()'
9027	], function ( dir ) {
9028		var that = this;
9029	
9030		return this.iterator( 'table', function ( settings, i ) {
9031			var sort = [];
9032	
9033			$.each( that[i], function (j, col) {
9034				sort.push( [ col, dir ] );
9035			} );
9036	
9037			settings.aaSorting = sort;
9038		} );
9039	} );
9040	
9041	
9042	
9043	_api_register( 'search()', function ( input, regex, smart, caseInsen ) {
9044		var ctx = this.context;
9045	
9046		if ( input === undefined ) {
9047			// get
9048			return ctx.length !== 0 ?
9049				ctx[0].oPreviousSearch.sSearch :
9050				undefined;
9051		}
9052	
9053		// set
9054		return this.iterator( 'table', function ( settings ) {
9055			if ( ! settings.oFeatures.bFilter ) {
9056				return;
9057			}
9058	
9059			_fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9060				"sSearch": input+"",
9061				"bRegex":  regex === null ? false : regex,
9062				"bSmart":  smart === null ? true  : smart,
9063				"bCaseInsensitive": caseInsen === null ? true : caseInsen
9064			} ), 1 );
9065		} );
9066	} );
9067	
9068	
9069	_api_registerPlural(
9070		'columns().search()',
9071		'column().search()',
9072		function ( input, regex, smart, caseInsen ) {
9073			return this.iterator( 'column', function ( settings, column ) {
9074				var preSearch = settings.aoPreSearchCols;
9075	
9076				if ( input === undefined ) {
9077					// get
9078					return preSearch[ column ].sSearch;
9079				}
9080	
9081				// set
9082				if ( ! settings.oFeatures.bFilter ) {
9083					return;
9084				}
9085	
9086				$.extend( preSearch[ column ], {
9087					"sSearch": input+"",
9088					"bRegex":  regex === null ? false : regex,
9089					"bSmart":  smart === null ? true  : smart,
9090					"bCaseInsensitive": caseInsen === null ? true : caseInsen
9091				} );
9092	
9093				_fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9094			} );
9095		}
9096	);
9097	
9098	/*
9099	 * State API methods
9100	 */
9101	
9102	_api_register( 'state()', function () {
9103		return this.context.length ?
9104			this.context[0].oSavedState :
9105			null;
9106	} );
9107	
9108	
9109	_api_register( 'state.clear()', function () {
9110		return this.iterator( 'table', function ( settings ) {
9111			// Save an empty object
9112			settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9113		} );
9114	} );
9115	
9116	
9117	_api_register( 'state.loaded()', function () {
9118		return this.context.length ?
9119			this.context[0].oLoadedState :
9120			null;
9121	} );
9122	
9123	
9124	_api_register( 'state.save()', function () {
9125		return this.iterator( 'table', function ( settings ) {
9126			_fnSaveState( settings );
9127		} );
9128	} );
9129	
9130	
9131	
9132	/**
9133	 * Provide a common method for plug-ins to check the version of DataTables being
9134	 * used, in order to ensure compatibility.
9135	 *
9136	 *  @param {string} version Version string to check for, in the format "X.Y.Z".
9137	 *    Note that the formats "X" and "X.Y" are also acceptable.
9138	 *  @returns {boolean} true if this version of DataTables is greater or equal to
9139	 *    the required version, or false if this version of DataTales is not
9140	 *    suitable
9141	 *  @static
9142	 *  @dtopt API-Static
9143	 *
9144	 *  @example
9145	 *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9146	 */
9147	DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9148	{
9149		var aThis = DataTable.version.split('.');
9150		var aThat = version.split('.');
9151		var iThis, iThat;
9152	
9153		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9154			iThis = parseInt( aThis[i], 10 ) || 0;
9155			iThat = parseInt( aThat[i], 10 ) || 0;
9156	
9157			// Parts are the same, keep comparing
9158			if (iThis === iThat) {
9159				continue;
9160			}
9161	
9162			// Parts are different, return immediately
9163			return iThis > iThat;
9164		}
9165	
9166		return true;
9167	};
9168	
9169	
9170	/**
9171	 * Check if a `<table>` node is a DataTable table already or not.
9172	 *
9173	 *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9174	 *      selector for the table to test. Note that if more than more than one
9175	 *      table is passed on, only the first will be checked
9176	 *  @returns {boolean} true the table given is a DataTable, or false otherwise
9177	 *  @static
9178	 *  @dtopt API-Static
9179	 *
9180	 *  @example
9181	 *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9182	 *      $('#example').dataTable();
9183	 *    }
9184	 */
9185	DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9186	{
9187		var t = $(table).get(0);
9188		var is = false;
9189	
9190		if ( table instanceof DataTable.Api ) {
9191			return true;
9192		}
9193	
9194		$.each( DataTable.settings, function (i, o) {
9195			var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9196			var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9197	
9198			if ( o.nTable === t || head === t || foot === t ) {
9199				is = true;
9200			}
9201		} );
9202	
9203		return is;
9204	};
9205	
9206	
9207	/**
9208	 * Get all DataTable tables that have been initialised - optionally you can
9209	 * select to get only currently visible tables.
9210	 *
9211	 *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9212	 *    or visible tables only.
9213	 *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9214	 *    DataTables
9215	 *  @static
9216	 *  @dtopt API-Static
9217	 *
9218	 *  @example
9219	 *    $.each( $.fn.dataTable.tables(true), function () {
9220	 *      $(table).DataTable().columns.adjust();
9221	 *    } );
9222	 */
9223	DataTable.tables = DataTable.fnTables = function ( visible )
9224	{
9225		var api = false;
9226	
9227		if ( $.isPlainObject( visible ) ) {
9228			api = visible.api;
9229			visible = visible.visible;
9230		}
9231	
9232		var a = $.map( DataTable.settings, function (o) {
9233			if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9234				return o.nTable;
9235			}
9236		} );
9237	
9238		return api ?
9239			new _Api( a ) :
9240			a;
9241	};
9242	
9243	
9244	/**
9245	 * Convert from camel case parameters to Hungarian notation. This is made public
9246	 * for the extensions to provide the same ability as DataTables core to accept
9247	 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9248	 * parameters.
9249	 *
9250	 *  @param {object} src The model object which holds all parameters that can be
9251	 *    mapped.
9252	 *  @param {object} user The object to convert from camel case to Hungarian.
9253	 *  @param {boolean} force When set to `true`, properties which already have a
9254	 *    Hungarian value in the `user` object will be overwritten. Otherwise they
9255	 *    won't be.
9256	 */
9257	DataTable.camelToHungarian = _fnCamelToHungarian;
9258	
9259	
9260	
9261	/**
9262	 *
9263	 */
9264	_api_register( '$()', function ( selector, opts ) {
9265		var
9266			rows   = this.rows( opts ).nodes(), // Get all rows
9267			jqRows = $(rows);
9268	
9269		return $( [].concat(
9270			jqRows.filter( selector ).toArray(),
9271			jqRows.find( selector ).toArray()
9272		) );
9273	} );
9274	
9275	
9276	// jQuery functions to operate on the tables
9277	$.each( [ 'on', 'one', 'off' ], function (i, key) {
9278		_api_register( key+'()', function ( /* event, handler */ ) {
9279			var args = Array.prototype.slice.call(arguments);
9280	
9281			// Add the `dt` namespace automatically if it isn't already present
9282			args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9283				return ! e.match(/\.dt\b/) ?
9284					e+'.dt' :
9285					e;
9286				} ).join( ' ' );
9287	
9288			var inst = $( this.tables().nodes() );
9289			inst[key].apply( inst, args );
9290			return this;
9291		} );
9292	} );
9293	
9294	
9295	_api_register( 'clear()', function () {
9296		return this.iterator( 'table', function ( settings ) {
9297			_fnClearTable( settings );
9298		} );
9299	} );
9300	
9301	
9302	_api_register( 'settings()', function () {
9303		return new _Api( this.context, this.context );
9304	} );
9305	
9306	
9307	_api_register( 'init()', function () {
9308		var ctx = this.context;
9309		return ctx.length ? ctx[0].oInit : null;
9310	} );
9311	
9312	
9313	_api_register( 'data()', function () {
9314		return this.iterator( 'table', function ( settings ) {
9315			return _pluck( settings.aoData, '_aData' );
9316		} ).flatten();
9317	} );
9318	
9319	
9320	_api_register( 'destroy()', function ( remove ) {
9321		remove = remove || false;
9322	
9323		return this.iterator( 'table', function ( settings ) {
9324			var orig      = settings.nTableWrapper.parentNode;
9325			var classes   = settings.oClasses;
9326			var table     = settings.nTable;
9327			var tbody     = settings.nTBody;
9328			var thead     = settings.nTHead;
9329			var tfoot     = settings.nTFoot;
9330			var jqTable   = $(table);
9331			var jqTbody   = $(tbody);
9332			var jqWrapper = $(settings.nTableWrapper);
9333			var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9334			var i, ien;
9335	
9336			// Flag to note that the table is currently being destroyed - no action
9337			// should be taken
9338			settings.bDestroying = true;
9339	
vendor: 4,126 bytes, lines 9340-9472
9340			// Fire off the destroy callbacks for plug-ins etc
9341			_fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9342	
9343			// If not being removed from the document, make all columns visible
9344			if ( ! remove ) {
9345				new _Api( settings ).columns().visible( true );
9346			}
9347	
9348			// Blitz all `DT` namespaced events (these are internal events, the
9349			// lowercase, `dt` events are user subscribed and they are responsible
9350			// for removing them
9351			jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9352			$(window).off('.DT-'+settings.sInstance);
9353	
9354			// When scrolling we had to break the table up - restore it
9355			if ( table != thead.parentNode ) {
9356				jqTable.children('thead').detach();
9357				jqTable.append( thead );
9358			}
9359	
9360			if ( tfoot && table != tfoot.parentNode ) {
9361				jqTable.children('tfoot').detach();
9362				jqTable.append( tfoot );
9363			}
9364	
9365			settings.aaSorting = [];
9366			settings.aaSortingFixed = [];
9367			_fnSortingClasses( settings );
9368	
9369			$( rows ).removeClass( settings.asStripeClasses.join(' ') );
9370	
9371			$('th, td', thead).removeClass( classes.sSortable+' '+
9372				classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9373			);
9374	
9375			// Add the TR elements back into the table in their original order
9376			jqTbody.children().detach();
9377			jqTbody.append( rows );
9378	
9379			// Remove the DataTables generated nodes, events and classes
9380			var removedMethod = remove ? 'remove' : 'detach';
9381			jqTable[ removedMethod ]();
9382			jqWrapper[ removedMethod ]();
9383	
9384			// If we need to reattach the table to the document
9385			if ( ! remove && orig ) {
9386				// insertBefore acts like appendChild if !arg[1]
9387				orig.insertBefore( table, settings.nTableReinsertBefore );
9388	
9389				// Restore the width of the original table - was read from the style property,
9390				// so we can restore directly to that
9391				jqTable
9392					.css( 'width', settings.sDestroyWidth )
9393					.removeClass( classes.sTable );
9394	
9395				// If the were originally stripe classes - then we add them back here.
9396				// Note this is not fool proof (for example if not all rows had stripe
9397				// classes - but it's a good effort without getting carried away
9398				ien = settings.asDestroyStripes.length;
9399	
9400				if ( ien ) {
9401					jqTbody.children().each( function (i) {
9402						$(this).addClass( settings.asDestroyStripes[i % ien] );
9403					} );
9404				}
9405			}
9406	
9407			/* Remove the settings object from the settings array */
9408			var idx = $.inArray( settings, DataTable.settings );
9409			if ( idx !== -1 ) {
9410				DataTable.settings.splice( idx, 1 );
9411			}
9412		} );
9413	} );
9414	
9415	
9416	// Add the `every()` method for rows, columns and cells in a compact form
9417	$.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9418		_api_register( type+'s().every()', function ( fn ) {
9419			var opts = this.selector.opts;
9420			var api = this;
9421	
9422			return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9423				// Rows and columns:
9424				//  arg1 - index
9425				//  arg2 - table counter
9426				//  arg3 - loop counter
9427				//  arg4 - undefined
9428				// Cells:
9429				//  arg1 - row index
9430				//  arg2 - column index
9431				//  arg3 - table counter
9432				//  arg4 - loop counter
9433				fn.call(
9434					api[ type ](
9435						arg1,
9436						type==='cell' ? arg2 : opts,
9437						type==='cell' ? opts : undefined
9438					),
9439					arg1, arg2, arg3, arg4
9440				);
9441			} );
9442		} );
9443	} );
9444	
9445	
9446	// i18n method for extensions to be able to use the language object from the
9447	// DataTable
9448	_api_register( 'i18n()', function ( token, def, plural ) {
9449		var ctx = this.context[0];
9450		var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9451	
9452		if ( resolved === undefined ) {
9453			resolved = def;
9454		}
9455	
9456		if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9457			resolved = resolved[ plural ] !== undefined ?
9458				resolved[ plural ] :
9459				resolved._;
9460		}
9461	
9462		return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9463	} );
9464
9465	/**
9466	 * Version string for plug-ins to check compatibility. Allowed format is
9467	 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9468	 * only for non-release builds. See http://semver.org/ for more information.
9469	 *  @member
9470	 *  @type string
9471	 *  @default Version number
9472	 */
9473	DataTable.version = "1.10.16";
9474
9475	/**
9476	 * Private data store, containing all of the settings objects that are
9477	 * created for the tables on a given page.
9478	 *
9479	 * Note that the `DataTable.settings` object is aliased to
9480	 * `jQuery.fn.dataTableExt` through which it may be accessed and
9481	 * manipulated, or `jQuery.fn.dataTable.settings`.
9482	 *  @member
9483	 *  @type array
9484	 *  @default []
9485	 *  @private
9486	 */
9487	DataTable.settings = [];
9488
9489	/**
9490	 * Object models container, for the various models that DataTables has
9491	 * available to it. These models define the objects that are used to hold
9492	 * the active state and configuration of the table.
9493	 *  @namespace
9494	 */
9495	DataTable.models = {};
9496	
9497	
9498	
9499	/**
9500	 * Template object for the way in which DataTables holds information about
9501	 * search information for the global filter and individual column filters.
9502	 *  @namespace
9503	 */
9504	DataTable.models.oSearch = {
9505		/**
9506		 * Flag to indicate if the filtering should be case insensitive or not
9507		 *  @type boolean
9508		 *  @default true
9509		 */
9510		"bCaseInsensitive": true,
9511	
9512		/**
9513		 * Applied search term
9514		 *  @type string
9515		 *  @default <i>Empty string</i>
9516		 */
9517		"sSearch": "",
9518	
9519		/**
9520		 * Flag to indicate if the search term should be interpreted as a
9521		 * regular expression (true) or not (false) and therefore and special
9522		 * regex characters escaped.
9523		 *  @type boolean
9524		 *  @default false
9525		 */
9526		"bRegex": false,
9527	
9528		/**
9529		 * Flag to indicate if DataTables is to use its smart filtering or not.
9530		 *  @type boolean
9531		 *  @default true
9532		 */
9533		"bSmart": true
9534	};
9535	
9536	
9537	
9538	
9539	/**
9540	 * Template object for the way in which DataTables holds information about
9541	 * each individual row. This is the object format used for the settings
9542	 * aoData array.
9543	 *  @namespace
9544	 */
9545	DataTable.models.oRow = {
9546		/**
9547		 * TR element for the row
9548		 *  @type node
9549		 *  @default null
9550		 */
9551		"nTr": null,
9552	
9553		/**
9554		 * Array of TD elements for each row. This is null until the row has been
9555		 * created.
9556		 *  @type array nodes
9557		 *  @default []
9558		 */
9559		"anCells": null,
9560	
9561		/**
9562		 * Data object from the original data source for the row. This is either
9563		 * an array if using the traditional form of DataTables, or an object if
9564		 * using mData options. The exact type will depend on the passed in
9565		 * data from the data source, or will be an array if using DOM a data
9566		 * source.
9567		 *  @type array|object
9568		 *  @default []
9569		 */
9570		"_aData": [],
9571	
9572		/**
9573		 * Sorting data cache - this array is ostensibly the same length as the
9574		 * number of columns (although each index is generated only as it is
9575		 * needed), and holds the data that is used for sorting each column in the
9576		 * row. We do this cache generation at the start of the sort in order that
9577		 * the formatting of the sort data need be done only once for each cell
9578		 * per sort. This array should not be read from or written to by anything
9579		 * other than the master sorting methods.
9580		 *  @type array
9581		 *  @default null
9582		 *  @private
9583		 */
9584		"_aSortData": null,
9585	
9586		/**
9587		 * Per cell filtering data cache. As per the sort data cache, used to
9588		 * increase the performance of the filtering in DataTables
9589		 *  @type array
9590		 *  @default null
9591		 *  @private
9592		 */
9593		"_aFilterData": null,
9594	
9595		/**
9596		 * Filtering data cache. This is the same as the cell filtering cache, but
9597		 * in this case a string rather than an array. This is easily computed with
9598		 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9599		 * needed on every search (memory traded for performance)
9600		 *  @type array
9601		 *  @default null
9602		 *  @private
9603		 */
9604		"_sFilterRow": null,
9605	
9606		/**
9607		 * Cache of the class name that DataTables has applied to the row, so we
9608		 * can quickly look at this variable rather than needing to do a DOM check
9609		 * on className for the nTr property.
9610		 *  @type string
9611		 *  @default <i>Empty string</i>
9612		 *  @private
9613		 */
9614		"_sRowStripe": "",
9615	
9616		/**
9617		 * Denote if the original data source was from the DOM, or the data source
9618		 * object. This is used for invalidating data, so DataTables can
9619		 * automatically read data from the original source, unless uninstructed
9620		 * otherwise.
9621		 *  @type string
9622		 *  @default null
9623		 *  @private
9624		 */
9625		"src": null,
9626	
9627		/**
9628		 * Index in the aoData array. This saves an indexOf lookup when we have the
9629		 * object, but want to know the index
9630		 *  @type integer
9631		 *  @default -1
9632		 *  @private
9633		 */
9634		"idx": -1
9635	};
9636	
9637	
9638	/**
9639	 * Template object for the column information object in DataTables. This object
9640	 * is held in the settings aoColumns array and contains all the information that
9641	 * DataTables needs about each individual column.
9642	 *
9643	 * Note that this object is related to {@link DataTable.defaults.column}
9644	 * but this one is the internal data store for DataTables's cache of columns.
9645	 * It should NOT be manipulated outside of DataTables. Any configuration should
9646	 * be done through the initialisation options.
9647	 *  @namespace
9648	 */
9649	DataTable.models.oColumn = {
9650		/**
9651		 * Column index. This could be worked out on-the-fly with $.inArray, but it
9652		 * is faster to just hold it as a variable
9653		 *  @type integer
9654		 *  @default null
9655		 */
9656		"idx": null,
9657	
9658		/**
9659		 * A list of the columns that sorting should occur on when this column
9660		 * is sorted. That this property is an array allows multi-column s
9660orting
9661		 * to be defined for a column (for example first name / last name columns
9662		 * would benefit from this). The values are integers pointing to the
9663		 * columns to be sorted on (typically it will be a single integer pointing
9664		 * at itself, but that doesn't need to be the case).
9665		 *  @type array
9666		 */
9667		"aDataSort": null,
9668	
9669		/**
9670		 * Define the sorting directions that are applied to the column, in sequence
9671		 * as the column is repeatedly sorted upon - i.e. the first value is used
9672		 * as the sorting direction when the column if first sorted (clicked on).
9673		 * Sort it again (click again) and it will move on to the next index.
9674		 * Repeat until loop.
9675		 *  @type array
9676		 */
9677		"asSorting": null,
9678	
9679		/**
9680		 * Flag to indicate if the column is searchable, and thus should be included
9681		 * in the filtering or not.
9682		 *  @type boolean
9683		 */
9684		"bSearchable": null,
9685	
9686		/**
9687		 * Flag to indicate if the column is sortable or not.
9688		 *  @type boolean
9689		 */
9690		"bSortable": null,
9691	
9692		/**
9693		 * Flag to indicate if the column is currently visible in the table or not
9694		 *  @type boolean
9695		 */
9696		"bVisible": null,
9697	
9698		/**
9699		 * Store for manual type assignment using the `column.type` option. This
9700		 * is held in store so we can manipulate the column's `sType` property.
9701		 *  @type string
9702		 *  @default null
9703		 *  @private
9704		 */
9705		"_sManualType": null,
9706	
9707		/**
9708		 * Flag to indicate if HTML5 data attributes should be used as the data
9709		 * source for filtering or sorting. True is either are.
9710		 *  @type boolean
9711		 *  @default false
9712		 *  @private
9713		 */
9714		"_bAttrSrc": false,
9715	
9716		/**
9717		 * Developer definable function that is called whenever a cell is created (Ajax source,
9718		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9719		 * allowing you to modify the DOM element (add background colour for example) when the
9720		 * element is available.
9721		 *  @type function
9722		 *  @param {element} nTd The TD node that has been created
9723		 *  @param {*} sData The Data for the cell
9724		 *  @param {array|object} oData The data for the whole row
9725		 *  @param {int} iRow The row index for the aoData data store
9726		 *  @default null
9727		 */
9728		"fnCreatedCell": null,
9729	
9730		/**
9731		 * Function to get data from a cell in a column. You should <b>never</b>
9732		 * access data directly through _aData internally in DataTables - always use
9733		 * the method attached to this property. It allows mData to function as
9734		 * required. This function is automatically assigned by the column
9735		 * initialisation method
9736		 *  @type function
9737		 *  @param {array|object} oData The data array/object for the array
9738		 *    (i.e. aoData[]._aData)
9739		 *  @param {string} sSpecific The specific data type you want to get -
9740		 *    'display', 'type' 'filter' 'sort'
9741		 *  @returns {*} The data for the cell from the given row's data
9742		 *  @default null
9743		 */
9744		"fnGetData": null,
9745	
9746		/**
9747		 * Function to set data for a cell in the column. You should <b>never</b>
9748		 * set the data directly to _aData internally in DataTables - always use
9749		 * this method. It allows mData to function as required. This function
9750		 * is automatically assigned by the column initialisation method
9751		 *  @type function
9752		 *  @param {array|object} oData The data array/object for the array
9753		 *    (i.e. aoData[]._aData)
9754		 *  @param {*} sValue Value to set
9755		 *  @default null
9756		 */
9757		"fnSetData": null,
9758	
9759		/**
9760		 * Property to read the value for the cells in the column from the data
9761		 * source array / object. If null, then the default content is used, if a
9762		 * function is given then the return from the function is used.
9763		 *  @type function|int|string|null
9764		 *  @default null
9765		 */
9766		"mData": null,
9767	
9768		/**
9769		 * Partner property to mData which is used (only when defined) to get
9770		 * the data - i.e. it is basically the same as mData, but without the
9771		 * 'set' option, and also the data fed to it is the result from mData.
9772		 * This is the rendering method to match the data method of mData.
9773		 *  @type function|int|string|null
9774		 *  @default null
9775		 */
9776		"mRender": null,
9777	
9778		/**
9779		 * Unique header TH/TD element for this column - this is what the sorting
9780		 * listener is attached to (if sorting is enabled.)
9781		 *  @type node
9782		 *  @default null
9783		 */
9784		"nTh": null,
9785	
9786		/**
9787		 * Unique footer TH/TD element for this column (if there is one). Not used
9788		 * in DataTables as such, but can be used for plug-ins to reference the
9789		 * footer for each column.
9790		 *  @type node
9791		 *  @default null
9792		 */
9793		"nTf": null,
9794	
9795		/**
9796		 * The class to apply to all TD elements in the table's TBODY for the column
9797		 *  @type string
9798		 *  @default null
9799		 */
9800		"sClass": null,
9801	
9802		/**
9803		 * When DataTables calculates the column widths to assign to each column,
9804		 * it finds the longest string in each column and then constructs a
9805		 * temporary table and reads the widths from that. The problem with this
9806		 * is that "mmm" is much wider then "iiii", but the latter is a longer
9807		 * string - thus the calculation can go wrong (doing it properly and putting
9808		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9809		 * a "work around" we provide this option. It will append its value to the
9810		 * text that is found to be the longest string for the column - i.e. padding.
9811		 *  @type string
9812		 */
9813		"sContentPadding": null,
9814	
9815		/**
9816		 * Allows a default value to be given for a column's data, and will be used
9817		 * whenever a null data source is encountered (this can be because mData
9818		 * is set to null, or because the data source itself is null).
9819		 *  @type string
9820		 *  @default null
9821		 */
9822		"sDefaultContent": null,
9823	
9824		/**
9825		 * Name for the column, allowing reference to the column by name as well as
9826		 * by index (needs a lookup to work by name).
9827		 *  @type string
9828		 */
9829		"sName": null,
9830	
9831		/**
9832		 * Custom sorting data type - defines which of the available plug-ins in
9833		 * afnSortData the custom sorting will use - if any is defined.
9834		 *  @type string
9835		 *  @default std
9836		 */
9837		"sSortDataType": 'std',
9838	
9839		/**
9840		 * Class to be applied to the header element when sorting on this column
9841		 *  @type string
9842		 *  @default null
9843		 */
9844		"sSortingClass": null,
9845	
9846		/**
9847		 * Class to be applied to the header element when sorting on this column -
9848		 * when jQuery UI theming is used.
9849		 *  @type string
9850		 *  @default null
9851		 */
9852		"sSortingClassJUI": null,
9853	
9854		/**
9855		 * Title of the column - what is seen in the TH element (nTh).
9856		 *  @type string
9857		 */
9858		"sTitle": null,
9859	
9860		/**
9861		 * Column sorting and filtering type
9862		 *  @type string
9863		 *  @default null
9864		 */
9865		"sType": null,
9866	
9867		/**
9868		 * Width of the column
9869		 *  @type string
9870		 *  @default null
9871		 */
9872		"sWidth": null,
9873	
9874		/**
9875		 * Width of the column when it was first "encountered"
9876		 *  @type string
9877		 *  @default null
9878		 */
9879		"sWidthOrig": null
9880	};
9881	
9882	
9883	/*
9884	 * Developer note: The properties of the object below are given in Hungarian
9885	 * notation, that was used as the interface for DataTables prior to v1.10, however
9886	 * from v1.10 onwards the primary interface is camel case. In order to avoid
9887	 * breaking backwards compatibility utterly with this change, the Hungarian
9888	 * version is still, internally the primary interface, but is is not documented
9889	 * - hence the @name tags in each doc comment. This allows a Javascript function
9890	 * to create a map from Hungarian notation to camel case (going the other direction
9891	 * would require each property to be listed, which would at around 3K to the size
9892	 * of DataTables, while this method is about a 0.5K hit
vendor: 57,087 bytes, lines 9892-11668
9892.
9893	 *
9894	 * Ultimately this does pave the way for Hungarian notation to be dropped
9895	 * completely, but that is a massive amount of work and will break current
9896	 * installs (therefore is on-hold until v2).
9897	 */
9898	
9899	/**
9900	 * Initialisation options that can be given to DataTables at initialisation
9901	 * time.
9902	 *  @namespace
9903	 */
9904	DataTable.defaults = {
9905		/**
9906		 * An array of data to use for the table, passed in at initialisation which
9907		 * will be used in preference to any data which is already in the DOM. This is
9908		 * particularly useful for constructing tables purely in Javascript, for
9909		 * example with a custom Ajax call.
9910		 *  @type array
9911		 *  @default null
9912		 *
9913		 *  @dtopt Option
9914		 *  @name DataTable.defaults.data
9915		 *
9916		 *  @example
9917		 *    // Using a 2D array data source
9918		 *    $(document).ready( function () {
9919		 *      $('#example').dataTable( {
9920		 *        "data": [
9921		 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9922		 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9923		 *        ],
9924		 *        "columns": [
9925		 *          { "title": "Engine" },
9926		 *          { "title": "Browser" },
9927		 *          { "title": "Platform" },
9928		 *          { "title": "Version" },
9929		 *          { "title": "Grade" }
9930		 *        ]
9931		 *      } );
9932		 *    } );
9933		 *
9934		 *  @example
9935		 *    // Using an array of objects as a data source (`data`)
9936		 *    $(document).ready( function () {
9937		 *      $('#example').dataTable( {
9938		 *        "data": [
9939		 *          {
9940		 *            "engine":   "Trident",
9941		 *            "browser":  "Internet Explorer 4.0",
9942		 *            "platform": "Win 95+",
9943		 *            "version":  4,
9944		 *            "grade":    "X"
9945		 *          },
9946		 *          {
9947		 *            "engine":   "Trident",
9948		 *            "browser":  "Internet Explorer 5.0",
9949		 *            "platform": "Win 95+",
9950		 *            "version":  5,
9951		 *            "grade":    "C"
9952		 *          }
9953		 *        ],
9954		 *        "columns": [
9955		 *          { "title": "Engine",   "data": "engine" },
9956		 *          { "title": "Browser",  "data": "browser" },
9957		 *          { "title": "Platform", "data": "platform" },
9958		 *          { "title": "Version",  "data": "version" },
9959		 *          { "title": "Grade",    "data": "grade" }
9960		 *        ]
9961		 *      } );
9962		 *    } );
9963		 */
9964		"aaData": null,
9965	
9966	
9967		/**
9968		 * If ordering is enabled, then DataTables will perform a first pass sort on
9969		 * initialisation. You can define which column(s) the sort is performed
9970		 * upon, and the sorting direction, with this variable. The `sorting` array
9971		 * should contain an array for each column to be sorted initially containing
9972		 * the column's index and a direction string ('asc' or 'desc').
9973		 *  @type array
9974		 *  @default [[0,'asc']]
9975		 *
9976		 *  @dtopt Option
9977		 *  @name DataTable.defaults.order
9978		 *
9979		 *  @example
9980		 *    // Sort by 3rd column first, and then 4th column
9981		 *    $(document).ready( function() {
9982		 *      $('#example').dataTable( {
9983		 *        "order": [[2,'asc'], [3,'desc']]
9984		 *      } );
9985		 *    } );
9986		 *
9987		 *    // No initial sorting
9988		 *    $(document).ready( function() {
9989		 *      $('#example').dataTable( {
9990		 *        "order": []
9991		 *      } );
9992		 *    } );
9993		 */
9994		"aaSorting": [[0,'asc']],
9995	
9996	
9997		/**
9998		 * This parameter is basically identical to the `sorting` parameter, but
9999		 * cannot be overridden by user interaction with the table. What this means
10000		 * is that you could have a column (visible or hidden) which the sorting
10001		 * will always be forced on first - any sorting after that (from the user)
10002		 * will then be performed as required. This can be useful for grouping rows
10003		 * together.
10004		 *  @type array
10005		 *  @default null
10006		 *
10007		 *  @dtopt Option
10008		 *  @name DataTable.defaults.orderFixed
10009		 *
10010		 *  @example
10011		 *    $(document).ready( function() {
10012		 *      $('#example').dataTable( {
10013		 *        "orderFixed": [[0,'asc']]
10014		 *      } );
10015		 *    } )
10016		 */
10017		"aaSortingFixed": [],
10018	
10019	
10020		/**
10021		 * DataTables can be instructed to load data to display in the table from a
10022		 * Ajax source. This option defines how that Ajax call is made and where to.
10023		 *
10024		 * The `ajax` property has three different modes of operation, depending on
10025		 * how it is defined. These are:
10026		 *
10027		 * * `string` - Set the URL from where the data should be loaded from.
10028		 * * `object` - Define properties for `jQuery.ajax`.
10029		 * * `function` - Custom data get function
10030		 *
10031		 * `string`
10032		 * --------
10033		 *
10034		 * As a string, the `ajax` property simply defines the URL from which
10035		 * DataTables will load data.
10036		 *
10037		 * `object`
10038		 * --------
10039		 *
10040		 * As an object, the parameters in the object are passed to
10041		 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10042		 * of the Ajax request. DataTables has a number of default parameters which
10043		 * you can override using this option. Please refer to the jQuery
10044		 * documentation for a full description of the options available, although
10045		 * the following parameters provide additional options in DataTables or
10046		 * require special consideration:
10047		 *
10048		 * * `data` - As with jQuery, `data` can be provided as an object, but it
10049		 *   can also be used as a function to manipulate the data DataTables sends
10050		 *   to the server. The function takes a single parameter, an object of
10051		 *   parameters with the values that DataTables has readied for sending. An
10052		 *   object may be returned which will be merged into the DataTables
10053		 *   defaults, or you can add the items to the object that was passed in and
10054		 *   not return anything from the function. This supersedes `fnServerParams`
10055		 *   from DataTables 1.9-.
10056		 *
10057		 * * `dataSrc` - By default DataTables will look for the property `data` (or
10058		 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10059		 *   from an Ajax source or for server-side processing - this parameter
10060		 *   allows that property to be changed. You can use Javascript dotted
10061		 *   object notation to get a data source for multiple levels of nesting, or
10062		 *   it my be used as a function. As a function it takes a single parameter,
10063		 *   the JSON returned from the server, which can be manipulated as
10064		 *   required, with the returned value being that used by DataTables as the
10065		 *   data source for the table. This supersedes `sAjaxDataProp` from
10066		 *   DataTables 1.9-.
10067		 *
10068		 * * `success` - Should not be overridden it is used internally in
10069		 *   DataTables. To manipulate / transform the data returned by the server
10070		 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10071		 *
10072		 * `function`
10073		 * ----------
10074		 *
10075		 * As a function, making the Ajax call is left up to yourself allowing
10076		 * complete control of the Ajax request. Indeed, if desired, a method other
10077		 * than Ajax could be used to obtain the required data, such as Web storage
10078		 * or an AIR database.
10079		 *
10080		 * The function is given four parameters and no return is required. The
10081		 * parameters are:
10082		 *
10083		 * 1. _object_ - Data to send to the server
10084		 * 2. _function_ - Callback function that must be executed when the required
10085		 *    data has been obtained. That data should be passed into the callback
10086		 *    as the only parameter
10087		 * 3. _object_ - DataTables settings object for the table
10088		 *
10089		 * Note that this supersedes `fnServerData` from DataTables 1.9-.
10090		 *
10091		 *  @type string|object|function
10092		 *  @default null
10093		 *
10094		 *  @dtopt Option
10095		 *  @name DataTable.defaults.ajax
10096		 *  @since 1.10.0
10097		 *
10098		 * @example
10099		 *   // Get JSON data from a file via Ajax.
10100		 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10101		 *   $('#example').dataTable( {
10102		 *     "ajax": "data.json"
10103		 *   } );
10104		 *
10105		 * @example
10106		 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10107		 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10108		 *   $('#example').dataTable( {
10109		 *     "ajax": {
10110		 *       "url": "data.json",
10111		 *       "dataSrc": "tableData"
10112		 *     }
10113		 *   } );
10114		 *
10115		 * @example
10116		 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10117		 *   // from a plain array rather than an array in an object
10118		 *   $('#example').dataTable( {
10119		 *     "ajax": {
10120		 *       "url": "data.json",
10121		 *       "dataSrc": ""
10122		 *     }
10123		 *   } );
10124		 *
10125		 * @example
10126		 *   // Manipulate the data returned from the server - add a link to data
10127		 *   // (note this can, should, be done using `render` for the column - this
10128		 *   // is just a simple example of how the data can be manipulated).
10129		 *   $('#example').dataTable( {
10130		 *     "ajax": {
10131		 *       "url": "data.json",
10132		 *       "dataSrc": function ( json ) {
10133		 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10134		 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10135		 *         }
10136		 *         return json;
10137		 *       }
10138		 *     }
10139		 *   } );
10140		 *
10141		 * @example
10142		 *   // Add data to the request
10143		 *   $('#example').dataTable( {
10144		 *     "ajax": {
10145		 *       "url": "data.json",
10146		 *       "data": function ( d ) {
10147		 *         return {
10148		 *           "extra_search": $('#extra').val()
10149		 *         };
10150		 *       }
10151		 *     }
10152		 *   } );
10153		 *
10154		 * @example
10155		 *   // Send request as POST
10156		 *   $('#example').dataTable( {
10157		 *     "ajax": {
10158		 *       "url": "data.json",
10159		 *       "type": "POST"
10160		 *     }
10161		 *   } );
10162		 *
10163		 * @example
10164		 *   // Get the data from localStorage (could interface with a form for
10165		 *   // adding, editing and removing rows).
10166		 *   $('#example').dataTable( {
10167		 *     "ajax": function (data, callback, settings) {
10168		 *       callback(
10169		 *         JSON.parse( localStorage.getItem('dataTablesData') )
10170		 *       );
10171		 *     }
10172		 *   } );
10173		 */
10174		"ajax": null,
10175	
10176	
10177		/**
10178		 * This parameter allows you to readily specify the entries in the length drop
10179		 * down menu that DataTables shows when pagination is enabled. It can be
10180		 * either a 1D array of options which will be used for both the displayed
10181		 * option and the value, or a 2D array which will use the array in the first
10182		 * position as the value, and the array in the second position as the
10183		 * displayed options (useful for language strings such as 'All').
10184		 *
10185		 * Note that the `pageLength` property will be automatically set to the
10186		 * first value given in this array, unless `pageLength` is also provided.
10187		 *  @type array
10188		 *  @default [ 10, 25, 50, 100 ]
10189		 *
10190		 *  @dtopt Option
10191		 *  @name DataTable.defaults.lengthMenu
10192		 *
10193		 *  @example
10194		 *    $(document).ready( function() {
10195		 *      $('#example').dataTable( {
10196		 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10197		 *      } );
10198		 *    } );
10199		 */
10200		"aLengthMenu": [ 10, 25, 50, 100 ],
10201	
10202	
10203		/**
10204		 * The `columns` option in the initialisation parameter allows you to define
10205		 * details about the way individual columns behave. For a full list of
10206		 * column options that can be set, please see
10207		 * {@link DataTable.defaults.column}. Note that if you use `columns` to
10208		 * define your columns, you must have an entry in the array for every single
10209		 * column that you have in your table (these can be null if you don't which
10210		 * to specify any options).
10211		 *  @member
10212		 *
10213		 *  @name DataTable.defaults.column
10214		 */
10215		"aoColumns": null,
10216	
10217		/**
10218		 * Very similar to `columns`, `columnDefs` allows you to target a specific
10219		 * column, multiple columns, or all columns, using the `targets` property of
10220		 * each object in the array. This allows great flexibility when creating
10221		 * tables, as the `columnDefs` arrays can be of any length, targeting the
10222		 * columns you specifically want. `columnDefs` may use any of the column
10223		 * options available: {@link DataTable.defaults.column}, but it _must_
10224		 * have `targets` defined in each object in the array. Values in the `targets`
10225		 * array may be:
10226		 *   <ul>
10227		 *     <li>a string - class name will be matched on the TH for the column</li>
10228		 *     <li>0 or a positive integer - column index counting from the left</li>
10229		 *     <li>a negative integer - column index counting from the right</li>
10230		 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10231		 *   </ul>
10232		 *  @member
10233		 *
10234		 *  @name DataTable.defaults.columnDefs
10235		 */
10236		"aoColumnDefs": null,
10237	
10238	
10239		/**
10240		 * Basically the same as `search`, this parameter defines the individual column
10241		 * filtering state at initialisation time. The array must be of the same size
10242		 * as the number of columns, and each element be an object with the parameters
10243		 * `search` and `escapeRegex` (the latter is optional). 'null' is also
10244		 * accepted and the default will be used.
10245		 *  @type array
10246		 *  @default []
10247		 *
10248		 *  @dtopt Option
10249		 *  @name DataTable.defaults.searchCols
10250		 *
10251		 *  @example
10252		 *    $(document).ready( function() {
10253		 *      $('#example').dataTable( {
10254		 *        "searchCols": [
10255		 *          null,
10256		 *          { "search": "My filter" },
10257		 *          null,
10258		 *          { "search": "^[0-9]", "escapeRegex": false }
10259		 *        ]
10260		 *      } );
10261		 *    } )
10262		 */
10263		"aoSearchCols": [],
10264	
10265	
10266		/**
10267		 * An array of CSS classes that should be applied to displayed rows. This
10268		 * array may be of any length, and DataTables will apply each class
10269		 * sequentially, looping when required.
10270		 *  @type array
10271		 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10272		 *    options</i>
10273		 *
10274		 *  @dtopt Option
10275		 *  @name DataTable.defaults.stripeClasses
10276		 *
10277		 *  @example
10278		 *    $(document).ready( function() {
10279		 *      $('#example').dataTable( {
10280		 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10281		 *      } );
10282		 *    } )
10283		 */
10284		"asStripeClasses": null,
10285	
10286	
10287		/**
10288		 * Enable or disable automatic column width calculation. This can be disabled
10289		 * as an optimisation (it takes some time to calculate the widths) if the
10290		 * tables widths are passed in using `columns`.
10291		 *  @type boolean
10292		 *  @default true
10293		 *
10294		 *  @dtopt Features
10295		 *  @name DataTable.defaults.autoWidth
10296		 *
10297		 *  @example
10298		 *    $(document).ready( function () {
10299		 *      $('#example').dataTable( {
10300		 *        "autoWidth": false
10301		 *      } );
10302		 *    } );
10303		 */
10304		"bAutoWidth": true,
10305	
10306	
10307		/**
10308		 * Deferred rendering can provide DataTables with a huge speed boost when you
10309		 * are using an Ajax or JS data source for the table. This option, when set to
10310		 * true, will cause DataTables to defer the creation of the table elements for
10311		 * each row until they are needed for a draw - saving a significant amount of
10312		 * time.
10313		 *  @type boolean
10314		 *  @default false
10315		 *
10316		 *  @dtopt Features
10317		 *  @name DataTable.defaults.deferRender
10318		 *
10319		 *  @example
10320		 *    $(document).ready( function() {
10321		 *      $('#example').dataTable( {
10322		 *        "ajax": "sources/arrays.txt",
10323		 *        "deferRender": true
10324		 *      } );
10325		 *    } );
10326		 */
10327		"bDeferRender": false,
10328	
10329	
10330		/**
10331		 * Replace a DataTable which matches the given selector and replace it with
10332		 * one which has the properties of the new initialisation object passed. If no
10333		 * table matches the selector, then the new DataTable will be constructed as
10334		 * per normal.
10335		 *  @type boolean
10336		 *  @default false
10337		 *
10338		 *  @dtopt Options
10339		 *  @name DataTable.defaults.destroy
10340		 *
10341		 *  @example
10342		 *    $(document).ready( function() {
10343		 *      $('#example').dataTable( {
10344		 *        "srollY": "200px",
10345		 *        "paginate": false
10346		 *      } );
10347		 *
10348		 *      // Some time later....
10349		 *      $('#example').dataTable( {
10350		 *        "filter": false,
10351		 *        "destroy": true
10352		 *      } );
10353		 *    } );
10354		 */
10355		"bDestroy": false,
10356	
10357	
10358		/**
10359		 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10360		 * that it allows the end user to input multiple words (space separated) and
10361		 * will match a row containing those words, even if not in the order that was
10362		 * specified (this allow matching across multiple columns). Note that if you
10363		 * wish to use filtering in DataTables this must remain 'true' - to remove the
10364		 * default filtering input box and retain filtering abilities, please use
10365		 * {@link DataTable.defaults.dom}.
10366		 *  @type boolean
10367		 *  @default true
10368		 *
10369		 *  @dtopt Features
10370		 *  @name DataTable.defaults.searching
10371		 *
10372		 *  @example
10373		 *    $(document).ready( function () {
10374		 *      $('#example').dataTable( {
10375		 *        "searching": false
10376		 *      } );
10377		 *    } );
10378		 */
10379		"bFilter": true,
10380	
10381	
10382		/**
10383		 * Enable or disable the table information display. This shows information
10384		 * about the data that is currently visible on the page, including information
10385		 * about filtered data if that action is being performed.
10386		 *  @type boolean
10387		 *  @default true
10388		 *
10389		 *  @dtopt Features
10390		 *  @name DataTable.defaults.info
10391		 *
10392		 *  @example
10393		 *    $(document).ready( function () {
10394		 *      $('#example').dataTable( {
10395		 *        "info": false
10396		 *      } );
10397		 *    } );
10398		 */
10399		"bInfo": true,
10400	
10401	
10402		/**
10403		 * Allows the end user to select the size of a formatted page from a select
10404		 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10405		 *  @type boolean
10406		 *  @default true
10407		 *
10408		 *  @dtopt Features
10409		 *  @name DataTable.defaults.lengthChange
10410		 *
10411		 *  @example
10412		 *    $(document).ready( function () {
10413		 *      $('#example').dataTable( {
10414		 *        "lengthChange": false
10415		 *      } );
10416		 *    } );
10417		 */
10418		"bLengthChange": true,
10419	
10420	
10421		/**
10422		 * Enable or disable pagination.
10423		 *  @type boolean
10424		 *  @default true
10425		 *
10426		 *  @dtopt Features
10427		 *  @name DataTable.defaults.paging
10428		 *
10429		 *  @example
10430		 *    $(document).ready( function () {
10431		 *      $('#example').dataTable( {
10432		 *        "paging": false
10433		 *      } );
10434		 *    } );
10435		 */
10436		"bPaginate": true,
10437	
10438	
10439		/**
10440		 * Enable or disable the display of a 'processing' indicator when the table is
10441		 * being processed (e.g. a sort). This is particularly useful for tables with
10442		 * large amounts of data where it can take a noticeable amount of time to sort
10443		 * the entries.
10444		 *  @type boolean
10445		 *  @default false
10446		 *
10447		 *  @dtopt Features
10448		 *  @name DataTable.defaults.processing
10449		 *
10450		 *  @example
10451		 *    $(document).ready( function () {
10452		 *      $('#example').dataTable( {
10453		 *        "processing": true
10454		 *      } );
10455		 *    } );
10456		 */
10457		"bProcessing": false,
10458	
10459	
10460		/**
10461		 * Retrieve the DataTables object for the given selector. Note that if the
10462		 * table has already been initialised, this parameter will cause DataTables
10463		 * to simply return the object that has already been set up - it will not take
10464		 * account of any changes you might have made to the initialisation object
10465		 * passed to DataTables (setting this parameter to true is an acknowledgement
10466		 * that you understand this). `destroy` can be used to reinitialise a table if
10467		 * you need.
10468		 *  @type boolean
10469		 *  @default false
10470		 *
10471		 *  @dtopt Options
10472		 *  @name DataTable.defaults.retrieve
10473		 *
10474		 *  @example
10475		 *    $(document).ready( function() {
10476		 *      initTable();
10477		 *      tableActions();
10478		 *    } );
10479		 *
10480		 *    function initTable ()
10481		 *    {
10482		 *      return $('#example').dataTable( {
10483		 *        "scrollY": "200px",
10484		 *        "paginate": false,
10485		 *        "retrieve": true
10486		 *      } );
10487		 *    }
10488		 *
10489		 *    function tableActions ()
10490		 *    {
10491		 *      var table = initTable();
10492		 *      // perform API operations with oTable
10493		 *    }
10494		 */
10495		"bRetrieve": false,
10496	
10497	
10498		/**
10499		 * When vertical (y) scrolling is enabled, DataTables will force the height of
10500		 * the table's viewport to the given height at all times (useful for layout).
10501		 * However, this can look odd when filtering data down to a small data set,
10502		 * and the footer is left "floating" further down. This parameter (when
10503		 * enabled) will cause DataTables to collapse the table's viewport down when
10504		 * the result set will fit within the given Y height.
10505		 *  @type boolean
10506		 *  @default false
10507		 *
10508		 *  @dtopt Options
10509		 *  @name DataTable.defaults.scrollCollapse
10510		 *
10511		 *  @example
10512		 *    $(document).ready( function() {
10513		 *      $('#example').dataTable( {
10514		 *        "scrollY": "200",
10515		 *        "scrollCollapse": true
10516		 *      } );
10517		 *    } );
10518		 */
10519		"bScrollCollapse": false,
10520	
10521	
10522		/**
10523		 * Configure DataTables to use server-side processing. Note that the
10524		 * `ajax` parameter must also be given in order to give DataTables a
10525		 * source to obtain the required data for each draw.
10526		 *  @type boolean
10527		 *  @default false
10528		 *
10529		 *  @dtopt Features
10530		 *  @dtopt Server-side
10531		 *  @name DataTable.defaults.serverSide
10532		 *
10533		 *  @example
10534		 *    $(document).ready( function () {
10535		 *      $('#example').dataTable( {
10536		 *        "serverSide": true,
10537		 *        "ajax": "xhr.php"
10538		 *      } );
10539		 *    } );
10540		 */
10541		"bServerSide": false,
10542	
10543	
10544		/**
10545		 * Enable or disable sorting of columns. Sorting of individual columns can be
10546		 * disabled by the `sortable` option for each column.
10547		 *  @type boolean
10548		 *  @default true
10549		 *
10550		 *  @dtopt Features
10551		 *  @name DataTable.defaults.ordering
10552		 *
10553		 *  @example
10554		 *    $(document).ready( function () {
10555		 *      $('#example').dataTable( {
10556		 *        "ordering": false
10557		 *      } );
10558		 *    } );
10559		 */
10560		"bSort": true,
10561	
10562	
10563		/**
10564		 * Enable or display DataTables' ability to sort multiple columns at the
10565		 * same time (activated by shift-click by the user).
10566		 *  @type boolean
10567		 *  @default true
10568		 *
10569		 *  @dtopt Options
10570		 *  @name DataTable.defaults.orderMulti
10571		 *
10572		 *  @example
10573		 *    // Disable multiple column sorting ability
10574		 *    $(document).ready( function () {
10575		 *      $('#example').dataTable( {
10576		 *        "orderMulti": false
10577		 *      } );
10578		 *    } );
10579		 */
10580		"bSortMulti": true,
10581	
10582	
10583		/**
10584		 * Allows control over whether DataTables should use the top (true) unique
10585		 * cell that is found for a single column, or the bottom (false - default).
10586		 * This is useful when using complex headers.
10587		 *  @type boolean
10588		 *  @default false
10589		 *
10590		 *  @dtopt Options
10591		 *  @name DataTable.defaults.orderCellsTop
10592		 *
10593		 *  @example
10594		 *    $(document).ready( function() {
10595		 *      $('#example').dataTable( {
10596		 *        "orderCellsTop": true
10597		 *      } );
10598		 *    } );
10599		 */
10600		"bSortCellsTop": false,
10601	
10602	
10603		/**
10604		 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10605		 * `sorting\_3` to the columns which are currently being sorted on. This is
10606		 * presented as a feature switch as it can increase processing time (while
10607		 * classes are removed and added) so for large data sets you might want to
10608		 * turn this off.
10609		 *  @type boolean
10610		 *  @default true
10611		 *
10612		 *  @dtopt Features
10613		 *  @name DataTable.defaults.orderClasses
10614		 *
10615		 *  @example
10616		 *    $(document).ready( function () {
10617		 *      $('#example').dataTable( {
10618		 *        "orderClasses": false
10619		 *      } );
10620		 *    } );
10621		 */
10622		"bSortClasses": true,
10623	
10624	
10625		/**
10626		 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10627		 * used to save table display information such as pagination information,
10628		 * display length, filtering and sorting. As such when the end user reloads
10629		 * the page the display display will match what thy had previously set up.
10630		 *
10631		 * Due to the use of `localStorage` the default state saving is not supported
10632		 * in IE6 or 7. If state saving is required in those browsers, use
10633		 * `stateSaveCallback` to provide a storage solution such as cookies.
10634		 *  @type boolean
10635		 *  @default false
10636		 *
10637		 *  @dtopt Features
10638		 *  @name DataTable.defaults.stateSave
10639		 *
10640		 *  @example
10641		 *    $(document).ready( function () {
10642		 *      $('#example').dataTable( {
10643		 *        "stateSave": true
10644		 *      } );
10645		 *    } );
10646		 */
10647		"bStateSave": false,
10648	
10649	
10650		/**
10651		 * This function is called when a TR element is created (and all TD child
10652		 * elements have been inserted), or registered if using a DOM source, allowing
10653		 * manipulation of the TR element (adding classes etc).
10654		 *  @type function
10655		 *  @param {node} row "TR" element for the current row
10656		 *  @param {array} data Raw data array for this row
10657		 *  @param {int} dataIndex The index of this row in the internal aoData array
10658		 *
10659		 *  @dtopt Callbacks
10660		 *  @name DataTable.defaults.createdRow
10661		 *
10662		 *  @example
10663		 *    $(document).ready( function() {
10664		 *      $('#example').dataTable( {
10665		 *        "createdRow": function( row, data, dataIndex ) {
10666		 *          // Bold the grade for all 'A' grade browsers
10667		 *          if ( data[4] == "A" )
10668		 *          {
10669		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10670		 *          }
10671		 *        }
10672		 *      } );
10673		 *    } );
10674		 */
10675		"fnCreatedRow": null,
10676	
10677	
10678		/**
10679		 * This function is called on every 'draw' event, and allows you to
10680		 * dynamically modify any aspect you want about the created DOM.
10681		 *  @type function
10682		 *  @param {object} settings DataTables settings object
10683		 *
10684		 *  @dtopt Callbacks
10685		 *  @name DataTable.defaults.drawCallback
10686		 *
10687		 *  @example
10688		 *    $(document).ready( function() {
10689		 *      $('#example').dataTable( {
10690		 *        "drawCallback": function( settings ) {
10691		 *          alert( 'DataTables has redrawn the table' );
10692		 *        }
10693		 *      } );
10694		 *    } );
10695		 */
10696		"fnDrawCallback": null,
10697	
10698	
10699		/**
10700		 * Identical to fnHeaderCallback() but for the table footer this function
10701		 * allows you to modify the table footer on every 'draw' event.
10702		 *  @type function
10703		 *  @param {node} foot "TR" element for the footer
10704		 *  @param {array} data Full table data (as derived from the original HTML)
10705		 *  @param {int} start Index for the current display starting point in the
10706		 *    display array
10707		 *  @param {int} end Index for the current display ending point in the
10708		 *    display array
10709		 *  @param {array int} display Index array to translate the visual position
10710		 *    to the full data array
10711		 *
10712		 *  @dtopt Callbacks
10713		 *  @name DataTable.defaults.footerCallback
10714		 *
10715		 *  @example
10716		 *    $(document).ready( function() {
10717		 *      $('#example').dataTable( {
10718		 *        "footerCallback": function( tfoot, data, start, end, display ) {
10719		 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10720		 *        }
10721		 *      } );
10722		 *    } )
10723		 */
10724		"fnFooterCallback": null,
10725	
10726	
10727		/**
10728		 * When rendering large numbers in the information element for the table
10729		 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10730		 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10731		 * rendered as "1,000,000") to help readability for the end user. This
10732		 * function will override the default method DataTables uses.
10733		 *  @type function
10734		 *  @member
10735		 *  @param {int} toFormat number to be formatted
10736		 *  @returns {string} formatted string for DataTables to show the number
10737		 *
10738		 *  @dtopt Callbacks
10739		 *  @name DataTable.defaults.formatNumber
10740		 *
10741		 *  @example
10742		 *    // Format a number using a single quote for the separator (note that
10743		 *    // this can also be done with the language.thousands option)
10744		 *    $(document).ready( function() {
10745		 *      $('#example').dataTable( {
10746		 *        "formatNumber": function ( toFormat ) {
10747		 *          return toFormat.toString().replace(
10748		 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10749		 *          );
10750		 *        };
10751		 *      } );
10752		 *    } );
10753		 */
10754		"fnFormatNumber": function ( toFormat ) {
10755			return toFormat.toString().replace(
10756				/\B(?=(\d{3})+(?!\d))/g,
10757				this.oLanguage.sThousands
10758			);
10759		},
10760	
10761	
10762		/**
10763		 * This function is called on every 'draw' event, and allows you to
10764		 * dynamically modify the header row. This can be used to calculate and
10765		 * display useful information about the table.
10766		 *  @type function
10767		 *  @param {node} head "TR" element for the header
10768		 *  @param {array} data Full table data (as derived from the original HTML)
10769		 *  @param {int} start Index for the current display starting point in the
10770		 *    display array
10771		 *  @param {int} end Index for the current display ending point in the
10772		 *    display array
10773		 *  @param {array int} display Index array to translate the visual position
10774		 *    to the full data array
10775		 *
10776		 *  @dtopt Callbacks
10777		 *  @name DataTable.defaults.headerCallback
10778		 *
10779		 *  @example
10780		 *    $(document).ready( function() {
10781		 *      $('#example').dataTable( {
10782		 *        "fheaderCallback": function( head, data, start, end, display ) {
10783		 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10784		 *        }
10785		 *      } );
10786		 *    } )
10787		 */
10788		"fnHeaderCallback": null,
10789	
10790	
10791		/**
10792		 * The information element can be used to convey information about the current
10793		 * state of the table. Although the internationalisation options presented by
10794		 * DataTables are quite capable of dealing with most customisations, there may
10795		 * be times where you wish to customise the string further. This callback
10796		 * allows you to do exactly that.
10797		 *  @type function
10798		 *  @param {object} oSettings DataTables settings object
10799		 *  @param {int} start Starting position in data for the draw
10800		 *  @param {int} end End position in data for the draw
10801		 *  @param {int} max Total number of rows in the table (regardless of
10802		 *    filtering)
10803		 *  @param {int} total Total number of rows in the data set, after filtering
10804		 *  @param {string} pre The string that DataTables has formatted using it's
10805		 *    own rules
10806		 *  @returns {string} The string to be displayed in the information element.
10807		 *
10808		 *  @dtopt Callbacks
10809		 *  @name DataTable.defaults.infoCallback
10810		 *
10811		 *  @example
10812		 *    $('#example').dataTable( {
10813		 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10814		 *        return start +" to "+ end;
10815		 *      }
10816		 *    } );
10817		 */
10818		"fnInfoCallback": null,
10819	
10820	
10821		/**
10822		 * Called when the table has been initialised. Normally DataTables will
10823		 * initialise sequentially and there will be no need for this function,
10824		 * however, this does not hold true when using external language information
10825		 * since that is obtained using an async XHR call.
10826		 *  @type function
10827		 *  @param {object} settings DataTables settings object
10828		 *  @param {object} json The JSON object request from the server - only
10829		 *    present if client-side Ajax sourced data is used
10830		 *
10831		 *  @dtopt Callbacks
10832		 *  @name DataTable.defaults.initComplete
10833		 *
10834		 *  @example
10835		 *    $(document).ready( function() {
10836		 *      $('#example').dataTable( {
10837		 *        "initComplete": function(settings, json) {
10838		 *          alert( 'DataTables has finished its initialisation.' );
10839		 *        }
10840		 *      } );
10841		 *    } )
10842		 */
10843		"fnInitComplete": null,
10844	
10845	
10846		/**
10847		 * Called at the very start of each table draw and can be used to cancel the
10848		 * draw by returning false, any other return (including undefined) results in
10849		 * the full draw occurring).
10850		 *  @type function
10851		 *  @param {object} settings DataTables settings object
10852		 *  @returns {boolean} False will cancel the draw, anything else (including no
10853		 *    return) will allow it to complete.
10854		 *
10855		 *  @dtopt Callbacks
10856		 *  @name DataTable.defaults.preDrawCallback
10857		 *
10858		 *  @example
10859		 *    $(document).ready( function() {
10860		 *      $('#example').dataTable( {
10861		 *        "preDrawCallback": function( settings ) {
10862		 *          if ( $('#test').val() == 1 ) {
10863		 *            return false;
10864		 *          }
10865		 *        }
10866		 *      } );
10867		 *    } );
10868		 */
10869		"fnPreDrawCallback": null,
10870	
10871	
10872		/**
10873		 * This function allows you to 'post process' each row after it have been
10874		 * generated for each table draw, but before it is rendered on screen. This
10875		 * function might be used for setting the row class name etc.
10876		 *  @type function
10877		 *  @param {node} row "TR" element for the current row
10878		 *  @param {array} data Raw data array for this row
10879		 *  @param {int} displayIndex The display index for the current table draw
10880		 *  @param {int} displayIndexFull The index of the data in the full list of
10881		 *    rows (after filtering)
10882		 *
10883		 *  @dtopt Callbacks
10884		 *  @name DataTable.defaults.rowCallback
10885		 *
10886		 *  @example
10887		 *    $(document).ready( function() {
10888		 *      $('#example').dataTable( {
10889		 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10890		 *          // Bold the grade for all 'A' grade browsers
10891		 *          if ( data[4] == "A" ) {
10892		 *            $('td:eq(4)', row).html( '<b>A</b>' );
10893		 *          }
10894		 *        }
10895		 *      } );
10896		 *    } );
10897		 */
10898		"fnRowCallback": null,
10899	
10900	
10901		/**
10902		 * __Deprecated__ The functionality provided by this parameter has now been
10903		 * superseded by that provided through `ajax`, which should be used instead.
10904		 *
10905		 * This parameter allows you to override the default function which obtains
10906		 * the data from the server so something more suitable for your application.
10907		 * For example you could use POST data, or pull information from a Gears or
10908		 * AIR database.
10909		 *  @type function
10910		 *  @member
10911		 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10912		 *  @param {array} data A key/value pair object containing the data to send
10913		 *    to the server
10914		 *  @param {function} callback to be called on completion of the data get
10915		 *    process that will draw the data on the page.
10916		 *  @param {object} settings DataTables settings object
10917		 *
10918		 *  @dtopt Callbacks
10919		 *  @dtopt Server-side
10920		 *  @name DataTable.defaults.serverData
10921		 *
10922		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10923		 */
10924		"fnServerData": null,
10925	
10926	
10927		/**
10928		 * __Deprecated__ The functionality provided by this parameter has now been
10929		 * superseded by that provided through `ajax`, which should be used instead.
10930		 *
10931		 *  It is often useful to send extra data to the server when making an Ajax
10932		 * request - for example custom filtering information, and this callback
10933		 * function makes it trivial to send extra information to the server. The
10934		 * passed in parameter is the data set that has been constructed by
10935		 * DataTables, and you can add to this or modify it as you require.
10936		 *  @type function
10937		 *  @param {array} data Data array (array of objects which are name/value
10938		 *    pairs) that has been constructed by DataTables and will be sent to the
10939		 *    server. In the case of Ajax sourced data with server-side processing
10940		 *    this will be an empty array, for server-side processing there will be a
10941		 *    significant number of parameters!
10942		 *  @returns {undefined} Ensure that you modify the data array passed in,
10943		 *    as this is passed by reference.
10944		 *
10945		 *  @dtopt Callbacks
10946		 *  @dtopt Server-side
10947		 *  @name DataTable.defaults.serverParams
10948		 *
10949		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10950		 */
10951		"fnServerParams": null,
10952	
10953	
10954		/**
10955		 * Load the table state. With this function you can define from where, and how, the
10956		 * state of a table is loaded. By default DataTables will load from `localStorage`
10957		 * but you might wish to use a server-side database or cookies.
10958		 *  @type function
10959		 *  @member
10960		 *  @param {object} settings DataTables settings object
10961		 *  @param {object} callback Callback that can be executed when done. It
10962		 *    should be passed the loaded state object.
10963		 *  @return {object} The DataTables state object to be loaded
10964		 *
10965		 *  @dtopt Callbacks
10966		 *  @name DataTable.defaults.stateLoadCallback
10967		 *
10968		 *  @example
10969		 *    $(document).ready( function() {
10970		 *      $('#example').dataTable( {
10971		 *        "stateSave": true,
10972		 *        "stateLoadCallback": function (settings, callback) {
10973		 *          $.ajax( {
10974		 *            "url": "/state_load",
10975		 *            "dataType": "json",
10976		 *            "success": function (json) {
10977		 *              callback( json );
10978		 *            }
10979		 *          } );
10980		 *        }
10981		 *      } );
10982		 *    } );
10983		 */
10984		"fnStateLoadCallback": function ( settings ) {
10985			try {
10986				return JSON.parse(
10987					(settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10988						'DataTables_'+settings.sInstance+'_'+location.pathname
10989					)
10990				);
10991			} catch (e) {}
10992		},
10993	
10994	
10995		/**
10996		 * Callback which allows modification of the saved state prior to loading that state.
10997		 * This callback is called when the table is loading state from the stored data, but
10998		 * prior to the settings object being modified by the saved state. Note that for
10999		 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
11000		 * a plug-in.
11001		 *  @type function
11002		 *  @param {object} settings DataTables settings object
11003		 *  @param {object} data The state object that is to be loaded
11004		 *
11005		 *  @dtopt Callbacks
11006		 *  @name DataTable.defaults.stateLoadParams
11007		 *
11008		 *  @example
11009		 *    // Remove a saved filter, so filtering is never loaded
11010		 *    $(document).ready( function() {
11011		 *      $('#example').dataTable( {
11012		 *        "stateSave": true,
11013		 *        "stateLoadParams": function (settings, data) {
11014		 *          data.oSearch.sSearch = "";
11015		 *        }
11016		 *      } );
11017		 *    } );
11018		 *
11019		 *  @example
11020		 *    // Disallow state loading by returning false
11021		 *    $(document).ready( function() {
11022		 *      $('#example').dataTable( {
11023		 *        "stateSave": true,
11024		 *        "stateLoadParams": function (settings, data) {
11025		 *          return false;
11026		 *        }
11027		 *      } );
11028		 *    } );
11029		 */
11030		"fnStateLoadParams": null,
11031	
11032	
11033		/**
11034		 * Callback that is called when the state has been loaded from the state saving method
11035		 * and the DataTables settings object has been modified as a result of the loaded state.
11036		 *  @type function
11037		 *  @param {object} settings DataTables settings object
11038		 *  @param {object} data The state object that was loaded
11039		 *
11040		 *  @dtopt Callbacks
11041		 *  @name DataTable.defaults.stateLoaded
11042		 *
11043		 *  @example
11044		 *    // Show an alert with the filtering value that was saved
11045		 *    $(document).ready( function() {
11046		 *      $('#example').dataTable( {
11047		 *        "stateSave": true,
11048		 *        "stateLoaded": function (settings, data) {
11049		 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11050		 *        }
11051		 *      } );
11052		 *    } );
11053		 */
11054		"fnStateLoaded": null,
11055	
11056	
11057		/**
11058		 * Save the table state. This function allows you to define where and how the state
11059		 * information for the table is stored By default DataTables will use `localStorage`
11060		 * but you might wish to use a server-side database or cookies.
11061		 *  @type function
11062		 *  @member
11063		 *  @param {object} settings DataTables settings object
11064		 *  @param {object} data The state object to be saved
11065		 *
11066		 *  @dtopt Callbacks
11067		 *  @name DataTable.defaults.stateSaveCallback
11068		 *
11069		 *  @example
11070		 *    $(document).ready( function() {
11071		 *      $('#example').dataTable( {
11072		 *        "stateSave": true,
11073		 *        "stateSaveCallback": function (settings, data) {
11074		 *          // Send an Ajax request to the server with the state object
11075		 *          $.ajax( {
11076		 *            "url": "/state_save",
11077		 *            "data": data,
11078		 *            "dataType": "json",
11079		 *            "method": "POST"
11080		 *            "success": function () {}
11081		 *          } );
11082		 *        }
11083		 *      } );
11084		 *    } );
11085		 */
11086		"fnStateSaveCallback": function ( settings, data ) {
11087			try {
11088				(settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11089					'DataTables_'+settings.sInstance+'_'+location.pathname,
11090					JSON.stringify( data )
11091				);
11092			} catch (e) {}
11093		},
11094	
11095	
11096		/**
11097		 * Callback which allows modification of the state to be saved. Called when the table
11098		 * has changed state a new state save is required. This method allows modification of
11099		 * the state saving object prior to actually doing the save, including addition or
11100		 * other state properties or modification. Note that for plug-in authors, you should
11101		 * use the `stateSaveParams` event to save parameters for a plug-in.
11102		 *  @type function
11103		 *  @param {object} settings DataTables settings object
11104		 *  @param {object} data The state object to be saved
11105		 *
11106		 *  @dtopt Callbacks
11107		 *  @name DataTable.defaults.stateSaveParams
11108		 *
11109		 *  @example
11110		 *    // Remove a saved filter, so filtering is never saved
11111		 *    $(document).ready( function() {
11112		 *      $('#example').dataTable( {
11113		 *        "stateSave": true,
11114		 *        "stateSaveParams": function (settings, data) {
11115		 *          data.oSearch.sSearch = "";
11116		 *        }
11117		 *      } );
11118		 *    } );
11119		 */
11120		"fnStateSaveParams": null,
11121	
11122	
11123		/**
11124		 * Duration for which the saved state information is considered valid. After this period
11125		 * has elapsed the state will be returned to the default.
11126		 * Value is given in seconds.
11127		 *  @type int
11128		 *  @default 7200 <i>(2 hours)</i>
11129		 *
11130		 *  @dtopt Options
11131		 *  @name DataTable.defaults.stateDuration
11132		 *
11133		 *  @example
11134		 *    $(document).ready( function() {
11135		 *      $('#example').dataTable( {
11136		 *        "stateDuration": 60*60*24; // 1 day
11137		 *      } );
11138		 *    } )
11139		 */
11140		"iStateDuration": 7200,
11141	
11142	
11143		/**
11144		 * When enabled DataTables will not make a request to the server for the first
11145		 * page draw - rather it will use the data already on the page (no sorting etc
11146		 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11147		 * is used to indicate that deferred loading is required, but it is also used
11148		 * to tell DataTables how many records there are in the full table (allowing
11149		 * the information element and pagination to be displayed correctly). In the case
11150		 * where a filtering is applied to the table on initial load, this can be
11151		 * indicated by giving the parameter as an array, where the first element is
11152		 * the number of records available after filtering and the second element is the
11153		 * number of records without filtering (allowing the table information element
11154		 * to be shown correctly).
11155		 *  @type int | array
11156		 *  @default null
11157		 *
11158		 *  @dtopt Options
11159		 *  @name DataTable.defaults.deferLoading
11160		 *
11161		 *  @example
11162		 *    // 57 records available in the table, no filtering applied
11163		 *    $(document).ready( function() {
11164		 *      $('#example').dataTable( {
11165		 *        "serverSide": true,
11166		 *        "ajax": "scripts/server_processing.php",
11167		 *        "deferLoading": 57
11168		 *      } );
11169		 *    } );
11170		 *
11171		 *  @example
11172		 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11173		 *    $(document).ready( function() {
11174		 *      $('#example').dataTable( {
11175		 *        "serverSide": true,
11176		 *        "ajax": "scripts/server_processing.php",
11177		 *        "deferLoading": [ 57, 100 ],
11178		 *        "search": {
11179		 *          "search": "my_filter"
11180		 *        }
11181		 *      } );
11182		 *    } );
11183		 */
11184		"iDeferLoading": null,
11185	
11186	
11187		/**
11188		 * Number of rows to display on a single page when using pagination. If
11189		 * feature enabled (`lengthChange`) then the end user will be able to override
11190		 * this to a custom setting using a pop-up menu.
11191		 *  @type int
11192		 *  @default 10
11193		 *
11194		 *  @dtopt Options
11195		 *  @name DataTable.defaults.pageLength
11196		 *
11197		 *  @example
11198		 *    $(document).ready( function() {
11199		 *      $('#example').dataTable( {
11200		 *        "pageLength": 50
11201		 *      } );
11202		 *    } )
11203		 */
11204		"iDisplayLength": 10,
11205	
11206	
11207		/**
11208		 * Define the starting point for data display when using DataTables with
11209		 * pagination. Note that this parameter is the number of records, rather than
11210		 * the page number, so if you have 10 records per page and want to start on
11211		 * the third page, it should be "20".
11212		 *  @type int
11213		 *  @default 0
11214		 *
11215		 *  @dtopt Options
11216		 *  @name DataTable.defaults.displayStart
11217		 *
11218		 *  @example
11219		 *    $(document).ready( function() {
11220		 *      $('#example').dataTable( {
11221		 *        "displayStart": 20
11222		 *      } );
11223		 *    } )
11224		 */
11225		"iDisplayStart": 0,
11226	
11227	
11228		/**
11229		 * By default DataTables allows keyboard navigation of the table (sorting, paging,
11230		 * and filtering) by adding a `tabindex` attribute to the required elements. This
11231		 * allows you to tab through the controls and press the enter key to activate them.
11232		 * The tabindex is default 0, meaning that the tab follows the flow of the document.
11233		 * You can overrule this using this parameter if you wish. Use a value of -1 to
11234		 * disable built-in keyboard navigation.
11235		 *  @type int
11236		 *  @default 0
11237		 *
11238		 *  @dtopt Options
11239		 *  @name DataTable.defaults.tabIndex
11240		 *
11241		 *  @example
11242		 *    $(document).ready( function() {
11243		 *      $('#example').dataTable( {
11244		 *        "tabIndex": 1
11245		 *      } );
11246		 *    } );
11247		 */
11248		"iTabIndex": 0,
11249	
11250	
11251		/**
11252		 * Classes that DataTables assigns to the various components and features
11253		 * that it adds to the HTML table. This allows classes to be configured
11254		 * during initialisation in addition to through the static
11255		 * {@link DataTable.ext.oStdClasses} object).
11256		 *  @namespace
11257		 *  @name DataTable.defaults.classes
11258		 */
11259		"oClasses": {},
11260	
11261	
11262		/**
11263		 * All strings that DataTables uses in the user interface that it creates
11264		 * are defined in this object, allowing you to modified them individually or
11265		 * completely replace them all as required.
11266		 *  @namespace
11267		 *  @name DataTable.defaults.language
11268		 */
11269		"oLanguage": {
11270			/**
11271			 * Strings that are used for WAI-ARIA labels and controls only (these are not
11272			 * actually visible on the page, but will be read by screenreaders, and thus
11273			 * must be internationalised as well).
11274			 *  @namespace
11275			 *  @name DataTable.defaults.language.aria
11276			 */
11277			"oAria": {
11278				/**
11279				 * ARIA label that is added to the table headers when the column may be
11280				 * sorted ascending by activing the column (click or return when focused).
11281				 * Note that the column header is prefixed to this string.
11282				 *  @type string
11283				 *  @default : activate to sort column ascending
11284				 *
11285				 *  @dtopt Language
11286				 *  @name DataTable.defaults.language.aria.sortAscending
11287				 *
11288				 *  @example
11289				 *    $(document).ready( function() {
11290				 *      $('#example').dataTable( {
11291				 *        "language": {
11292				 *          "aria": {
11293				 *            "sortAscending": " - click/return to sort ascending"
11294				 *          }
11295				 *        }
11296				 *      } );
11297				 *    } );
11298				 */
11299				"sSortAscending": ": activate to sort column ascending",
11300	
11301				/**
11302				 * ARIA label that is added to the table headers when the column may be
11303				 * sorted descending by activing the column (click or return when focused).
11304				 * Note that the column header is prefixed to this string.
11305				 *  @type string
11306				 *  @default : activate to sort column ascending
11307				 *
11308				 *  @dtopt Language
11309				 *  @name DataTable.defaults.language.aria.sortDescending
11310				 *
11311				 *  @example
11312				 *    $(document).ready( function() {
11313				 *      $('#example').dataTable( {
11314				 *        "language": {
11315				 *          "aria": {
11316				 *            "sortDescending": " - click/return to sort descending"
11317				 *          }
11318				 *        }
11319				 *      } );
11320				 *    } );
11321				 */
11322				"sSortDescending": ": activate to sort column descending"
11323			},
11324	
11325			/**
11326			 * Pagination string used by DataTables for the built-in pagination
11327			 * control types.
11328			 *  @namespace
11329			 *  @name DataTable.defaults.language.paginate
11330			 */
11331			"oPaginate": {
11332				/**
11333				 * Text to use when using the 'full_numbers' type of pagination for the
11334				 * button to take the user to the first page.
11335				 *  @type string
11336				 *  @default First
11337				 *
11338				 *  @dtopt Language
11339				 *  @name DataTable.defaults.language.paginate.first
11340				 *
11341				 *  @example
11342				 *    $(document).ready( function() {
11343				 *      $('#example').dataTable( {
11344				 *        "language": {
11345				 *          "paginate": {
11346				 *            "first": "First page"
11347				 *          }
11348				 *        }
11349				 *      } );
11350				 *    } );
11351				 */
11352				"sFirst": "First",
11353	
11354	
11355				/**
11356				 * Text to use when using the 'full_numbers' type of pagination for the
11357				 * button to take the user to the last page.
11358				 *  @type string
11359				 *  @default Last
11360				 *
11361				 *  @dtopt Language
11362				 *  @name DataTable.defaults.language.paginate.last
11363				 *
11364				 *  @example
11365				 *    $(document).ready( function() {
11366				 *      $('#example').dataTable( {
11367				 *        "language": {
11368				 *          "paginate": {
11369				 *            "last": "Last page"
11370				 *          }
11371				 *        }
11372				 *      } );
11373				 *    } );
11374				 */
11375				"sLast": "Last",
11376	
11377	
11378				/**
11379				 * Text to use for the 'next' pagination button (to take the user to the
11380				 * next page).
11381				 *  @type string
11382				 *  @default Next
11383				 *
11384				 *  @dtopt Language
11385				 *  @name DataTable.defaults.language.paginate.next
11386				 *
11387				 *  @example
11388				 *    $(document).ready( function() {
11389				 *      $('#example').dataTable( {
11390				 *        "language": {
11391				 *          "paginate": {
11392				 *            "next": "Next page"
11393				 *          }
11394				 *        }
11395				 *      } );
11396				 *    } );
11397				 */
11398				"sNext": "Next",
11399	
11400	
11401				/**
11402				 * Text to use for the 'previous' pagination button (to take the user to
11403				 * the previous page).
11404				 *  @type string
11405				 *  @default Previous
11406				 *
11407				 *  @dtopt Language
11408				 *  @name DataTable.defaults.language.paginate.previous
11409				 *
11410				 *  @example
11411				 *    $(document).ready( function() {
11412				 *      $('#example').dataTable( {
11413				 *        "language": {
11414				 *          "paginate": {
11415				 *            "previous": "Previous page"
11416				 *          }
11417				 *        }
11418				 *      } );
11419				 *    } );
11420				 */
11421				"sPrevious": "Previous"
11422			},
11423	
11424			/**
11425			 * This string is shown in preference to `zeroRecords` when the table is
11426			 * empty of data (regardless of filtering). Note that this is an optional
11427			 * parameter - if it is not given, the value of `zeroRecords` will be used
11428			 * instead (either the default or given value).
11429			 *  @type string
11430			 *  @default No data available in table
11431			 *
11432			 *  @dtopt Language
11433			 *  @name DataTable.defaults.language.emptyTable
11434			 *
11435			 *  @example
11436			 *    $(document).ready( function() {
11437			 *      $('#example').dataTable( {
11438			 *        "language": {
11439			 *          "emptyTable": "No data available in table"
11440			 *        }
11441			 *      } );
11442			 *    } );
11443			 */
11444			"sEmptyTable": "No data available in table",
11445	
11446	
11447			/**
11448			 * This string gives information to the end user about the information
11449			 * that is current on display on the page. The following tokens can be
11450			 * used in the string and will be dynamically replaced as the table
11451			 * display updates. This tokens can be placed anywhere in the string, or
11452			 * removed as needed by the language requires:
11453			 *
11454			 * * `\_START\_` - Display index of the first record on the current page
11455			 * * `\_END\_` - Display index of the last record on the current page
11456			 * * `\_TOTAL\_` - Number of records in the table after filtering
11457			 * * `\_MAX\_` - Number of records in the table without filtering
11458			 * * `\_PAGE\_` - Current page number
11459			 * * `\_PAGES\_` - Total number of pages of data in the table
11460			 *
11461			 *  @type string
11462			 *  @default Showing _START_ to _END_ of _TOTAL_ entries
11463			 *
11464			 *  @dtopt Language
11465			 *  @name DataTable.defaults.language.info
11466			 *
11467			 *  @example
11468			 *    $(document).ready( function() {
11469			 *      $('#example').dataTable( {
11470			 *        "language": {
11471			 *          "info": "Showing page _PAGE_ of _PAGES_"
11472			 *        }
11473			 *      } );
11474			 *    } );
11475			 */
11476			"sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11477	
11478	
11479			/**
11480			 * Display information string for when the table is empty. Typically the
11481			 * format of this string should match `info`.
11482			 *  @type string
11483			 *  @default Showing 0 to 0 of 0 entries
11484			 *
11485			 *  @dtopt Language
11486			 *  @name DataTable.defaults.language.infoEmpty
11487			 *
11488			 *  @example
11489			 *    $(document).ready( function() {
11490			 *      $('#example').dataTable( {
11491			 *        "language": {
11492			 *          "infoEmpty": "No entries to show"
11493			 *        }
11494			 *      } );
11495			 *    } );
11496			 */
11497			"sInfoEmpty": "Showing 0 to 0 of 0 entries",
11498	
11499	
11500			/**
11501			 * When a user filters the information in a table, this string is appended
11502			 * to the information (`info`) to give an idea of how strong the filtering
11503			 * is. The variable _MAX_ is dynamically updated.
11504			 *  @type string
11505			 *  @default (filtered from _MAX_ total entries)
11506			 *
11507			 *  @dtopt Language
11508			 *  @name DataTable.defaults.language.infoFiltered
11509			 *
11510			 *  @example
11511			 *    $(document).ready( function() {
11512			 *      $('#example').dataTable( {
11513			 *        "language": {
11514			 *          "infoFiltered": " - filtering from _MAX_ records"
11515			 *        }
11516			 *      } );
11517			 *    } );
11518			 */
11519			"sInfoFiltered": "(filtered from _MAX_ total entries)",
11520	
11521	
11522			/**
11523			 * If can be useful to append extra information to the info string at times,
11524			 * and this variable does exactly that. This information will be appended to
11525			 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11526			 * being used) at all times.
11527			 *  @type string
11528			 *  @default <i>Empty string</i>
11529			 *
11530			 *  @dtopt Language
11531			 *  @name DataTable.defaults.language.infoPostFix
11532			 *
11533			 *  @example
11534			 *    $(document).ready( function() {
11535			 *      $('#example').dataTable( {
11536			 *        "language": {
11537			 *          "infoPostFix": "All records shown are derived from real information."
11538			 *        }
11539			 *      } );
11540			 *    } );
11541			 */
11542			"sInfoPostFix": "",
11543	
11544	
11545			/**
11546			 * This decimal place operator is a little different from the other
11547			 * language options since DataTables doesn't output floating point
11548			 * numbers, so it won't ever use this for display of a number. Rather,
11549			 * what this parameter does is modify the sort methods of the table so
11550			 * that numbers which are in a format which has a character other than
11551			 * a period (`.`) as a decimal place will be sorted numerically.
11552			 *
11553			 * Note that numbers with different decimal places cannot be shown in
11554			 * the same table and still be sortable, the table must be consistent.
11555			 * However, multiple different tables on the page can use different
11556			 * decimal place characters.
11557			 *  @type string
11558			 *  @default 
11559			 *
11560			 *  @dtopt Language
11561			 *  @name DataTable.defaults.language.decimal
11562			 *
11563			 *  @example
11564			 *    $(document).ready( function() {
11565			 *      $('#example').dataTable( {
11566			 *        "language": {
11567			 *          "decimal": ","
11568			 *          "thousands": "."
11569			 *        }
11570			 *      } );
11571			 *    } );
11572			 */
11573			"sDecimal": "",
11574	
11575	
11576			/**
11577			 * DataTables has a build in number formatter (`formatNumber`) which is
11578			 * used to format large numbers that are used in the table information.
11579			 * By default a comma is used, but this can be trivially changed to any
11580			 * character you wish with this parameter.
11581			 *  @type string
11582			 *  @default ,
11583			 *
11584			 *  @dtopt Language
11585			 *  @name DataTable.defaults.language.thousands
11586			 *
11587			 *  @example
11588			 *    $(document).ready( function() {
11589			 *      $('#example').dataTable( {
11590			 *        "language": {
11591			 *          "thousands": "'"
11592			 *        }
11593			 *      } );
11594			 *    } );
11595			 */
11596			"sThousands": ",",
11597	
11598	
11599			/**
11600			 * Detail the action that will be taken when the drop down menu for the
11601			 * pagination length option is changed. The '_MENU_' variable is replaced
11602			 * with a default select list of 10, 25, 50 and 100, and can be replaced
11603			 * with a custom select box if required.
11604			 *  @type string
11605			 *  @default Show _MENU_ entries
11606			 *
11607			 *  @dtopt Language
11608			 *  @name DataTable.defaults.language.lengthMenu
11609			 *
11610			 *  @example
11611			 *    // Language change only
11612			 *    $(document).ready( function() {
11613			 *      $('#example').dataTable( {
11614			 *        "language": {
11615			 *          "lengthMenu": "Display _MENU_ records"
11616			 *        }
11617			 *      } );
11618			 *    } );
11619			 *
11620			 *  @example
11621			 *    // Language and options change
11622			 *    $(document).ready( function() {
11623			 *      $('#example').dataTable( {
11624			 *        "language": {
11625			 *          "lengthMenu": 'Display <select>'+
11626			 *            '<option value="10">10</option>'+
11627			 *            '<option value="20">20</option>'+
11628			 *            '<option value="30">30</option>'+
11629			 *            '<option value="40">40</option>'+
11630			 *            '<option value="50">50</option>'+
11631			 *            '<option value="-1">All</option>'+
11632			 *            '</select> records'
11633			 *        }
11634			 *      } );
11635			 *    } );
11636			 */
11637			"sLengthMenu": "Show _MENU_ entries",
11638	
11639	
11640			/**
11641			 * When using Ajax sourced data and during the first draw when DataTables is
11642			 * gathering the data, this message is shown in an empty row in the table to
11643			 * indicate to the end user the the data is being loaded. Note that this
11644			 * parameter is not used when loading data by server-side processing, just
11645			 * Ajax sourced data with client-side processing.
11646			 *  @type string
11647			 *  @default Loading...
11648			 *
11649			 *  @dtopt Language
11650			 *  @name DataTable.defaults.language.loadingRecords
11651			 *
11652			 *  @example
11653			 *    $(document).ready( function() {
11654			 *      $('#example').dataTable( {
11655			 *        "language": {
11656			 *          "loadingRecords": "Please wait - loading..."
11657			 *        }
11658			 *      } );
11659			 *    } );
11660			 */
11661			"sLoadingRecords": "Loading...",
11662	
11663	
11664			/**
11665			 * Text which is displayed when the table is processing a user action
11666			 * (usually a sort command or similar).
11667			 *  @type string
11668			 *
11668  @default Processing...
11669			 *
11670			 *  @dtopt Language
11671			 *  @name DataTable.defaults.language.processing
11672			 *
11673			 *  @example
11674			 *    $(document).ready( function() {
11675			 *      $('#example').dataTable( {
11676			 *        "language": {
11677			 *          "processing": "DataTables is currently busy"
11678			 *        }
11679			 *      } );
11680			 *    } );
11681			 */
11682			"sProcessing": "Processing...
vendor: 24,082 bytes, lines 11682-12411
11682",
11683	
11684	
11685			/**
11686			 * Details the actions that will be taken when the user types into the
11687			 * filtering input text box. The variable "_INPUT_", if used in the string,
11688			 * is replaced with the HTML text box for the filtering input allowing
11689			 * control over where it appears in the string. If "_INPUT_" is not given
11690			 * then the input box is appended to the string automatically.
11691			 *  @type string
11692			 *  @default Search:
11693			 *
11694			 *  @dtopt Language
11695			 *  @name DataTable.defaults.language.search
11696			 *
11697			 *  @example
11698			 *    // Input text box will be appended at the end automatically
11699			 *    $(document).ready( function() {
11700			 *      $('#example').dataTable( {
11701			 *        "language": {
11702			 *          "search": "Filter records:"
11703			 *        }
11704			 *      } );
11705			 *    } );
11706			 *
11707			 *  @example
11708			 *    // Specify where the filter should appear
11709			 *    $(document).ready( function() {
11710			 *      $('#example').dataTable( {
11711			 *        "language": {
11712			 *          "search": "Apply filter _INPUT_ to table"
11713			 *        }
11714			 *      } );
11715			 *    } );
11716			 */
11717			"sSearch": "Search:",
11718	
11719	
11720			/**
11721			 * Assign a `placeholder` attribute to the search `input` element
11722			 *  @type string
11723			 *  @default 
11724			 *
11725			 *  @dtopt Language
11726			 *  @name DataTable.defaults.language.searchPlaceholder
11727			 */
11728			"sSearchPlaceholder": "",
11729	
11730	
11731			/**
11732			 * All of the language information can be stored in a file on the
11733			 * server-side, which DataTables will look up if this parameter is passed.
11734			 * It must store the URL of the language file, which is in a JSON format,
11735			 * and the object has the same properties as the oLanguage object in the
11736			 * initialiser object (i.e. the above parameters). Please refer to one of
11737			 * the example language files to see how this works in action.
11738			 *  @type string
11739			 *  @default <i>Empty string - i.e. disabled</i>
11740			 *
11741			 *  @dtopt Language
11742			 *  @name DataTable.defaults.language.url
11743			 *
11744			 *  @example
11745			 *    $(document).ready( function() {
11746			 *      $('#example').dataTable( {
11747			 *        "language": {
11748			 *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11749			 *        }
11750			 *      } );
11751			 *    } );
11752			 */
11753			"sUrl": "",
11754	
11755	
11756			/**
11757			 * Text shown inside the table records when the is no information to be
11758			 * displayed after filtering. `emptyTable` is shown when there is simply no
11759			 * information in the table at all (regardless of filtering).
11760			 *  @type string
11761			 *  @default No matching records found
11762			 *
11763			 *  @dtopt Language
11764			 *  @name DataTable.defaults.language.zeroRecords
11765			 *
11766			 *  @example
11767			 *    $(document).ready( function() {
11768			 *      $('#example').dataTable( {
11769			 *        "language": {
11770			 *          "zeroRecords": "No records to display"
11771			 *        }
11772			 *      } );
11773			 *    } );
11774			 */
11775			"sZeroRecords": "No matching records found"
11776		},
11777	
11778	
11779		/**
11780		 * This parameter allows you to have define the global filtering state at
11781		 * initialisation time. As an object the `search` parameter must be
11782		 * defined, but all other parameters are optional. When `regex` is true,
11783		 * the search string will be treated as a regular expression, when false
11784		 * (default) it will be treated as a straight string. When `smart`
11785		 * DataTables will use it's smart filtering methods (to word match at
11786		 * any point in the data), when false this will not be done.
11787		 *  @namespace
11788		 *  @extends DataTable.models.oSearch
11789		 *
11790		 *  @dtopt Options
11791		 *  @name DataTable.defaults.search
11792		 *
11793		 *  @example
11794		 *    $(document).ready( function() {
11795		 *      $('#example').dataTable( {
11796		 *        "search": {"search": "Initial search"}
11797		 *      } );
11798		 *    } )
11799		 */
11800		"oSearch": $.extend( {}, DataTable.models.oSearch ),
11801	
11802	
11803		/**
11804		 * __Deprecated__ The functionality provided by this parameter has now been
11805		 * superseded by that provided through `ajax`, which should be used instead.
11806		 *
11807		 * By default DataTables will look for the property `data` (or `aaData` for
11808		 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11809		 * source or for server-side processing - this parameter allows that
11810		 * property to be changed. You can use Javascript dotted object notation to
11811		 * get a data source for multiple levels of nesting.
11812		 *  @type string
11813		 *  @default data
11814		 *
11815		 *  @dtopt Options
11816		 *  @dtopt Server-side
11817		 *  @name DataTable.defaults.ajaxDataProp
11818		 *
11819		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11820		 */
11821		"sAjaxDataProp": "data",
11822	
11823	
11824		/**
11825		 * __Deprecated__ The functionality provided by this parameter has now been
11826		 * superseded by that provided through `ajax`, which should be used instead.
11827		 *
11828		 * You can instruct DataTables to load data from an external
11829		 * source using this parameter (use aData if you want to pass data in you
11830		 * already have). Simply provide a url a JSON object can be obtained from.
11831		 *  @type string
11832		 *  @default null
11833		 *
11834		 *  @dtopt Options
11835		 *  @dtopt Server-side
11836		 *  @name DataTable.defaults.ajaxSource
11837		 *
11838		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11839		 */
11840		"sAjaxSource": null,
11841	
11842	
11843		/**
11844		 * This initialisation variable allows you to specify exactly where in the
11845		 * DOM you want DataTables to inject the various controls it adds to the page
11846		 * (for example you might want the pagination controls at the top of the
11847		 * table). DIV elements (with or without a custom class) can also be added to
11848		 * aid styling. The follow syntax is used:
11849		 *   <ul>
11850		 *     <li>The following options are allowed:
11851		 *       <ul>
11852		 *         <li>'l' - Length changing</li>
11853		 *         <li>'f' - Filtering input</li>
11854		 *         <li>'t' - The table!</li>
11855		 *         <li>'i' - Information</li>
11856		 *         <li>'p' - Pagination</li>
11857		 *         <li>'r' - pRocessing</li>
11858		 *       </ul>
11859		 *     </li>
11860		 *     <li>The following constants are allowed:
11861		 *       <ul>
11862		 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11863		 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11864		 *       </ul>
11865		 *     </li>
11866		 *     <li>The following syntax is expected:
11867		 *       <ul>
11868		 *         <li>'&lt;' and '&gt;' - div elements</li>
11869		 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11870		 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11871		 *       </ul>
11872		 *     </li>
11873		 *     <li>Examples:
11874		 *       <ul>
11875		 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11876		 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11877		 *       </ul>
11878		 *     </li>
11879		 *   </ul>
11880		 *  @type string
11881		 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11882		 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11883		 *
11884		 *  @dtopt Options
11885		 *  @name DataTable.defaults.dom
11886		 *
11887		 *  @example
11888		 *    $(document).ready( function() {
11889		 *      $('#example').dataTable( {
11890		 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11891		 *      } );
11892		 *    } );
11893		 */
11894		"sDom": "lfrtip",
11895	
11896	
11897		/**
11898		 * Search delay option. This will throttle full table searches that use the
11899		 * DataTables provided search input element (it does not effect calls to
11900		 * `dt-api search()`, providing a delay before the search is made.
11901		 *  @type integer
11902		 *  @default 0
11903		 *
11904		 *  @dtopt Options
11905		 *  @name DataTable.defaults.searchDelay
11906		 *
11907		 *  @example
11908		 *    $(document).ready( function() {
11909		 *      $('#example').dataTable( {
11910		 *        "searchDelay": 200
11911		 *      } );
11912		 *    } )
11913		 */
11914		"searchDelay": null,
11915	
11916	
11917		/**
11918		 * DataTables features six different built-in options for the buttons to
11919		 * display for pagination control:
11920		 *
11921		 * * `numbers` - Page number buttons only
11922		 * * `simple` - 'Previous' and 'Next' buttons only
11923		 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11924		 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11925		 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11926		 * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11927		 *  
11928		 * Further methods can be added using {@link DataTable.ext.oPagination}.
11929		 *  @type string
11930		 *  @default simple_numbers
11931		 *
11932		 *  @dtopt Options
11933		 *  @name DataTable.defaults.pagingType
11934		 *
11935		 *  @example
11936		 *    $(document).ready( function() {
11937		 *      $('#example').dataTable( {
11938		 *        "pagingType": "full_numbers"
11939		 *      } );
11940		 *    } )
11941		 */
11942		"sPaginationType": "simple_numbers",
11943	
11944	
11945		/**
11946		 * Enable horizontal scrolling. When a table is too wide to fit into a
11947		 * certain layout, or you have a large number of columns in the table, you
11948		 * can enable x-scrolling to show the table in a viewport, which can be
11949		 * scrolled. This property can be `true` which will allow the table to
11950		 * scroll horizontally when needed, or any CSS unit, or a number (in which
11951		 * case it will be treated as a pixel measurement). Setting as simply `true`
11952		 * is recommended.
11953		 *  @type boolean|string
11954		 *  @default <i>blank string - i.e. disabled</i>
11955		 *
11956		 *  @dtopt Features
11957		 *  @name DataTable.defaults.scrollX
11958		 *
11959		 *  @example
11960		 *    $(document).ready( function() {
11961		 *      $('#example').dataTable( {
11962		 *        "scrollX": true,
11963		 *        "scrollCollapse": true
11964		 *      } );
11965		 *    } );
11966		 */
11967		"sScrollX": "",
11968	
11969	
11970		/**
11971		 * This property can be used to force a DataTable to use more width than it
11972		 * might otherwise do when x-scrolling is enabled. For example if you have a
11973		 * table which requires to be well spaced, this parameter is useful for
11974		 * "over-sizing" the table, and thus forcing scrolling. This property can by
11975		 * any CSS unit, or a number (in which case it will be treated as a pixel
11976		 * measurement).
11977		 *  @type string
11978		 *  @default <i>blank string - i.e. disabled</i>
11979		 *
11980		 *  @dtopt Options
11981		 *  @name DataTable.defaults.scrollXInner
11982		 *
11983		 *  @example
11984		 *    $(document).ready( function() {
11985		 *      $('#example').dataTable( {
11986		 *        "scrollX": "100%",
11987		 *        "scrollXInner": "110%"
11988		 *      } );
11989		 *    } );
11990		 */
11991		"sScrollXInner": "",
11992	
11993	
11994		/**
11995		 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11996		 * to the given height, and enable scrolling for any data which overflows the
11997		 * current viewport. This can be used as an alternative to paging to display
11998		 * a lot of data in a small area (although paging and scrolling can both be
11999		 * enabled at the same time). This property can be any CSS unit, or a number
12000		 * (in which case it will be treated as a pixel measurement).
12001		 *  @type string
12002		 *  @default <i>blank string - i.e. disabled</i>
12003		 *
12004		 *  @dtopt Features
12005		 *  @name DataTable.defaults.scrollY
12006		 *
12007		 *  @example
12008		 *    $(document).ready( function() {
12009		 *      $('#example').dataTable( {
12010		 *        "scrollY": "200px",
12011		 *        "paginate": false
12012		 *      } );
12013		 *    } );
12014		 */
12015		"sScrollY": "",
12016	
12017	
12018		/**
12019		 * __Deprecated__ The functionality provided by this parameter has now been
12020		 * superseded by that provided through `ajax`, which should be used instead.
12021		 *
12022		 * Set the HTTP method that is used to make the Ajax call for server-side
12023		 * processing or Ajax sourced data.
12024		 *  @type string
12025		 *  @default GET
12026		 *
12027		 *  @dtopt Options
12028		 *  @dtopt Server-side
12029		 *  @name DataTable.defaults.serverMethod
12030		 *
12031		 *  @deprecated 1.10. Please use `ajax` for this functionality now.
12032		 */
12033		"sServerMethod": "GET",
12034	
12035	
12036		/**
12037		 * DataTables makes use of renderers when displaying HTML elements for
12038		 * a table. These renderers can be added or modified by plug-ins to
12039		 * generate suitable mark-up for a site. For example the Bootstrap
12040		 * integration plug-in for DataTables uses a paging button renderer to
12041		 * display pagination buttons in the mark-up required by Bootstrap.
12042		 *
12043		 * For further information about the renderers available see
12044		 * DataTable.ext.renderer
12045		 *  @type string|object
12046		 *  @default null
12047		 *
12048		 *  @name DataTable.defaults.renderer
12049		 *
12050		 */
12051		"renderer": null,
12052	
12053	
12054		/**
12055		 * Set the data property name that DataTables should use to get a row's id
12056		 * to set as the `id` property in the node.
12057		 *  @type string
12058		 *  @default DT_RowId
12059		 *
12060		 *  @name DataTable.defaults.rowId
12061		 */
12062		"rowId": "DT_RowId"
12063	};
12064	
12065	_fnHungarianMap( DataTable.defaults );
12066	
12067	
12068	
12069	/*
12070	 * Developer note - See note in model.defaults.js about the use of Hungarian
12071	 * notation and camel case.
12072	 */
12073	
12074	/**
12075	 * Column options that can be given to DataTables at initialisation time.
12076	 *  @namespace
12077	 */
12078	DataTable.defaults.column = {
12079		/**
12080		 * Define which column(s) an order will occur on for this column. This
12081		 * allows a column's ordering to take multiple columns into account when
12082		 * doing a sort or use the data from a different column. For example first
12083		 * name / last name columns make sense to do a multi-column sort over the
12084		 * two columns.
12085		 *  @type array|int
12086		 *  @default null <i>Takes the value of the column index automatically</i>
12087		 *
12088		 *  @name DataTable.defaults.column.orderData
12089		 *  @dtopt Columns
12090		 *
12091		 *  @example
12092		 *    // Using `columnDefs`
12093		 *    $(document).ready( function() {
12094		 *      $('#example').dataTable( {
12095		 *        "columnDefs": [
12096		 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12097		 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12098		 *          { "orderData": 2, "targets": [ 2 ] }
12099		 *        ]
12100		 *      } );
12101		 *    } );
12102		 *
12103		 *  @example
12104		 *    // Using `columns`
12105		 *    $(document).ready( function() {
12106		 *      $('#example').dataTable( {
12107		 *        "columns": [
12108		 *          { "orderData": [ 0, 1 ] },
12109		 *          { "orderData": [ 1, 0 ] },
12110		 *          { "orderData": 2 },
12111		 *          null,
12112		 *          null
12113		 *        ]
12114		 *      } );
12115		 *    } );
12116		 */
12117		"aDataSort": null,
12118		"iDataSort": -1,
12119	
12120	
12121		/**
12122		 * You can control the default ordering direction, and even alter the
12123		 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12124		 * using this parameter.
12125		 *  @type array
12126		 *  @default [ 'asc', 'desc' ]
12127		 *
12128		 *  @name DataTable.defaults.column.orderSequence
12129		 *  @dtopt Columns
12130		 *
12131		 *  @example
12132		 *    // Using `columnDefs`
12133		 *    $(document).ready( function() {
12134		 *      $('#example').dataTable( {
12135		 *        "columnDefs": [
12136		 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12137		 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12138		 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12139		 *        ]
12140		 *      } );
12141		 *    } );
12142		 *
12143		 *  @example
12144		 *    // Using `columns`
12145		 *    $(document).ready( function() {
12146		 *      $('#example').dataTable( {
12147		 *        "columns": [
12148		 *          null,
12149		 *          { "orderSequence": [ "asc" ] },
12150		 *          { "orderSequence": [ "desc", "asc", "asc" ] },
12151		 *          { "orderSequence": [ "desc" ] },
12152		 *          null
12153		 *        ]
12154		 *      } );
12155		 *    } );
12156		 */
12157		"asSorting": [ 'asc', 'desc' ],
12158	
12159	
12160		/**
12161		 * Enable or disable filtering on the data in this column.
12162		 *  @type boolean
12163		 *  @default true
12164		 *
12165		 *  @name DataTable.defaults.column.searchable
12166		 *  @dtopt Columns
12167		 *
12168		 *  @example
12169		 *    // Using `columnDefs`
12170		 *    $(document).ready( function() {
12171		 *      $('#example').dataTable( {
12172		 *        "columnDefs": [
12173		 *          { "searchable": false, "targets": [ 0 ] }
12174		 *        ] } );
12175		 *    } );
12176		 *
12177		 *  @example
12178		 *    // Using `columns`
12179		 *    $(document).ready( function() {
12180		 *      $('#example').dataTable( {
12181		 *        "columns": [
12182		 *          { "searchable": false },
12183		 *          null,
12184		 *          null,
12185		 *          null,
12186		 *          null
12187		 *        ] } );
12188		 *    } );
12189		 */
12190		"bSearchable": true,
12191	
12192	
12193		/**
12194		 * Enable or disable ordering on this column.
12195		 *  @type boolean
12196		 *  @default true
12197		 *
12198		 *  @name DataTable.defaults.column.orderable
12199		 *  @dtopt Columns
12200		 *
12201		 *  @example
12202		 *    // Using `columnDefs`
12203		 *    $(document).ready( function() {
12204		 *      $('#example').dataTable( {
12205		 *        "columnDefs": [
12206		 *          { "orderable": false, "targets": [ 0 ] }
12207		 *        ] } );
12208		 *    } );
12209		 *
12210		 *  @example
12211		 *    // Using `columns`
12212		 *    $(document).ready( function() {
12213		 *      $('#example').dataTable( {
12214		 *        "columns": [
12215		 *          { "orderable": false },
12216		 *          null,
12217		 *          null,
12218		 *          null,
12219		 *          null
12220		 *        ] } );
12221		 *    } );
12222		 */
12223		"bSortable": true,
12224	
12225	
12226		/**
12227		 * Enable or disable the display of this column.
12228		 *  @type boolean
12229		 *  @default true
12230		 *
12231		 *  @name DataTable.defaults.column.visible
12232		 *  @dtopt Columns
12233		 *
12234		 *  @example
12235		 *    // Using `columnDefs`
12236		 *    $(document).ready( function() {
12237		 *      $('#example').dataTable( {
12238		 *        "columnDefs": [
12239		 *          { "visible": false, "targets": [ 0 ] }
12240		 *        ] } );
12241		 *    } );
12242		 *
12243		 *  @example
12244		 *    // Using `columns`
12245		 *    $(document).ready( function() {
12246		 *      $('#example').dataTable( {
12247		 *        "columns": [
12248		 *          { "visible": false },
12249		 *          null,
12250		 *          null,
12251		 *          null,
12252		 *          null
12253		 *        ] } );
12254		 *    } );
12255		 */
12256		"bVisible": true,
12257	
12258	
12259		/**
12260		 * Developer definable function that is called whenever a cell is created (Ajax source,
12261		 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12262		 * allowing you to modify the DOM element (add background colour for example) when the
12263		 * element is available.
12264		 *  @type function
12265		 *  @param {element} td The TD node that has been created
12266		 *  @param {*} cellData The Data for the cell
12267		 *  @param {array|object} rowData The data for the whole row
12268		 *  @param {int} row The row index for the aoData data store
12269		 *  @param {int} col The column index for aoColumns
12270		 *
12271		 *  @name DataTable.defaults.column.createdCell
12272		 *  @dtopt Columns
12273		 *
12274		 *  @example
12275		 *    $(document).ready( function() {
12276		 *      $('#example').dataTable( {
12277		 *        "columnDefs": [ {
12278		 *          "targets": [3],
12279		 *          "createdCell": function (td, cellData, rowData, row, col) {
12280		 *            if ( cellData == "1.7" ) {
12281		 *              $(td).css('color', 'blue')
12282		 *            }
12283		 *          }
12284		 *        } ]
12285		 *      });
12286		 *    } );
12287		 */
12288		"fnCreatedCell": null,
12289	
12290	
12291		/**
12292		 * This parameter has been replaced by `data` in DataTables to ensure naming
12293		 * consistency. `dataProp` can still be used, as there is backwards
12294		 * compatibility in DataTables for this option, but it is strongly
12295		 * recommended that you use `data` in preference to `dataProp`.
12296		 *  @name DataTable.defaults.column.dataProp
12297		 */
12298	
12299	
12300		/**
12301		 * This property can be used to read data from any data source property,
12302		 * including deeply nested objects / properties. `data` can be given in a
12303		 * number of different ways which effect its behaviour:
12304		 *
12305		 * * `integer` - treated as an array index for the data source. This is the
12306		 *   default that DataTables uses (incrementally increased for each column).
12307		 * * `string` - read an object property from the data source. There are
12308		 *   three 'special' options that can be used in the string to alter how
12309		 *   DataTables reads the data from the source object:
12310		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12311		 *      Javascript to read from nested objects, so to can the options
12312		 *      specified in `data`. For example: `browser.version` or
12313		 *      `browser.name`. If your object parameter name contains a period, use
12314		 *      `\\` to escape it - i.e. `first\\.name`.
12315		 *    * `[]` - Array notation. DataTables can automatically combine data
12316		 *      from and array source, joining the data with the characters provided
12317		 *      between the two brackets. For example: `name[, ]` would provide a
12318		 *      comma-space separated list from the source array. If no characters
12319		 *      are provided between the brackets, the original array source is
12320		 *      returned.
12321		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12322		 *      execute a function of the name given. For example: `browser()` for a
12323		 *      simple function on the data source, `browser.version()` for a
12324		 *      function in a nested property or even `browser().version` to get an
12325		 *      object property if the function called returns an object. Note that
12326		 *      function notation is recommended for use in `render` rather than
12327		 *      `data` as it is much simpler to use as a renderer.
12328		 * * `null` - use the original data source for the row rather than plucking
12329		 *   data directly from it. This action has effects on two other
12330		 *   initialisation options:
12331		 *    * `defaultContent` - When null is given as the `data` option and
12332		 *      `defaultContent` is specified for the column, the value defined by
12333		 *      `defaultContent` will be used for the cell.
12334		 *    * `render` - When null is used for the `data` option and the `render`
12335		 *      option is specified for the column, the whole data source for the
12336		 *      row is used for the renderer.
12337		 * * `function` - the function given will be executed whenever DataTables
12338		 *   needs to set or get the data for a cell in the column. The function
12339		 *   takes three parameters:
12340		 *    * Parameters:
12341		 *      * `{array|object}` The data source for the row
12342		 *      * `{string}` The type call data requested - this will be 'set' when
12343		 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12344		 *        when gathering data. Note that when `undefined` is given for the
12345		 *        type DataTables expects to get the raw data for the object back<
12346		 *      * `{*}` Data to set when the second parameter is 'set'.
12347		 *    * Return:
12348		 *      * The return value from the function is not required when 'set' is
12349		 *        the type of call, but otherwise the return is what will be used
12350		 *        for the data requested.
12351		 *
12352		 * Note that `data` is a getter and setter option. If you just require
12353		 * formatting of data for output, you will likely want to use `render` which
12354		 * is simply a getter and thus simpler to use.
12355		 *
12356		 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12357		 * name change reflects the flexibility of this property and is consistent
12358		 * with the naming of mRender. If 'mDataProp' is given, then it will still
12359		 * be used by DataTables, as it automatically maps the old name to the new
12360		 * if required.
12361		 *
12362		 *  @type string|int|function|null
12363		 *  @default null <i>Use automatically calculated column index</i>
12364		 *
12365		 *  @name DataTable.defaults.column.data
12366		 *  @dtopt Columns
12367		 *
12368		 *  @example
12369		 *    // Read table data from objects
12370		 *    // JSON structure for each row:
12371		 *    //   {
12372		 *    //      "engine": {value},
12373		 *    //      "browser": {value},
12374		 *    //      "platform": {value},
12375		 *    //      "version": {value},
12376		 *    //      "grade": {value}
12377		 *    //   }
12378		 *    $(document).ready( function() {
12379		 *      $('#example').dataTable( {
12380		 *        "ajaxSource": "sources/objects.txt",
12381		 *        "columns": [
12382		 *          { "data": "engine" },
12383		 *          { "data": "browser" },
12384		 *          { "data": "platform" },
12385		 *          { "data": "version" },
12386		 *          { "data": "grade" }
12387		 *        ]
12388		 *      } );
12389		 *    } );
12390		 *
12391		 *  @example
12392		 *    // Read information from deeply nested objects
12393		 *    // JSON structure for each row:
12394		 *    //   {
12395		 *    //      "engine": {value},
12396		 *    //      "browser": {value},
12397		 *    //      "platform": {
12398		 *    //         "inner": {value}
12399		 *    //      },
12400		 *    //      "details": [
12401		 *    //         {value}, {value}
12402		 *    //      ]
12403		 *    //   }
12404		 *    $(document).ready( function() {
12405		 *      $('#example').dataTable( {
12406		 *        "ajaxSource": "sources/deep.txt",
12407		 *        "columns": [
12408		 *          { "data": "engine" },
12409		 *          { "data": "browser" },
12410		 *          { "data": "platform.inner" },
12411		 *          { "data": "
12411platform.details.0" },
12412		 *          { "data": "platform.details.1" }
12413		 *        ]
12414		 *      } );
12415		 *    } );
12416		 *
12417		 *  @example
12418		 *    // Using `data` as a function to provide different information for
12419		 *    // sorting, filtering and display. In this case, currency (price)
12420		 *    $(document).ready( function() {
12421		 *      $('#example').dataTable( {
12422		 *        "columnDefs": [ {
12423		 *          "targets": [ 0 ],
12424		 *          "data": function ( source, type, val ) {
12425		 *            if (type === 'set') {
12426		 *              source.price = val;
12427		 *              // Store the computed dis
vendor: 18,284 bytes, lines 12427-12976
12427lay and filter values for efficiency
12428		 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12429		 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12430		 *              return;
12431		 *            }
12432		 *            else if (type === 'display') {
12433		 *              return source.price_display;
12434		 *            }
12435		 *            else if (type === 'filter') {
12436		 *              return source.price_filter;
12437		 *            }
12438		 *            // 'sort', 'type' and undefined all just use the integer
12439		 *            return source.price;
12440		 *          }
12441		 *        } ]
12442		 *      } );
12443		 *    } );
12444		 *
12445		 *  @example
12446		 *    // Using default content
12447		 *    $(document).ready( function() {
12448		 *      $('#example').dataTable( {
12449		 *        "columnDefs": [ {
12450		 *          "targets": [ 0 ],
12451		 *          "data": null,
12452		 *          "defaultContent": "Click to edit"
12453		 *        } ]
12454		 *      } );
12455		 *    } );
12456		 *
12457		 *  @example
12458		 *    // Using array notation - outputting a list from an array
12459		 *    $(document).ready( function() {
12460		 *      $('#example').dataTable( {
12461		 *        "columnDefs": [ {
12462		 *          "targets": [ 0 ],
12463		 *          "data": "name[, ]"
12464		 *        } ]
12465		 *      } );
12466		 *    } );
12467		 *
12468		 */
12469		"mData": null,
12470	
12471	
12472		/**
12473		 * This property is the rendering partner to `data` and it is suggested that
12474		 * when you want to manipulate data for display (including filtering,
12475		 * sorting etc) without altering the underlying data for the table, use this
12476		 * property. `render` can be considered to be the the read only companion to
12477		 * `data` which is read / write (then as such more complex). Like `data`
12478		 * this option can be given in a number of different ways to effect its
12479		 * behaviour:
12480		 *
12481		 * * `integer` - treated as an array index for the data source. This is the
12482		 *   default that DataTables uses (incrementally increased for each column).
12483		 * * `string` - read an object property from the data source. There are
12484		 *   three 'special' options that can be used in the string to alter how
12485		 *   DataTables reads the data from the source object:
12486		 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12487		 *      Javascript to read from nested objects, so to can the options
12488		 *      specified in `data`. For example: `browser.version` or
12489		 *      `browser.name`. If your object parameter name contains a period, use
12490		 *      `\\` to escape it - i.e. `first\\.name`.
12491		 *    * `[]` - Array notation. DataTables can automatically combine data
12492		 *      from and array source, joining the data with the characters provided
12493		 *      between the two brackets. For example: `name[, ]` would provide a
12494		 *      comma-space separated list from the source array. If no characters
12495		 *      are provided between the brackets, the original array source is
12496		 *      returned.
12497		 *    * `()` - Function notation. Adding `()` to the end of a parameter will
12498		 *      execute a function of the name given. For example: `browser()` for a
12499		 *      simple function on the data source, `browser.version()` for a
12500		 *      function in a nested property or even `browser().version` to get an
12501		 *      object property if the function called returns an object.
12502		 * * `object` - use different data for the different data types requested by
12503		 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12504		 *   of the object is the data type the property refers to and the value can
12505		 *   defined using an integer, string or function using the same rules as
12506		 *   `render` normally does. Note that an `_` option _must_ be specified.
12507		 *   This is the default value to use if you haven't specified a value for
12508		 *   the data type requested by DataTables.
12509		 * * `function` - the function given will be executed whenever DataTables
12510		 *   needs to set or get the data for a cell in the column. The function
12511		 *   takes three parameters:
12512		 *    * Parameters:
12513		 *      * {array|object} The data source for the row (based on `data`)
12514		 *      * {string} The type call data requested - this will be 'filter',
12515		 *        'display', 'type' or 'sort'.
12516		 *      * {array|object} The full data source for the row (not based on
12517		 *        `data`)
12518		 *    * Return:
12519		 *      * The return value from the function is what will be used for the
12520		 *        data requested.
12521		 *
12522		 *  @type string|int|function|object|null
12523		 *  @default null Use the data source value.
12524		 *
12525		 *  @name DataTable.defaults.column.render
12526		 *  @dtopt Columns
12527		 *
12528		 *  @example
12529		 *    // Create a comma separated list from an array of objects
12530		 *    $(document).ready( function() {
12531		 *      $('#example').dataTable( {
12532		 *        "ajaxSource": "sources/deep.txt",
12533		 *        "columns": [
12534		 *          { "data": "engine" },
12535		 *          { "data": "browser" },
12536		 *          {
12537		 *            "data": "platform",
12538		 *            "render": "[, ].name"
12539		 *          }
12540		 *        ]
12541		 *      } );
12542		 *    } );
12543		 *
12544		 *  @example
12545		 *    // Execute a function to obtain data
12546		 *    $(document).ready( function() {
12547		 *      $('#example').dataTable( {
12548		 *        "columnDefs": [ {
12549		 *          "targets": [ 0 ],
12550		 *          "data": null, // Use the full data source object for the renderer's source
12551		 *          "render": "browserName()"
12552		 *        } ]
12553		 *      } );
12554		 *    } );
12555		 *
12556		 *  @example
12557		 *    // As an object, extracting different data for the different types
12558		 *    // This would be used with a data source such as:
12559		 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12560		 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12561		 *    // (which has both forms) is used for filtering for if a user inputs either format, while
12562		 *    // the formatted phone number is the one that is shown in the table.
12563		 *    $(document).ready( function() {
12564		 *      $('#example').dataTable( {
12565		 *        "columnDefs": [ {
12566		 *          "targets": [ 0 ],
12567		 *          "data": null, // Use the full data source object for the renderer's source
12568		 *          "render": {
12569		 *            "_": "phone",
12570		 *            "filter": "phone_filter",
12571		 *            "display": "phone_display"
12572		 *          }
12573		 *        } ]
12574		 *      } );
12575		 *    } );
12576		 *
12577		 *  @example
12578		 *    // Use as a function to create a link from the data source
12579		 *    $(document).ready( function() {
12580		 *      $('#example').dataTable( {
12581		 *        "columnDefs": [ {
12582		 *          "targets": [ 0 ],
12583		 *          "data": "download_link",
12584		 *          "render": function ( data, type, full ) {
12585		 *            return '<a href="'+data+'">Download</a>';
12586		 *          }
12587		 *        } ]
12588		 *      } );
12589		 *    } );
12590		 */
12591		"mRender": null,
12592	
12593	
12594		/**
12595		 * Change the cell type created for the column - either TD cells or TH cells. This
12596		 * can be useful as TH cells have semantic meaning in the table body, allowing them
12597		 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12598		 *  @type string
12599		 *  @default td
12600		 *
12601		 *  @name DataTable.defaults.column.cellType
12602		 *  @dtopt Columns
12603		 *
12604		 *  @example
12605		 *    // Make the first column use TH cells
12606		 *    $(document).ready( function() {
12607		 *      $('#example').dataTable( {
12608		 *        "columnDefs": [ {
12609		 *          "targets": [ 0 ],
12610		 *          "cellType": "th"
12611		 *        } ]
12612		 *      } );
12613		 *    } );
12614		 */
12615		"sCellType": "td",
12616	
12617	
12618		/**
12619		 * Class to give to each cell in this column.
12620		 *  @type string
12621		 *  @default <i>Empty string</i>
12622		 *
12623		 *  @name DataTable.defaults.column.class
12624		 *  @dtopt Columns
12625		 *
12626		 *  @example
12627		 *    // Using `columnDefs`
12628		 *    $(document).ready( function() {
12629		 *      $('#example').dataTable( {
12630		 *        "columnDefs": [
12631		 *          { "class": "my_class", "targets": [ 0 ] }
12632		 *        ]
12633		 *      } );
12634		 *    } );
12635		 *
12636		 *  @example
12637		 *    // Using `columns`
12638		 *    $(document).ready( function() {
12639		 *      $('#example').dataTable( {
12640		 *        "columns": [
12641		 *          { "class": "my_class" },
12642		 *          null,
12643		 *          null,
12644		 *          null,
12645		 *          null
12646		 *        ]
12647		 *      } );
12648		 *    } );
12649		 */
12650		"sClass": "",
12651	
12652		/**
12653		 * When DataTables calculates the column widths to assign to each column,
12654		 * it finds the longest string in each column and then constructs a
12655		 * temporary table and reads the widths from that. The problem with this
12656		 * is that "mmm" is much wider then "iiii", but the latter is a longer
12657		 * string - thus the calculation can go wrong (doing it properly and putting
12658		 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12659		 * a "work around" we provide this option. It will append its value to the
12660		 * text that is found to be the longest string for the column - i.e. padding.
12661		 * Generally you shouldn't need this!
12662		 *  @type string
12663		 *  @default <i>Empty string<i>
12664		 *
12665		 *  @name DataTable.defaults.column.contentPadding
12666		 *  @dtopt Columns
12667		 *
12668		 *  @example
12669		 *    // Using `columns`
12670		 *    $(document).ready( function() {
12671		 *      $('#example').dataTable( {
12672		 *        "columns": [
12673		 *          null,
12674		 *          null,
12675		 *          null,
12676		 *          {
12677		 *            "contentPadding": "mmm"
12678		 *          }
12679		 *        ]
12680		 *      } );
12681		 *    } );
12682		 */
12683		"sContentPadding": "",
12684	
12685	
12686		/**
12687		 * Allows a default value to be given for a column's data, and will be used
12688		 * whenever a null data source is encountered (this can be because `data`
12689		 * is set to null, or because the data source itself is null).
12690		 *  @type string
12691		 *  @default null
12692		 *
12693		 *  @name DataTable.defaults.column.defaultContent
12694		 *  @dtopt Columns
12695		 *
12696		 *  @example
12697		 *    // Using `columnDefs`
12698		 *    $(document).ready( function() {
12699		 *      $('#example').dataTable( {
12700		 *        "columnDefs": [
12701		 *          {
12702		 *            "data": null,
12703		 *            "defaultContent": "Edit",
12704		 *            "targets": [ -1 ]
12705		 *          }
12706		 *        ]
12707		 *      } );
12708		 *    } );
12709		 *
12710		 *  @example
12711		 *    // Using `columns`
12712		 *    $(document).ready( function() {
12713		 *      $('#example').dataTable( {
12714		 *        "columns": [
12715		 *          null,
12716		 *          null,
12717		 *          null,
12718		 *          {
12719		 *            "data": null,
12720		 *            "defaultContent": "Edit"
12721		 *          }
12722		 *        ]
12723		 *      } );
12724		 *    } );
12725		 */
12726		"sDefaultContent": null,
12727	
12728	
12729		/**
12730		 * This parameter is only used in DataTables' server-side processing. It can
12731		 * be exceptionally useful to know what columns are being displayed on the
12732		 * client side, and to map these to database fields. When defined, the names
12733		 * also allow DataTables to reorder information from the server if it comes
12734		 * back in an unexpected order (i.e. if you switch your columns around on the
12735		 * client-side, your server-side code does not also need updating).
12736		 *  @type string
12737		 *  @default <i>Empty string</i>
12738		 *
12739		 *  @name DataTable.defaults.column.name
12740		 *  @dtopt Columns
12741		 *
12742		 *  @example
12743		 *    // Using `columnDefs`
12744		 *    $(document).ready( function() {
12745		 *      $('#example').dataTable( {
12746		 *        "columnDefs": [
12747		 *          { "name": "engine", "targets": [ 0 ] },
12748		 *          { "name": "browser", "targets": [ 1 ] },
12749		 *          { "name": "platform", "targets": [ 2 ] },
12750		 *          { "name": "version", "targets": [ 3 ] },
12751		 *          { "name": "grade", "targets": [ 4 ] }
12752		 *        ]
12753		 *      } );
12754		 *    } );
12755		 *
12756		 *  @example
12757		 *    // Using `columns`
12758		 *    $(document).ready( function() {
12759		 *      $('#example').dataTable( {
12760		 *        "columns": [
12761		 *          { "name": "engine" },
12762		 *          { "name": "browser" },
12763		 *          { "name": "platform" },
12764		 *          { "name": "version" },
12765		 *          { "name": "grade" }
12766		 *        ]
12767		 *      } );
12768		 *    } );
12769		 */
12770		"sName": "",
12771	
12772	
12773		/**
12774		 * Defines a data source type for the ordering which can be used to read
12775		 * real-time information from the table (updating the internally cached
12776		 * version) prior to ordering. This allows ordering to occur on user
12777		 * editable elements such as form inputs.
12778		 *  @type string
12779		 *  @default std
12780		 *
12781		 *  @name DataTable.defaults.column.orderDataType
12782		 *  @dtopt Columns
12783		 *
12784		 *  @example
12785		 *    // Using `columnDefs`
12786		 *    $(document).ready( function() {
12787		 *      $('#example').dataTable( {
12788		 *        "columnDefs": [
12789		 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12790		 *          { "type": "numeric", "targets": [ 3 ] },
12791		 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12792		 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12793		 *        ]
12794		 *      } );
12795		 *    } );
12796		 *
12797		 *  @example
12798		 *    // Using `columns`
12799		 *    $(document).ready( function() {
12800		 *      $('#example').dataTable( {
12801		 *        "columns": [
12802		 *          null,
12803		 *          null,
12804		 *          { "orderDataType": "dom-text" },
12805		 *          { "orderDataType": "dom-text", "type": "numeric" },
12806		 *          { "orderDataType": "dom-select" },
12807		 *          { "orderDataType": "dom-checkbox" }
12808		 *        ]
12809		 *      } );
12810		 *    } );
12811		 */
12812		"sSortDataType": "std",
12813	
12814	
12815		/**
12816		 * The title of this column.
12817		 *  @type string
12818		 *  @default null <i>Derived from the 'TH' value for this column in the
12819		 *    original HTML table.</i>
12820		 *
12821		 *  @name DataTable.defaults.column.title
12822		 *  @dtopt Columns
12823		 *
12824		 *  @example
12825		 *    // Using `columnDefs`
12826		 *    $(document).ready( function() {
12827		 *      $('#example').dataTable( {
12828		 *        "columnDefs": [
12829		 *          { "title": "My column title", "targets": [ 0 ] }
12830		 *        ]
12831		 *      } );
12832		 *    } );
12833		 *
12834		 *  @example
12835		 *    // Using `columns`
12836		 *    $(document).ready( function() {
12837		 *      $('#example').dataTable( {
12838		 *        "columns": [
12839		 *          { "title": "My column title" },
12840		 *          null,
12841		 *          null,
12842		 *          null,
12843		 *          null
12844		 *        ]
12845		 *      } );
12846		 *    } );
12847		 */
12848		"sTitle": null,
12849	
12850	
12851		/**
12852		 * The type allows you to specify how the data for this column will be
12853		 * ordered. Four types (string, numeric, date and html (which will strip
12854		 * HTML tags before ordering)) are currently available. Note that only date
12855		 * formats understood by Javascript's Date() object will be accepted as type
12856		 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12857		 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12858		 * through plug-ins.
12859		 *  @type string
12860		 *  @default null <i>Auto-detected from raw data</i>
12861		 *
12862		 *  @name DataTable.defaults.column.type
12863		 *  @dtopt Columns
12864		 *
12865		 *  @example
12866		 *    // Using `columnDefs`
12867		 *    $(document).ready( function() {
12868		 *      $('#example').dataTable( {
12869		 *        "columnDefs": [
12870		 *          { "type": "html", "targets": [ 0 ] }
12871		 *        ]
12872		 *      } );
12873		 *    } );
12874		 *
12875		 *  @example
12876		 *    // Using `columns`
12877		 *    $(document).ready( function() {
12878		 *      $('#example').dataTable( {
12879		 *        "columns": [
12880		 *          { "type": "html" },
12881		 *          null,
12882		 *          null,
12883		 *          null,
12884		 *          null
12885		 *        ]
12886		 *      } );
12887		 *    } );
12888		 */
12889		"sType": null,
12890	
12891	
12892		/**
12893		 * Defining the width of the column, this parameter may take any CSS value
12894		 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12895		 * been given a specific width through this interface ensuring that the table
12896		 * remains readable.
12897		 *  @type string
12898		 *  @default null <i>Automatic</i>
12899		 *
12900		 *  @name DataTable.defaults.column.width
12901		 *  @dtopt Columns
12902		 *
12903		 *  @example
12904		 *    // Using `columnDefs`
12905		 *    $(document).ready( function() {
12906		 *      $('#example').dataTable( {
12907		 *        "columnDefs": [
12908		 *          { "width": "20%", "targets": [ 0 ] }
12909		 *        ]
12910		 *      } );
12911		 *    } );
12912		 *
12913		 *  @example
12914		 *    // Using `columns`
12915		 *    $(document).ready( function() {
12916		 *      $('#example').dataTable( {
12917		 *        "columns": [
12918		 *          { "width": "20%" },
12919		 *          null,
12920		 *          null,
12921		 *          null,
12922		 *          null
12923		 *        ]
12924		 *      } );
12925		 *    } );
12926		 */
12927		"sWidth": null
12928	};
12929	
12930	_fnHungarianMap( DataTable.defaults.column );
12931	
12932	
12933	
12934	/**
12935	 * DataTables settings object - this holds all the information needed for a
12936	 * given table, including configuration, data and current application of the
12937	 * table options. DataTables does not have a single instance for each DataTable
12938	 * with the settings attached to that instance, but rather instances of the
12939	 * DataTable "class" are created on-the-fly as needed (typically by a
12940	 * $().dataTable() call) and the settings object is then applied to that
12941	 * instance.
12942	 *
12943	 * Note that this object is related to {@link DataTable.defaults} but this
12944	 * one is the internal data store for DataTables's cache of columns. It should
12945	 * NOT be manipulated outside of DataTables. Any configuration should be done
12946	 * through the initialisation options.
12947	 *  @namespace
12948	 *  @todo Really should attach the settings object to individual instances so we
12949	 *    don't need to create new instances on each $().dataTable() call (if the
12950	 *    table already exists). It would also save passing oSettings around and
12951	 *    into every single function. However, this is a very significant
12952	 *    architecture change for DataTables and will almost certainly break
12953	 *    backwards compatibility with older installations. This is something that
12954	 *    will be done in 2.0.
12955	 */
12956	DataTable.models.oSettings = {
12957		/**
12958		 * Primary features of DataTables and their enablement state.
12959		 *  @namespace
12960		 */
12961		"oFeatures": {
12962	
12963			/**
12964			 * Flag to say if DataTables should automatically try to calculate the
12965			 * optimum table and columns widths (true) or not (false).
12966			 * Note that this parameter will be set by the initialisation routine. To
12967			 * set a default use {@link DataTable.defaults}.
12968			 *  @type boolean
12969			 */
12970			"bAutoWidth": null,
12971	
12972			/**
12973			 * Delay the creation of TR and TD elements until they are actually
12974			 * needed by a driven page draw. This can give a significant speed
12975			 * increase for Ajax source and Javascript source data, but makes no
12976			 * difference at all f
12976ro
vendor: 14,836 bytes, lines 12976-13553
12976 DOM and server-side processing tables.
12977			 * Note that this parameter will be set by the initialisation routine. To
12978			 * set a default use {@link DataTable.defaults}.
12979			 *  @type boolean
12980			 */
12981			"bDeferRender": null,
12982	
12983			/**
12984			 * Enable filtering on the table or not. Note that if this is disabled
12985			 * then there is no filtering at all on the table, including fnFilter.
12986			 * To just remove the filtering input use sDom and remove the 'f' option.
12987			 * Note that this parameter will be set by the initialisation routine. To
12988			 * set a default use {@link DataTable.defaults}.
12989			 *  @type boolean
12990			 */
12991			"bFilter": null,
12992	
12993			/**
12994			 * Table information element (the 'Showing x of y records' div) enable
12995			 * flag.
12996			 * Note that this parameter will be set by the initialisation routine. To
12997			 * set a default use {@link DataTable.defaults}.
12998			 *  @type boolean
12999			 */
13000			"bInfo": null,
13001	
13002			/**
13003			 * Present a user control allowing the end user to change the page size
13004			 * when pagination is enabled.
13005			 * Note that this parameter will be set by the initialisation routine. To
13006			 * set a default use {@link DataTable.defaults}.
13007			 *  @type boolean
13008			 */
13009			"bLengthChange": null,
13010	
13011			/**
13012			 * Pagination enabled or not. Note that if this is disabled then length
13013			 * changing must also be disabled.
13014			 * Note that this parameter will be set by the initialisation routine. To
13015			 * set a default use {@link DataTable.defaults}.
13016			 *  @type boolean
13017			 */
13018			"bPaginate": null,
13019	
13020			/**
13021			 * Processing indicator enable flag whenever DataTables is enacting a
13022			 * user request - typically an Ajax request for server-side processing.
13023			 * Note that this parameter will be set by the initialisation routine. To
13024			 * set a default use {@link DataTable.defaults}.
13025			 *  @type boolean
13026			 */
13027			"bProcessing": null,
13028	
13029			/**
13030			 * Server-side processing enabled flag - when enabled DataTables will
13031			 * get all data from the server for every draw - there is no filtering,
13032			 * sorting or paging done on the client-side.
13033			 * Note that this parameter will be set by the initialisation routine. To
13034			 * set a default use {@link DataTable.defaults}.
13035			 *  @type boolean
13036			 */
13037			"bServerSide": null,
13038	
13039			/**
13040			 * Sorting enablement flag.
13041			 * Note that this parameter will be set by the initialisation routine. To
13042			 * set a default use {@link DataTable.defaults}.
13043			 *  @type boolean
13044			 */
13045			"bSort": null,
13046	
13047			/**
13048			 * Multi-column sorting
13049			 * Note that this parameter will be set by the initialisation routine. To
13050			 * set a default use {@link DataTable.defaults}.
13051			 *  @type boolean
13052			 */
13053			"bSortMulti": null,
13054	
13055			/**
13056			 * Apply a class to the columns which are being sorted to provide a
13057			 * visual highlight or not. This can slow things down when enabled since
13058			 * there is a lot of DOM interaction.
13059			 * Note that this parameter will be set by the initialisation routine. To
13060			 * set a default use {@link DataTable.defaults}.
13061			 *  @type boolean
13062			 */
13063			"bSortClasses": null,
13064	
13065			/**
13066			 * State saving enablement flag.
13067			 * Note that this parameter will be set by the initialisation routine. To
13068			 * set a default use {@link DataTable.defaults}.
13069			 *  @type boolean
13070			 */
13071			"bStateSave": null
13072		},
13073	
13074	
13075		/**
13076		 * Scrolling settings for a table.
13077		 *  @namespace
13078		 */
13079		"oScroll": {
13080			/**
13081			 * When the table is shorter in height than sScrollY, collapse the
13082			 * table container down to the height of the table (when true).
13083			 * Note that this parameter will be set by the initialisation routine. To
13084			 * set a default use {@link DataTable.defaults}.
13085			 *  @type boolean
13086			 */
13087			"bCollapse": null,
13088	
13089			/**
13090			 * Width of the scrollbar for the web-browser's platform. Calculated
13091			 * during table initialisation.
13092			 *  @type int
13093			 *  @default 0
13094			 */
13095			"iBarWidth": 0,
13096	
13097			/**
13098			 * Viewport width for horizontal scrolling. Horizontal scrolling is
13099			 * disabled if an empty string.
13100			 * Note that this parameter will be set by the initialisation routine. To
13101			 * set a default use {@link DataTable.defaults}.
13102			 *  @type string
13103			 */
13104			"sX": null,
13105	
13106			/**
13107			 * Width to expand the table to when using x-scrolling. Typically you
13108			 * should not need to use this.
13109			 * Note that this parameter will be set by the initialisation routine. To
13110			 * set a default use {@link DataTable.defaults}.
13111			 *  @type string
13112			 *  @deprecated
13113			 */
13114			"sXInner": null,
13115	
13116			/**
13117			 * Viewport height for vertical scrolling. Vertical scrolling is disabled
13118			 * if an empty string.
13119			 * Note that this parameter will be set by the initialisation routine. To
13120			 * set a default use {@link DataTable.defaults}.
13121			 *  @type string
13122			 */
13123			"sY": null
13124		},
13125	
13126		/**
13127		 * Language information for the table.
13128		 *  @namespace
13129		 *  @extends DataTable.defaults.oLanguage
13130		 */
13131		"oLanguage": {
13132			/**
13133			 * Information callback function. See
13134			 * {@link DataTable.defaults.fnInfoCallback}
13135			 *  @type function
13136			 *  @default null
13137			 */
13138			"fnInfoCallback": null
13139		},
13140	
13141		/**
13142		 * Browser support parameters
13143		 *  @namespace
13144		 */
13145		"oBrowser": {
13146			/**
13147			 * Indicate if the browser incorrectly calculates width:100% inside a
13148			 * scrolling element (IE6/7)
13149			 *  @type boolean
13150			 *  @default false
13151			 */
13152			"bScrollOversize": false,
13153	
13154			/**
13155			 * Determine if the vertical scrollbar is on the right or left of the
13156			 * scrolling container - needed for rtl language layout, although not
13157			 * all browsers move the scrollbar (Safari).
13158			 *  @type boolean
13159			 *  @default false
13160			 */
13161			"bScrollbarLeft": false,
13162	
13163			/**
13164			 * Flag for if `getBoundingClientRect` is fully supported or not
13165			 *  @type boolean
13166			 *  @default false
13167			 */
13168			"bBounding": false,
13169	
13170			/**
13171			 * Browser scrollbar width
13172			 *  @type integer
13173			 *  @default 0
13174			 */
13175			"barWidth": 0
13176		},
13177	
13178	
13179		"ajax": null,
13180	
13181	
13182		/**
13183		 * Array referencing the nodes which are used for the features. The
13184		 * parameters of this object match what is allowed by sDom - i.e.
13185		 *   <ul>
13186		 *     <li>'l' - Length changing</li>
13187		 *     <li>'f' - Filtering input</li>
13188		 *     <li>'t' - The table!</li>
13189		 *     <li>'i' - Information</li>
13190		 *     <li>'p' - Pagination</li>
13191		 *     <li>'r' - pRocessing</li>
13192		 *   </ul>
13193		 *  @type array
13194		 *  @default []
13195		 */
13196		"aanFeatures": [],
13197	
13198		/**
13199		 * Store data information - see {@link DataTable.models.oRow} for detailed
13200		 * information.
13201		 *  @type array
13202		 *  @default []
13203		 */
13204		"aoData": [],
13205	
13206		/**
13207		 * Array of indexes which are in the current display (after filtering etc)
13208		 *  @type array
13209		 *  @default []
13210		 */
13211		"aiDisplay": [],
13212	
13213		/**
13214		 * Array of indexes for display - no filtering
13215		 *  @type array
13216		 *  @default []
13217		 */
13218		"aiDisplayMaster": [],
13219	
13220		/**
13221		 * Map of row ids to data indexes
13222		 *  @type object
13223		 *  @default {}
13224		 */
13225		"aIds": {},
13226	
13227		/**
13228		 * Store information about each column that is in use
13229		 *  @type array
13230		 *  @default []
13231		 */
13232		"aoColumns": [],
13233	
13234		/**
13235		 * Store information about the table's header
13236		 *  @type array
13237		 *  @default []
13238		 */
13239		"aoHeader": [],
13240	
13241		/**
13242		 * Store information about the table's footer
13243		 *  @type array
13244		 *  @default []
13245		 */
13246		"aoFooter": [],
13247	
13248		/**
13249		 * Store the applied global search information in case we want to force a
13250		 * research or compare the old search to a new one.
13251		 * Note that this parameter will be set by the initialisation routine. To
13252		 * set a default use {@link DataTable.defaults}.
13253		 *  @namespace
13254		 *  @extends DataTable.models.oSearch
13255		 */
13256		"oPreviousSearch": {},
13257	
13258		/**
13259		 * Store the applied search for each column - see
13260		 * {@link DataTable.models.oSearch} for the format that is used for the
13261		 * filtering information for each column.
13262		 *  @type array
13263		 *  @default []
13264		 */
13265		"aoPreSearchCols": [],
13266	
13267		/**
13268		 * Sorting that is applied to the table. Note that the inner arrays are
13269		 * used in the following manner:
13270		 * <ul>
13271		 *   <li>Index 0 - column number</li>
13272		 *   <li>Index 1 - current sorting direction</li>
13273		 * </ul>
13274		 * Note that this parameter will be set by the initialisation routine. To
13275		 * set a default use {@link DataTable.defaults}.
13276		 *  @type array
13277		 *  @todo These inner arrays should really be objects
13278		 */
13279		"aaSorting": null,
13280	
13281		/**
13282		 * Sorting that is always applied to the table (i.e. prefixed in front of
13283		 * aaSorting).
13284		 * Note that this parameter will be set by the initialisation routine. To
13285		 * set a default use {@link DataTable.defaults}.
13286		 *  @type array
13287		 *  @default []
13288		 */
13289		"aaSortingFixed": [],
13290	
13291		/**
13292		 * Classes to use for the striping of a table.
13293		 * Note that this parameter will be set by the initialisation routine. To
13294		 * set a default use {@link DataTable.defaults}.
13295		 *  @type array
13296		 *  @default []
13297		 */
13298		"asStripeClasses": null,
13299	
13300		/**
13301		 * If restoring a table - we should restore its striping classes as well
13302		 *  @type array
13303		 *  @default []
13304		 */
13305		"asDestroyStripes": [],
13306	
13307		/**
13308		 * If restoring a table - we should restore its width
13309		 *  @type int
13310		 *  @default 0
13311		 */
13312		"sDestroyWidth": 0,
13313	
13314		/**
13315		 * Callback functions array for every time a row is inserted (i.e. on a draw).
13316		 *  @type array
13317		 *  @default []
13318		 */
13319		"aoRowCallback": [],
13320	
13321		/**
13322		 * Callback functions for the header on each draw.
13323		 *  @type array
13324		 *  @default []
13325		 */
13326		"aoHeaderCallback": [],
13327	
13328		/**
13329		 * Callback function for the footer on each draw.
13330		 *  @type array
13331		 *  @default []
13332		 */
13333		"aoFooterCallback": [],
13334	
13335		/**
13336		 * Array of callback functions for draw callback functions
13337		 *  @type array
13338		 *  @default []
13339		 */
13340		"aoDrawCallback": [],
13341	
13342		/**
13343		 * Array of callback functions for row created function
13344		 *  @type array
13345		 *  @default []
13346		 */
13347		"aoRowCreatedCallback": [],
13348	
13349		/**
13350		 * Callback functions for just before the table is redrawn. A return of
13351		 * false will be used to cancel the draw.
13352		 *  @type array
13353		 *  @default []
13354		 */
13355		"aoPreDrawCallback": [],
13356	
13357		/**
13358		 * Callback functions for when the table has been initialised.
13359		 *  @type array
13360		 *  @default []
13361		 */
13362		"aoInitComplete": [],
13363	
13364	
13365		/**
13366		 * Callbacks for modifying the settings to be stored for state saving, prior to
13367		 * saving state.
13368		 *  @type array
13369		 *  @default []
13370		 */
13371		"aoStateSaveParams": [],
13372	
13373		/**
13374		 * Callbacks for modifying the settings that have been stored for state saving
13375		 * prior to using the stored values to restore the state.
13376		 *  @type array
13377		 *  @default []
13378		 */
13379		"aoStateLoadParams": [],
13380	
13381		/**
13382		 * Callbacks for operating on the settings object once the saved state has been
13383		 * loaded
13384		 *  @type array
13385		 *  @default []
13386		 */
13387		"aoStateLoaded": [],
13388	
13389		/**
13390		 * Cache the table ID for quick access
13391		 *  @type string
13392		 *  @default <i>Empty string</i>
13393		 */
13394		"sTableId": "",
13395	
13396		/**
13397		 * The TABLE node for the main table
13398		 *  @type node
13399		 *  @default null
13400		 */
13401		"nTable": null,
13402	
13403		/**
13404		 * Permanent ref to the thead element
13405		 *  @type node
13406		 *  @default null
13407		 */
13408		"nTHead": null,
13409	
13410		/**
13411		 * Permanent ref to the tfoot element - if it exists
13412		 *  @type node
13413		 *  @default null
13414		 */
13415		"nTFoot": null,
13416	
13417		/**
13418		 * Permanent ref to the tbody element
13419		 *  @type node
13420		 *  @default null
13421		 */
13422		"nTBody": null,
13423	
13424		/**
13425		 * Cache the wrapper node (contains all DataTables controlled elements)
13426		 *  @type node
13427		 *  @default null
13428		 */
13429		"nTableWrapper": null,
13430	
13431		/**
13432		 * Indicate if when using server-side processing the loading of data
13433		 * should be deferred until the second draw.
13434		 * Note that this parameter will be set by the initialisation routine. To
13435		 * set a default use {@link DataTable.defaults}.
13436		 *  @type boolean
13437		 *  @default false
13438		 */
13439		"bDeferLoading": false,
13440	
13441		/**
13442		 * Indicate if all required information has been read in
13443		 *  @type boolean
13444		 *  @default false
13445		 */
13446		"bInitialised": false,
13447	
13448		/**
13449		 * Information about open rows. Each object in the array has the parameters
13450		 * 'nTr' and 'nParent'
13451		 *  @type array
13452		 *  @default []
13453		 */
13454		"aoOpenRows": [],
13455	
13456		/**
13457		 * Dictate the positioning of DataTables' control elements - see
13458		 * {@link DataTable.model.oInit.sDom}.
13459		 * Note that this parameter will be set by the initialisation routine. To
13460		 * set a default use {@link DataTable.defaults}.
13461		 *  @type string
13462		 *  @default null
13463		 */
13464		"sDom": null,
13465	
13466		/**
13467		 * Search delay (in mS)
13468		 *  @type integer
13469		 *  @default null
13470		 */
13471		"searchDelay": null,
13472	
13473		/**
13474		 * Which type of pagination should be used.
13475		 * Note that this parameter will be set by the initialisation routine. To
13476		 * set a default use {@link DataTable.defaults}.
13477		 *  @type string
13478		 *  @default two_button
13479		 */
13480		"sPaginationType": "two_button",
13481	
13482		/**
13483		 * The state duration (for `stateSave`) in seconds.
13484		 * Note that this parameter will be set by the initialisation routine. To
13485		 * set a default use {@link DataTable.defaults}.
13486		 *  @type int
13487		 *  @default 0
13488		 */
13489		"iStateDuration": 0,
13490	
13491		/**
13492		 * Array of callback functions for state saving. Each array element is an
13493		 * object with the following parameters:
13494		 *   <ul>
13495		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13496		 *       and the JSON string to save that has been thus far created. Returns
13497		 *       a JSON string to be inserted into a json object
13498		 *       (i.e. '"param": [ 0, 1, 2]')</li>
13499		 *     <li>string:sName - name of callback</li>
13500		 *   </ul>
13501		 *  @type array
13502		 *  @default []
13503		 */
13504		"aoStateSave": [],
13505	
13506		/**
13507		 * Array of callback functions for state loading. Each array element is an
13508		 * object with the following parameters:
13509		 *   <ul>
13510		 *     <li>function:fn - function to call. Takes two parameters, oSettings
13511		 *       and the object stored. May return false to cancel state loading</li>
13512		 *     <li>string:sName - name of callback</li>
13513		 *   </ul>
13514		 *  @type array
13515		 *  @default []
13516		 */
13517		"aoStateLoad": [],
13518	
13519		/**
13520		 * State that was saved. Useful for back reference
13521		 *  @type object
13522		 *  @default null
13523		 */
13524		"oSavedState": null,
13525	
13526		/**
13527		 * State that was loaded. Useful for back reference
13528		 *  @type object
13529		 *  @default null
13530		 */
13531		"oLoadedState": null,
13532	
13533		/**
13534		 * Source url for AJAX data for the table.
13535		 * Note that this parameter will be set by the initialisation routine. To
13536		 * set a default use {@link DataTable.defaults}.
13537		 *  @type string
13538		 *  @default null
13539		 */
13540		"sAjaxSource": null,
13541	
13542		/**
13543		 * Property from a given object from which to read the table data from. This
13544		 * can be an empty string (when not server-side processing), in which case
13545		 * it is  assumed an an array is given directly.
13546		 * Note that this parameter will be set by the initialisation routine. To
13547		 * set a default use {@link DataTable.defaults}.
13548		 *  @type string
13549		 */
13550		"sAjaxDataProp": null,
13551	
13552		/**
13553		 * 
13553Note if draw should be blocked while getting data
13554		 *  @type boolean
13555		 *  @default true
13556		 */
13557		"bAjaxDataGet": true,
13558	
13559		/**
13560		 * The last jQuery XHR object that was used for server-side data gathering.
13561		 * This can be used for working with the XHR information in one of the
13562		 * callbacks
13563		 *  @type object
13564		 *  @default null
13565		 */
13566		"jqXHR": null,
13567	
13568		/**
13569		 * JSON returned from the server in the last Ajax request
13570		 *  @type object
13571		 *  @default undefined
13572		 */
13573		"json": undefined,
13574	
13575		/**
13576		 * Data submitted as part of the last Ajax request
13577		 *  @type object
13578		 *  @default undefined
13579		 */
13580		"oAjaxData": undefined,
13581	
13582		/**
13583		 * Function to get the server-side data.
13584		 * Note that this parameter will be set by the initialisation routine. To
13585		 * set a default use {@link DataTable.defaults}.
13586		 *  @type function
13587		 */
13588		"fnServerData": null,
13589	
13590		/**
13591		 * Functions which are called prior to sending an Ajax request so extra
13592		 * parameters can easily be sent to the server
13593		 *  @type array
13594		 *  @default []
13595		 */
13596		"aoServerParams": [],
13597	
13598		/**
13599		 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13600		 * required).
13601		 * Note that this parameter will be set by the initialisation routine. To
13602		 * set a default use {@link DataTable.defaults}.
13603		 *  @type string
13604		 */
13605		"sServerMethod": null,
13606	
13607		/**
13608		 * Format numbers for display.
13609		 * Note that this parameter will be set by the initialisation routine. To
13610		 * set a default use {@link DataTable.defaults}.
13611		 *  @type function
13612		 */
13613		"fnFormatNumber": null,
13614	
13615		/**
13616		 * List of options that can be used for the user selectable length menu.
13617		 * Note that this parameter will be set by the initialisation routine. To
13618		 * set a default use {@link DataTable.defaults}.
13619		 *  @type array
13620		 *  @default []
13621		 */
13622		"aLengthMenu": null,
13623	
13624		/**
13625		 * Counter for the draws that the table does. Also used as a tracker for
13626		 * server-side processing
13627		 *  @type int
13628		 *  @default 0
13629		 */
13630		"iDraw": 0,
13631	
13632		/**
13633		 * Indicate if a redraw is being done - useful for Ajax
13634		 *  @type boolean
13635		 *  @default false
13636		 */
13637		"bDrawing": false,
13638	
13639		/**
13640		 * Draw index (iDraw) of the last error when parsing the returned data
13641		 *  @type int
13642		 *  @default -1
13643		 */
13644		"iDrawError": -1,
13645	
13646		/**
13647		 * Paging display length
13648		 *  @type int
13649		 *  @default 10
13650		 */
13651		"_iDisplayLength": 10,
13652	
13653		/**
13654		 * Paging start point - aiDisplay index
13655		 *  @type int
13656		 *  @default 0
13657		 */
13658		"_iDisplayStart": 0,
13659	
13660		/**
13661		 * Server-side processing - number of records in the result set
13662		 * (i.e. before filtering), Use fnRecordsTotal rather than
13663		 * this property to get the value of the number of records, regardless of
13664		 * the server-side processing setting.
13665		 *  @type int
13666		 *  @default 0
13667		 *  @private
13668		 */
13669		"_iRecordsTotal": 0,
13670	
13671		/**
13672		 * Server-side processing - number of records in the current display set
13673		 * (i.e. after filtering). Use fnRecordsDisplay rather than
13674		 * this property to get the value of the number of records, regardless of
13675		 * the server-side processing setting.
13676		 *  @type boolean
13677		 *  @default 0
13678		 *  @private
13679		 */
13680		"_iRecordsDisplay": 0,
13681	
13682		/**
13683		 * The classes to use for the table
13684		 *  @type object
13685		 *  @default {}
13686		 */
vendor: 4,830 bytes, lines 13687-13895
13687		"oClasses": {},
13688	
13689		/**
13690		 * Flag attached to the settings object so you can check in the draw
13691		 * callback if filtering has been done in the draw. Deprecated in favour of
13692		 * events.
13693		 *  @type boolean
13694		 *  @default false
13695		 *  @deprecated
13696		 */
13697		"bFiltered": false,
13698	
13699		/**
13700		 * Flag attached to the settings object so you can check in the draw
13701		 * callback if sorting has been done in the draw. Deprecated in favour of
13702		 * events.
13703		 *  @type boolean
13704		 *  @default false
13705		 *  @deprecated
13706		 */
13707		"bSorted": false,
13708	
13709		/**
13710		 * Indicate that if multiple rows are in the header and there is more than
13711		 * one unique cell per column, if the top one (true) or bottom one (false)
13712		 * should be used for sorting / title by DataTables.
13713		 * Note that this parameter will be set by the initialisation routine. To
13714		 * set a default use {@link DataTable.defaults}.
13715		 *  @type boolean
13716		 */
13717		"bSortCellsTop": null,
13718	
13719		/**
13720		 * Initialisation object that is used for the table
13721		 *  @type object
13722		 *  @default null
13723		 */
13724		"oInit": null,
13725	
13726		/**
13727		 * Destroy callback functions - for plug-ins to attach themselves to the
13728		 * destroy so they can clean up markup and events.
13729		 *  @type array
13730		 *  @default []
13731		 */
13732		"aoDestroyCallback": [],
13733	
13734	
13735		/**
13736		 * Get the number of records in the current record set, before filtering
13737		 *  @type function
13738		 */
13739		"fnRecordsTotal": function ()
13740		{
13741			return _fnDataSource( this ) == 'ssp' ?
13742				this._iRecordsTotal * 1 :
13743				this.aiDisplayMaster.length;
13744		},
13745	
13746		/**
13747		 * Get the number of records in the current record set, after filtering
13748		 *  @type function
13749		 */
13750		"fnRecordsDisplay": function ()
13751		{
13752			return _fnDataSource( this ) == 'ssp' ?
13753				this._iRecordsDisplay * 1 :
13754				this.aiDisplay.length;
13755		},
13756	
13757		/**
13758		 * Get the display end point - aiDisplay index
13759		 *  @type function
13760		 */
13761		"fnDisplayEnd": function ()
13762		{
13763			var
13764				len      = this._iDisplayLength,
13765				start    = this._iDisplayStart,
13766				calc     = start + len,
13767				records  = this.aiDisplay.length,
13768				features = this.oFeatures,
13769				paginate = features.bPaginate;
13770	
13771			if ( features.bServerSide ) {
13772				return paginate === false || len === -1 ?
13773					start + records :
13774					Math.min( start+len, this._iRecordsDisplay );
13775			}
13776			else {
13777				return ! paginate || calc>records || len===-1 ?
13778					records :
13779					calc;
13780			}
13781		},
13782	
13783		/**
13784		 * The DataTables object for this table
13785		 *  @type object
13786		 *  @default null
13787		 */
13788		"oInstance": null,
13789	
13790		/**
13791		 * Unique identifier for each instance of the DataTables object. If there
13792		 * is an ID on the table node, then it takes that value, otherwise an
13793		 * incrementing internal counter is used.
13794		 *  @type string
13795		 *  @default null
13796		 */
13797		"sInstance": null,
13798	
13799		/**
13800		 * tabindex attribute value that is added to DataTables control elements, allowing
13801		 * keyboard navigation of the table and its controls.
13802		 */
13803		"iTabIndex": 0,
13804	
13805		/**
13806		 * DIV container for the footer scrolling table if scrolling
13807		 */
13808		"nScrollHead": null,
13809	
13810		/**
13811		 * DIV container for the footer scrolling table if scrolling
13812		 */
13813		"nScrollFoot": null,
13814	
13815		/**
13816		 * Last applied sort
13817		 *  @type array
13818		 *  @default []
13819		 */
13820		"aLastSort": [],
13821	
13822		/**
13823		 * Stored plug-in instances
13824		 *  @type object
13825		 *  @default {}
13826		 */
13827		"oPlugins": {},
13828	
13829		/**
13830		 * Function used to get a row's id from the row's data
13831		 *  @type function
13832		 *  @default null
13833		 */
13834		"rowIdFn": null,
13835	
13836		/**
13837		 * Data location where to store a row's id
13838		 *  @type string
13839		 *  @default null
13840		 */
13841		"rowId": null
13842	};
13843
13844	/**
13845	 * Extension object for DataTables that is used to provide all extension
13846	 * options.
13847	 *
13848	 * Note that the `DataTable.ext` object is available through
13849	 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13850	 * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13851	 *  @namespace
13852	 *  @extends DataTable.models.ext
13853	 */
13854	
13855	
13856	/**
13857	 * DataTables extensions
13858	 * 
13859	 * This namespace acts as a collection area for plug-ins that can be used to
13860	 * extend DataTables capabilities. Indeed many of the build in methods
13861	 * use this method to provide their own capabilities (sorting methods for
13862	 * example).
13863	 *
13864	 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13865	 * reasons
13866	 *
13867	 *  @namespace
13868	 */
13869	DataTable.ext = _ext = {
13870		/**
13871		 * Buttons. For use with the Buttons extension for DataTables. This is
13872		 * defined here so other extensions can define buttons regardless of load
13873		 * order. It is _not_ used by DataTables core.
13874		 *
13875		 *  @type object
13876		 *  @default {}
13877		 */
13878		buttons: {},
13879	
13880	
13881		/**
13882		 * Element class names
13883		 *
13884		 *  @type object
13885		 *  @default {}
13886		 */
13887		classes: {},
13888	
13889	
13890		/**
13891		 * DataTables build type (expanded by the download builder)
13892		 *
13893		 *  @type string
13894		 */
13895		build:"bs/dt-1.10.16/r-2.2.1
vendor: 10,712 bytes, lines 13895-14209
13895",
13896	
13897	
13898		/**
13899		 * Error reporting.
13900		 * 
13901		 * How should DataTables report an error. Can take the value 'alert',
13902		 * 'throw', 'none' or a function.
13903		 *
13904		 *  @type string|function
13905		 *  @default alert
13906		 */
13907		errMode: "alert",
13908	
13909	
13910		/**
13911		 * Feature plug-ins.
13912		 * 
13913		 * This is an array of objects which describe the feature plug-ins that are
13914		 * available to DataTables. These feature plug-ins are then available for
13915		 * use through the `dom` initialisation option.
13916		 * 
13917		 * Each feature plug-in is described by an object which must have the
13918		 * following properties:
13919		 * 
13920		 * * `fnInit` - function that is used to initialise the plug-in,
13921		 * * `cFeature` - a character so the feature can be enabled by the `dom`
13922		 *   instillation option. This is case sensitive.
13923		 *
13924		 * The `fnInit` function has the following input parameters:
13925		 *
13926		 * 1. `{object}` DataTables settings object: see
13927		 *    {@link DataTable.models.oSettings}
13928		 *
13929		 * And the following return is expected:
13930		 * 
13931		 * * {node|null} The element which contains your feature. Note that the
13932		 *   return may also be void if your plug-in does not require to inject any
13933		 *   DOM elements into DataTables control (`dom`) - for example this might
13934		 *   be useful when developing a plug-in which allows table control via
13935		 *   keyboard entry
13936		 *
13937		 *  @type array
13938		 *
13939		 *  @example
13940		 *    $.fn.dataTable.ext.features.push( {
13941		 *      "fnInit": function( oSettings ) {
13942		 *        return new TableTools( { "oDTSettings": oSettings } );
13943		 *      },
13944		 *      "cFeature": "T"
13945		 *    } );
13946		 */
13947		feature: [],
13948	
13949	
13950		/**
13951		 * Row searching.
13952		 * 
13953		 * This method of searching is complimentary to the default type based
13954		 * searching, and a lot more comprehensive as it allows you complete control
13955		 * over the searching logic. Each element in this array is a function
13956		 * (parameters described below) that is called for every row in the table,
13957		 * and your logic decides if it should be included in the searching data set
13958		 * or not.
13959		 *
13960		 * Searching functions have the following input parameters:
13961		 *
13962		 * 1. `{object}` DataTables settings object: see
13963		 *    {@link DataTable.models.oSettings}
13964		 * 2. `{array|object}` Data for the row to be processed (same as the
13965		 *    original format that was passed in as the data source, or an array
13966		 *    from a DOM data source
13967		 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13968		 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13969		 *
13970		 * And the following return is expected:
13971		 *
13972		 * * {boolean} Include the row in the searched result set (true) or not
13973		 *   (false)
13974		 *
13975		 * Note that as with the main search ability in DataTables, technically this
13976		 * is "filtering", since it is subtractive. However, for consistency in
13977		 * naming we call it searching here.
13978		 *
13979		 *  @type array
13980		 *  @default []
13981		 *
13982		 *  @example
13983		 *    // The following example shows custom search being applied to the
13984		 *    // fourth column (i.e. the data[3] index) based on two input values
13985		 *    // from the end-user, matching the data in a certain range.
13986		 *    $.fn.dataTable.ext.search.push(
13987		 *      function( settings, data, dataIndex ) {
13988		 *        var min = document.getElementById('min').value * 1;
13989		 *        var max = document.getElementById('max').value * 1;
13990		 *        var version = data[3] == "-" ? 0 : data[3]*1;
13991		 *
13992		 *        if ( min == "" && max == "" ) {
13993		 *          return true;
13994		 *        }
13995		 *        else if ( min == "" && version < max ) {
13996		 *          return true;
13997		 *        }
13998		 *        else if ( min < version && "" == max ) {
13999		 *          return true;
14000		 *        }
14001		 *        else if ( min < version && version < max ) {
14002		 *          return true;
14003		 *        }
14004		 *        return false;
14005		 *      }
14006		 *    );
14007		 */
14008		search: [],
14009	
14010	
14011		/**
14012		 * Selector extensions
14013		 *
14014		 * The `selector` option can be used to extend the options available for the
14015		 * selector modifier options (`selector-modifier` object data type) that
14016		 * each of the three built in selector types offer (row, column and cell +
14017		 * their plural counterparts). For example the Select extension uses this
14018		 * mechanism to provide an option to select only rows, columns and cells
14019		 * that have been marked as selected by the end user (`{selected: true}`),
14020		 * which can be used in conjunction with the existing built in selector
14021		 * options.
14022		 *
14023		 * Each property is an array to which functions can be pushed. The functions
14024		 * take three attributes:
14025		 *
14026		 * * Settings object for the host table
14027		 * * Options object (`selector-modifier` object type)
14028		 * * Array of selected item indexes
14029		 *
14030		 * The return is an array of the resulting item indexes after the custom
14031		 * selector has been applied.
14032		 *
14033		 *  @type object
14034		 */
14035		selector: {
14036			cell: [],
14037			column: [],
14038			row: []
14039		},
14040	
14041	
14042		/**
14043		 * Internal functions, exposed for used in plug-ins.
14044		 * 
14045		 * Please note that you should not need to use the internal methods for
14046		 * anything other than a plug-in (and even then, try to avoid if possible).
14047		 * The internal function may change between releases.
14048		 *
14049		 *  @type object
14050		 *  @default {}
14051		 */
14052		internal: {},
14053	
14054	
14055		/**
14056		 * Legacy configuration options. Enable and disable legacy options that
14057		 * are available in DataTables.
14058		 *
14059		 *  @type object
14060		 */
14061		legacy: {
14062			/**
14063			 * Enable / disable DataTables 1.9 compatible server-side processing
14064			 * requests
14065			 *
14066			 *  @type boolean
14067			 *  @default null
14068			 */
14069			ajax: null
14070		},
14071	
14072	
14073		/**
14074		 * Pagination plug-in methods.
14075		 * 
14076		 * Each entry in this object is a function and defines which buttons should
14077		 * be shown by the pagination rendering method that is used for the table:
14078		 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14079		 * buttons are displayed in the document, while the functions here tell it
14080		 * what buttons to display. This is done by returning an array of button
14081		 * descriptions (what each button will do).
14082		 *
14083		 * Pagination types (the four built in options and any additional plug-in
14084		 * options defined here) can be used through the `paginationType`
14085		 * initialisation parameter.
14086		 *
14087		 * The functions defined take two parameters:
14088		 *
14089		 * 1. `{int} page` The current page index
14090		 * 2. `{int} pages` The number of pages in the table
14091		 *
14092		 * Each function is expected to return an array where each element of the
14093		 * array can be one of:
14094		 *
14095		 * * `first` - Jump to first page when activated
14096		 * * `last` - Jump to last page when activated
14097		 * * `previous` - Show previous page when activated
14098		 * * `next` - Show next page when activated
14099		 * * `{int}` - Show page of the index given
14100		 * * `{array}` - A nested array containing the above elements to add a
14101		 *   containing 'DIV' element (might be useful for styling).
14102		 *
14103		 * Note that DataTables v1.9- used this object slightly differently whereby
14104		 * an object with two functions would be defined for each plug-in. That
14105		 * ability is still supported by DataTables 1.10+ to provide backwards
14106		 * compatibility, but this option of use is now decremented and no longer
14107		 * documented in DataTables 1.10+.
14108		 *
14109		 *  @type object
14110		 *  @default {}
14111		 *
14112		 *  @example
14113		 *    // Show previous, next and current page buttons only
14114		 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14115		 *      return [ 'previous', page, 'next' ];
14116		 *    };
14117		 */
14118		pager: {},
14119	
14120	
14121		renderer: {
14122			pageButton: {},
14123			header: {}
14124		},
14125	
14126	
14127		/**
14128		 * Ordering plug-ins - custom data source
14129		 * 
14130		 * The extension options for ordering of data available here is complimentary
14131		 * to the default type based ordering that DataTables typically uses. It
14132		 * allows much greater control over the the data that is being used to
14133		 * order a column, but is necessarily therefore more complex.
14134		 * 
14135		 * This type of ordering is useful if you want to do ordering based on data
14136		 * live from the DOM (for example the contents of an 'input' element) rather
14137		 * than just the static string that DataTables knows of.
14138		 * 
14139		 * The way these plug-ins work is that you create an array of the values you
14140		 * wish to be ordering for the column in question and then return that
14141		 * array. The data in the array much be in the index order of the rows in
14142		 * the table (not the currently ordering order!). Which order data gathering
14143		 * function is run here depends on the `dt-init columns.orderDataType`
14144		 * parameter that is used for the column (if any).
14145		 *
14146		 * The functions defined take two parameters:
14147		 *
14148		 * 1. `{object}` DataTables settings object: see
14149		 *    {@link DataTable.models.oSettings}
14150		 * 2. `{int}` Target column index
14151		 *
14152		 * Each function is expected to return an array:
14153		 *
14154		 * * `{array}` Data for the column to be ordering upon
14155		 *
14156		 *  @type array
14157		 *
14158		 *  @example
14159		 *    // Ordering using `input` node values
14160		 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14161		 *    {
14162		 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14163		 *        return $('input', td).val();
14164		 *      } );
14165		 *    }
14166		 */
14167		order: {},
14168	
14169	
14170		/**
14171		 * Type based plug-ins.
14172		 *
14173		 * Each column in DataTables has a type assigned to it, either by automatic
14174		 * detection or by direct assignment using the `type` option for the column.
14175		 * The type of a column will effect how it is ordering and search (plug-ins
14176		 * can also make use of the column type if required).
14177		 *
14178		 * @namespace
14179		 */
14180		type: {
14181			/**
14182			 * Type detection functions.
14183			 *
14184			 * The functions defined in this object are used to automatically detect
14185			 * a column's type, making initialisation of DataTables super easy, even
14186			 * when complex data is in the table.
14187			 *
14188			 * The functions defined take two parameters:
14189			 *
14190		     *  1. `{*}` Data from the column cell to be analysed
14191		     *  2. `{settings}` DataTables settings object. This can be used to
14192		     *     perform context specific type detection - for example detection
14193		     *     based on language settings such as using a comma for a decimal
14194		     *     place. Generally speaking the options from the settings will not
14195		     *     be required
14196			 *
14197			 * Each function is expected to return:
14198			 *
14199			 * * `{string|null}` Data type detected, or null if unknown (and thus
14200			 *   pass it on to the other type detection functions.
14201			 *
14202			 *  @type array
14203			 *
14204			 *  @example
14205			 *    // Currency type detection plug-in:
14206			 *    $.fn.dataTable.ext.type.detect.push(
14207			 *      function ( data, settings ) {
14208			 *        // Check the numeric part
14209			 *        if ( ! 
14209$.isNumeric( data.substring(1) ) ) {
14210			 *          return null;
14211			 *        }
14212			 *
14213			 *        // Check prefixed by currency
14214			 *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14215			 *          return 'currency';
14216			 *        }
14217			 *        return null;
14218			 *      }
14219			 *    );
14220			 */
14221			detect: [],
14222	
14223	
14224			/**
14225			 * Type based search formatting.
14226			 *
14227			 * The type based searching functions can be used to pre-format the
14228			 * data to be search on. For example, it can be used to strip HTML
14229			 * tags or to de-format telephone numbers for numeric only searching.
14230			 *
14231			 * Note that is a search is not defined for a column of a given type,
14232			 * no search formatting will be performed.
14233			 * 
14234			 * Pre-processing of searching data plug-ins - When you assign the sType
14235			 * for a column (or have it automatically detected for you by DataTables
14236			 * or a type detection plug-in), you will typically be using this for
14237			 * custom sorting, but it can also be used to provide custom searching
14238			 * by allowing you to pre-processing the data and returning the data in
14239			 * the format that should be searched upon. This is done by adding
14240			 * functions this object with a parameter name which matches the sType
14241			 * for that target column. This is the corollary of <i>afnSortData</i>
14242			 * for searching data.
14243			 *
14244			 * The functions defined take a single parameter:
14245			 *
14246		     *  1. `{*}` Data from the column cell to be prepared for searching
14247			 *
14248			 * Each function is expected to return:
14249			 *
14250			 * * `{string|null}` Formatted string that will be used for the searching.
14251			 *
14252			 *  @type object
14253			 *  @default {}
14254			 *
14255			 *  @example
14256			 *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14257			 *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14258			 *    }
14259			 */
14260			search: {},
14261	
14262	
14263			/**
14264			 * Type based ordering.
14265			 *
14266			 * The column type tells DataTables what ordering to apply to the table
14267			 * when a column is sorted upon. The order for each type that is defined,
14268			 * is defined by the functions available in this object.
14269			 *
14270			 * Each ordering option can be described by three properties added to
14271			 * this object:
14272			 *
14273			 * * `{type}-pre` - Pre-formatting function
14274			 * * `{type}-asc` - Ascending order function
14275			 * * `{type}-desc` - Descending order function
14276			 *
14277			 * All three can be used together, only `{type}-pre` or only
14278			 * `{type}-asc` and `{type}-desc` together. It is generally recommended
14279			 * that only `{type}-pre` is used, as this provides the optimal
14280			 * implementation in terms of speed, although the others are provided
14281			 * for compatibility with existing Javascript sort functions.
14282			 *
14283			 * `{type}-pre`: Functions defined take a single parameter:
14284			 *
14285		     *  1. `{*}` Data from the column cell to be prepared for ordering
14286			 *
14287			 * And return:
14288			 *
14289			 * * `{*}` Data to be sorted upon
14290			 *
14291			 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14292			 * functions, taking two parameters:
14293			 *
14294		     *  1. `{*}` Data to compare to the second parameter
14295		     *  2. `{*}` Data to compare to the first parameter
14296			 *
14297			 * And returning:
14298			 *
14299			 * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14300			 *   than the second parameter, ===0 if the two parameters are equal and
14301			 *   >0 if the first parameter should be sorted height than the second
14302			 *   parameter.
14303			 * 
14304			 *  @type object
14305			 *  @default {}
14306			 *
14307			 *  @example
14308			 *    // Numeric ordering of formatted numbers with a pre-formatter
14309			 *    $.extend( $.fn.dataTable.ext.type.order, {
14310			 *      "string-pre": function(x) {
14311			 *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14312			 *        return parseFloat( a );
14313			 *      }
14314			 *    } );
14315			 *
14316			 *  @example
14317			 *    // Case-sensitive string ordering, with no pre-formatting method
14318			 *    $.extend( $.fn.dataTable.ext.order, {
14319			 *      "string-case-asc": function(x,y) {
14320			 *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14321			 *      },
14322			 *      "string-case-desc": function(x,y) {
14323			 *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14324			 *      }
14325			 *    } );
14326			 */
14327			order: {}
14328		},
14329	
14330		/**
14331		 * Unique DataTables instance counter
14332		 *
14333		 * @type int
14334		 * @private
14335		 */
14336		_unique: 0,
14337	
14338	
14339		//
14340		// Depreciated
14341		// The following properties are retained for backwards compatiblity only.
14342		// The should not be used in new projects and will be removed in a future
14343		// version
14344		//
14345	
14346		/**
14347		 * Version check function.
14348		 *  @type function
14349		 *  @depreciated Since 1.10
14350		 */
14351		fnVersionCheck: DataTable.fnVersionCheck,
14352	
14353	
14354		/**
14355		 * Index for what 'this' index API functions should use
14356		 *  @type int
14357		 *  @deprecated Since v1.10
14358		 */
14359		iApiIndex: 0,
14360	
14361	
14362		/**
14363		 * jQuery UI class container
14364		 *  @type object
14365		 *  @deprecated Since v1.10
14366		 */
14367		oJUIClasses: {},
14368	
14369	
14370		/**
14371		 * Software version
14372		 *  @type string
14373		 *  @deprecated Since v1.10
14374		 */
14375		sVersion: DataTable.version
14376	};
14377	
14378	
14379	//
14380	// Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14381	//
14382	$.extend( _ext, {
14383		afnFiltering: _ext.search,
14384		aTypes:       _ext.type.detect,
14385		ofnSearch:    _ext.type.search,
14386		oSort:        _ext.type.order,
14387		afnSortData:  _ext.order,
14388		aoFeatures:   _ext.feature,
14389		oApi:         _ext.internal,
14390		oStdClasses:  _ext.classes,
14391		oPagination:  _ext.pager
14392	} );
14393	
14394	
14395	$.extend( DataTable.ext.classes, {
14396		"sTable": "dataTable",
14397		"sNoFooter": "no-footer",
14398	
14399		/* Paging buttons */
14400		"sPageButton": "paginate_button",
14401		"sPageButtonActive": "current",
14402		"sPageButtonDisabled": "disabled",
14403	
14404		/* Striping classes */
14405		"sStripeOdd": "odd",
14406		"sStripeEven": "even",
14407	
14408		/* Empty row */
14409		"sRowEmpty": "dataTables_empty",
14410	
14411		/* Features */
14412		"sWrapper": "dataTables_wrapper",
14413		"sFilter": "dataTables_filter",
14414		"sInfo": "dataTables_info",
14415		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14416		"sLength": "dataTables_length",
14417		"sProcessing": "dataTables_processing",
14418	
14419		/* Sorting */
14420		"sSortAsc": "sorting_asc",
14421		"sSortDesc": "sorting_desc",
14422		"sSortable": "sorting", /* Sortable in both directions */
14423		"sSortableAsc": "sorting_asc_disabled",
14424		"sSortableDesc": "sorting_desc_disabled",
14425		"sSortableNone": "sorting_disabled",
14426		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14427	
14428		/* Filtering */
14429		"sFilterInput": "",
14430	
14431		/* Page length */
14432		"sLengthSelect": "",
14433	
14434		/* Scrolling */
14435		"sScrollWrapper": "dataTables_scroll",
14436		"sScrollHead": "dataTables_scrollHead",
14437		"sScrollHeadInner": "dataTables_scrollHeadInner",
14438		"sScrollBody": "dataTables_scrollBody",
14439		"sScrollFoot": "dataTables_scrollFoot",
14440		"sScrollFootInner": "dataTables_scrollFootInner",
14441	
14442		/* Misc */
14443		"sHeaderTH": "",
14444		"sFooterTH": "",
14445	
14446		// Deprecated
14447		"sSortJUIAsc": "",
14448		"sSortJUIDesc": "",
14449		"sSortJUI": "",
14450		"sSortJUIAscAllowed": "",
14451		"sSortJUIDescAllowed": "",
14452		"sSortJUIWrapper": "",
14453		"sSortIcon": "",
14454		"sJUIHeader": "",
14455		"sJUIFooter": ""
14456	} );
14457	
14458	
14459	var extPagination = DataTable.ext.pager;
14460	
14461	function _numbers ( page, pages ) {
14462		var
14463			numbers = [],
14464			buttons = extPagination.numbers_length,
14465			half = Math.floor( buttons / 2 ),
14466			i = 1;
14467	
14468		if ( pages <= buttons ) {
14469			numbers = _range( 0, pages );
14470		}
14471		else if ( page <= half ) {
14472			numbers = _range( 0, buttons-2 );
14473			numbers.push( 'ellipsis' );
14474			numbers.push( pages-1 );
14475		}
14476		else if ( page >= pages - 1 - half ) {
14477			numbers = _range( pages-(buttons-2), pages );
14478			numbers.splice( 0, 0, 'ellipsis' );
14478 // no unshift in ie6
14479			numbers.splice( 0, 0, 0 );
14480		}
14481		else {
14482			numbers = _range( page-half+2, page+half-1 );
14483			numbers.push( 'ellipsis' );
14484			numbers.push( pages-1 );
14485			numbers.splice( 0, 0, 'ellipsis' );
14486			numbers.splice( 0, 0, 0 );
14487		}
14488	
14489		numbers.DT_el = 'span';
14490		return numbers;
14491	}
14492	
14493	
14494	$.extend( extPagination, {
14495		simple: function ( page, pages ) {
14496			return [ 'previous', 'next' ];
14497		},
14498	
14499		full: function ( page, pages ) {
14500			return [  'first', 'previous', 'next', 'last' ];
14501		},
14502	
14503		numbers: function ( page, pages ) {
14504			return [ _numbers(page, pages) ];
14505		},
14506	
14507		simple_numbers: function ( page, pages ) {
14508			return [ 'previous', _numbers(page, pages), 'next' ];
14509		},
14510	
14511		full_numbers: function ( page, pages ) {
14512			return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14513		},
14514		
14515		first_last_numbers: function (page, pages) {
14516	 		return ['first', _numbers(page, pages), 'last'];
14517	 	},
14518	
14519		// For testing and plug-ins to use
14520		_numbers: _numbers,
14521	
14522		// Number of number buttons (including ellipsis) to show. _Must be odd!_
14523		numbers_length: 7
14524	} );
14525	
14526	
14527	$.extend( true, DataTable.ext.renderer, {
14528		pageButton: {
14529			_: function ( settings, host, idx, buttons, page, pages ) {
14530				var classes = settings.oClasses;
14531				var lang = settings.oLanguage.oPaginate;
14532				var aria = settings.oLanguage.oAria.paginate || {};
14533				var btnDisplay, btnClass, counter=0;
14534	
14535				var attach = function( container, buttons ) {
14536					var i, ien, node, button;
14537					var clickHandler = function ( e ) {
14538						_fnPageChange( settings, e.data.action, true );
14539					};
14540	
14541					for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14542						button = buttons[i];
14543	
14544						if ( $.isArray( button ) ) {
14545							var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14546								.appendTo( container );
14547							attach( inner, button );
14548						}
14549						else {
14550							btnDisplay = null;
14551							btnClass = '';
14552	
14553							switch ( button ) {
14554								case 'ellipsis':
14555									container.append('<span class="ellipsis">&#x2026;</span>');
14556									break;
14557	
14558								case 'first':
14559									btnDisplay = lang.sFirst;
14560									btnClass = button + (page > 0 ?
14561										'' : ' '+classes.sPageButtonDisabled);
14562									break;
14563	
14564								case 'previous':
14565									btnDisplay = lang.sPrevious;
14566									btnClass = button + (page > 0 ?
14567										'' : ' '+classes.sPageButtonDisabled);
14568									break;
14569	
14570								case 'next':
14571									btnDisplay = lang.sNext;
14572									btnClass = button + (page < pages-1 ?
14573										'' : ' '+classes.sPageButtonDisabled);
14574									break;
14575	
14576								case 'last':
14577									btnDisplay = lang.sLast;
14578									btnClass = button + (page < pages-1 ?
14579										'' : ' '+classes.sPageButtonDisabled);
14580									break;
14581	
14582								default:
14583									btnDisplay = button + 1;
14584									btnClass = page === button ?
14585										classes.sPageButtonActive : '';
14586									break;
14587							}
14588	
14589							if ( btnDisplay !== null ) {
14590								node = $('<a>', {
14591										'class': classes.sPageButton+' '+btnClass,
14592										'aria-controls': settings.sTableId,
14593										'aria-label': aria[ button ],
14594										'data-dt-idx': counter,
14595										'tabindex': settings.iTabIndex,
14596										'id': idx === 0 && typeof button === 'string' ?
14597											settings.sTableId +'_'+ button :
14598											null
14599									} )
14600									.html( btnDisplay )
14601									.appendTo( container );
14602	
14603								_fnBindAction(
14604									node, {action: button}, clickHandler
14605								);
14606	
14607								counter++;
14608							}
14609						}
14610					}
14611				};
14612	
14613				// IE9 throws an 'unknown error' if document.activeElement is used
14614				// inside an iframe or frame. Try / catch the error. Not good for
14615				// accessibility, but neither are frames.
14616				var activeEl;
14617	
14618				try {
14619					// Because this approach is destroying and recreating the paging
14620					// elements, focus is lost on the select button which is bad for
14621					// accessibility. So we want to restore focus once the draw has
14622					// completed
14623					activeEl = $(host).find(document.activeElement).data('dt-idx');
14624				}
14625				catch (e) {}
14626	
14627				attach( $(host).empty(), buttons );
14628	
14629				if ( activeEl !== undefined ) {
14630					$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14631				}
14632			}
14633		}
14634	} );
14635	
14636	
14637	
14638	// Built in type detection. See model.ext.aTypes for information about
14639	// what is required from this methods.
14640	$.extend( DataTable.ext.type.detect, [
vendor: 18,159 bytes, lines 14641-15235
14641		// Plain numbers - first since V8 detects some plain numbers as dates
14642		// e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14643		function ( d, settings )
14644		{
14645			var decimal = settings.oLanguage.sDecimal;
14646			return _isNumber( d, decimal ) ? 'num'+decimal : null;
14647		},
14648	
14649		// Dates (only those recognised by the browser's Date.parse)
14650		function ( d, settings )
14651		{
14652			// V8 tries _very_ hard to make a string passed into `Date.parse()`
14653			// valid, so we need to use a regex to restrict date formats. Use a
14654			// plug-in for anything other than ISO8601 style strings
14655			if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14656				return null;
14657			}
14658			var parsed = Date.parse(d);
14659			return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14660		},
14661	
14662		// Formatted numbers
14663		function ( d, settings )
14664		{
14665			var decimal = settings.oLanguage.sDecimal;
14666			return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14667		},
14668	
14669		// HTML numeric
14670		function ( d, settings )
14671		{
14672			var decimal = settings.oLanguage.sDecimal;
14673			return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14674		},
14675	
14676		// HTML numeric, formatted
14677		function ( d, settings )
14678		{
14679			var decimal = settings.oLanguage.sDecimal;
14680			return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14681		},
14682	
14683		// HTML (this is strict checking - there must be html)
14684		function ( d, settings )
14685		{
14686			return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14687				'html' : null;
14688		}
14689	] );
14690	
14691	
14692	
14693	// Filter formatting functions. See model.ext.ofnSearch for information about
14694	// what is required from these methods.
14695	// 
14696	// Note that additional search methods are added for the html numbers and
14697	// html formatted numbers by `_addNumericSort()` when we know what the decimal
14698	// place is
14699	
14700	
14701	$.extend( DataTable.ext.type.search, {
14702		html: function ( data ) {
14703			return _empty(data) ?
14704				data :
14705				typeof data === 'string' ?
14706					data
14707						.replace( _re_new_lines, " " )
14708						.replace( _re_html, "" ) :
14709					'';
14710		},
14711	
14712		string: function ( data ) {
14713			return _empty(data) ?
14714				data :
14715				typeof data === 'string' ?
14716					data.replace( _re_new_lines, " " ) :
14717					data;
14718		}
14719	} );
14720	
14721	
14722	
14723	var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14724		if ( d !== 0 && (!d || d === '-') ) {
14725			return -Infinity;
14726		}
14727	
14728		// If a decimal place other than `.` is used, it needs to be given to the
14729		// function so we can detect it and replace with a `.` which is the only
14730		// decimal place Javascript recognises - it is not locale aware.
14731		if ( decimalPlace ) {
14732			d = _numToDecimal( d, decimalPlace );
14733		}
14734	
14735		if ( d.replace ) {
14736			if ( re1 ) {
14737				d = d.replace( re1, '' );
14738			}
14739	
14740			if ( re2 ) {
14741				d = d.replace( re2, '' );
14742			}
14743		}
14744	
14745		return d * 1;
14746	};
14747	
14748	
14749	// Add the numeric 'deformatting' functions for sorting and search. This is done
14750	// in a function to provide an easy ability for the language options to add
14751	// additional methods if a non-period decimal place is used.
14752	function _addNumericSort ( decimalPlace ) {
14753		$.each(
14754			{
14755				// Plain numbers
14756				"num": function ( d ) {
14757					return __numericReplace( d, decimalPlace );
14758				},
14759	
14760				// Formatted numbers
14761				"num-fmt": function ( d ) {
14762					return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14763				},
14764	
14765				// HTML numeric
14766				"html-num": function ( d ) {
14767					return __numericReplace( d, decimalPlace, _re_html );
14768				},
14769	
14770				// HTML numeric, formatted
14771				"html-num-fmt": function ( d ) {
14772					return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14773				}
14774			},
14775			function ( key, fn ) {
14776				// Add the ordering method
14777				_ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14778	
14779				// For HTML types add a search formatter that will strip the HTML
14780				if ( key.match(/^html\-/) ) {
14781					_ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14782				}
14783			}
14784		);
14785	}
14786	
14787	
14788	// Default sort methods
14789	$.extend( _ext.type.order, {
14790		// Dates
14791		"date-pre": function ( d ) {
14792			return Date.parse( d ) || -Infinity;
14793		},
14794	
14795		// html
14796		"html-pre": function ( a ) {
14797			return _empty(a) ?
14798				'' :
14799				a.replace ?
14800					a.replace( /<.*?>/g, "" ).toLowerCase() :
14801					a+'';
14802		},
14803	
14804		// string
14805		"string-pre": function ( a ) {
14806			// This is a little complex, but faster than always calling toString,
14807			// http://jsperf.com/tostring-v-check
14808			return _empty(a) ?
14809				'' :
14810				typeof a === 'string' ?
14811					a.toLowerCase() :
14812					! a.toString ?
14813						'' :
14814						a.toString();
14815		},
14816	
14817		// string-asc and -desc are retained only for compatibility with the old
14818		// sort methods
14819		"string-asc": function ( x, y ) {
14820			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14821		},
14822	
14823		"string-desc": function ( x, y ) {
14824			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14825		}
14826	} );
14827	
14828	
14829	// Numeric sorting types - order doesn't matter here
14830	_addNumericSort( '' );
14831	
14832	
14833	$.extend( true, DataTable.ext.renderer, {
14834		header: {
14835			_: function ( settings, cell, column, classes ) {
14836				// No additional mark-up required
14837				// Attach a sort listener to update on sort - note that using the
14838				// `DT` namespace will allow the event to be removed automatically
14839				// on destroy, while the `dt` namespaced event is the one we are
14840				// listening for
14841				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14842					if ( settings !== ctx ) { // need to check this this is the host
14843						return;               // table, not a nested one
14844					}
14845	
14846					var colIdx = column.idx;
14847	
14848					cell
14849						.removeClass(
14850							column.sSortingClass +' '+
14851							classes.sSortAsc +' '+
14852							classes.sSortDesc
14853						)
14854						.addClass( columns[ colIdx ] == 'asc' ?
14855							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14856								classes.sSortDesc :
14857								column.sSortingClass
14858						);
14859				} );
14860			},
14861	
14862			jqueryui: function ( settings, cell, column, classes ) {
14863				$('<div/>')
14864					.addClass( classes.sSortJUIWrapper )
14865					.append( cell.contents() )
14866					.append( $('<span/>')
14867						.addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14868					)
14869					.appendTo( cell );
14870	
14871				// Attach a sort listener to update on sort
14872				$(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14873					if ( settings !== ctx ) {
14874						return;
14875					}
14876	
14877					var colIdx = column.idx;
14878	
14879					cell
14880						.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14881						.addClass( columns[ colIdx ] == 'asc' ?
14882							classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14883								classes.sSortDesc :
14884								column.sSortingClass
14885						);
14886	
14887					cell
14888						.find( 'span.'+classes.sSortIcon )
14889						.removeClass(
14890							classes.sSortJUIAsc +" "+
14891							classes.sSortJUIDesc +" "+
14892							classes.sSortJUI +" "+
14893							classes.sSortJUIAscAllowed +" "+
14894							classes.sSortJUIDescAllowed
14895						)
14896						.addClass( columns[ colIdx ] == 'asc' ?
14897							classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14898								classes.sSortJUIDesc :
14899								column.sSortingClassJUI
14900						);
14901				} );
14902			}
14903		}
14904	} );
14905	
14906	/*
14907	 * Public helper functions. These aren't used internally by DataTables, or
14908	 * called by any of the options passed into DataTables, but they can be used
14909	 * externally by developers working with DataTables. They are helper functions
14910	 * to make working with DataTables a little bit easier.
14911	 */
14912	
14913	var __htmlEscapeEntities = function ( d ) {
14914		return typeof d === 'string' ?
14915			d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14916			d;
14917	};
14918	
14919	/**
14920	 * Helpers for `columns.render`.
14921	 *
14922	 * The options defined here can be used with the `columns.render` initialisation
14923	 * option to provide a display renderer. The following functions are defined:
14924	 *
14925	 * * `number` - Will format numeric data (defined by `columns.data`) for
14926	 *   display, retaining the original unformatted data for sorting and filtering.
14927	 *   It takes 5 parameters:
14928	 *   * `string` - Thousands grouping separator
14929	 *   * `string` - Decimal point indicator
14930	 *   * `integer` - Number of decimal points to show
14931	 *   * `string` (optional) - Prefix.
14932	 *   * `string` (optional) - Postfix (/suffix).
14933	 * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14934	 *   parameters.
14935	 *
14936	 * @example
14937	 *   // Column definition using the number renderer
14938	 *   {
14939	 *     data: "salary",
14940	 *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14941	 *   }
14942	 *
14943	 * @namespace
14944	 */
14945	DataTable.render = {
14946		number: function ( thousands, decimal, precision, prefix, postfix ) {
14947			return {
14948				display: function ( d ) {
14949					if ( typeof d !== 'number' && typeof d !== 'string' ) {
14950						return d;
14951					}
14952	
14953					var negative = d < 0 ? '-' : '';
14954					var flo = parseFloat( d );
14955	
14956					// If NaN then there isn't much formatting that we can do - just
14957					// return immediately, escaping any HTML (this was supposed to
14958					// be a number after all)
14959					if ( isNaN( flo ) ) {
14960						return __htmlEscapeEntities( d );
14961					}
14962	
14963					flo = flo.toFixed( precision );
14964					d = Math.abs( flo );
14965	
14966					var intPart = parseInt( d, 10 );
14967					var floatPart = precision ?
14968						decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14969						'';
14970	
14971					return negative + (prefix||'') +
14972						intPart.toString().replace(
14973							/\B(?=(\d{3})+(?!\d))/g, thousands
14974						) +
14975						floatPart +
14976						(postfix||'');
14977				}
14978			};
14979		},
14980	
14981		text: function () {
14982			return {
14983				display: __htmlEscapeEntities
14984			};
14985		}
14986	};
14987	
14988	
14989	/*
14990	 * This is really a good bit rubbish this method of exposing the internal methods
14991	 * publicly... - To be fixed in 2.0 using methods on the prototype
14992	 */
14993	
14994	
14995	/**
14996	 * Create a wrapper function for exporting an internal functions to an external API.
14997	 *  @param {string} fn API function name
14998	 *  @returns {function} wrapped function
14999	 *  @memberof DataTable#internal
15000	 */
15001	function _fnExternApiFunc (fn)
15002	{
15003		return function() {
15004			var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15005				Array.prototype.slice.call(arguments)
15006			);
15007			return DataTable.ext.internal[fn].apply( this, args );
15008		};
15009	}
15010	
15011	
15012	/**
15013	 * Reference to internal functions for use by plug-in developers. Note that
15014	 * these methods are references to internal functions and are considered to be
15015	 * private. If you use these methods, be aware that they are liable to change
15016	 * between versions.
15017	 *  @namespace
15018	 */
15019	$.extend( DataTable.ext.internal, {
15020		_fnExternApiFunc: _fnExternApiFunc,
15021		_fnBuildAjax: _fnBuildAjax,
15022		_fnAjaxUpdate: _fnAjaxUpdate,
15023		_fnAjaxParameters: _fnAjaxParameters,
15024		_fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15025		_fnAjaxDataSrc: _fnAjaxDataSrc,
15026		_fnAddColumn: _fnAddColumn,
15027		_fnColumnOptions: _fnColumnOptions,
15028		_fnAdjustColumnSizing: _fnAdjustColumnSizing,
15029		_fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15030		_fnColumnIndexToVisible: _fnColumnIndexToVisible,
15031		_fnVisbleColumns: _fnVisbleColumns,
15032		_fnGetColumns: _fnGetColumns,
15033		_fnColumnTypes: _fnColumnTypes,
15034		_fnApplyColumnDefs: _fnApplyColumnDefs,
15035		_fnHungarianMap: _fnHungarianMap,
15036		_fnCamelToHungarian: _fnCamelToHungarian,
15037		_fnLanguageCompat: _fnLanguageCompat,
15038		_fnBrowserDetect: _fnBrowserDetect,
15039		_fnAddData: _fnAddData,
15040		_fnAddTr: _fnAddTr,
15041		_fnNodeToDataIndex: _fnNodeToDataIndex,
15042		_fnNodeToColumnIndex: _fnNodeToColumnIndex,
15043		_fnGetCellData: _fnGetCellData,
15044		_fnSetCellData: _fnSetCellData,
15045		_fnSplitObjNotation: _fnSplitObjNotation,
15046		_fnGetObjectDataFn: _fnGetObjectDataFn,
15047		_fnSetObjectDataFn: _fnSetObjectDataFn,
15048		_fnGetDataMaster: _fnGetDataMaster,
15049		_fnClearTable: _fnClearTable,
15050		_fnDeleteIndex: _fnDeleteIndex,
15051		_fnInvalidate: _fnInvalidate,
15052		_fnGetRowElements: _fnGetRowElements,
15053		_fnCreateTr: _fnCreateTr,
15054		_fnBuildHead: _fnBuildHead,
15055		_fnDrawHead: _fnDrawHead,
15056		_fnDraw: _fnDraw,
15057		_fnReDraw: _fnReDraw,
15058		_fnAddOptionsHtml: _fnAddOptionsHtml,
15059		_fnDetectHeader: _fnDetectHeader,
15060		_fnGetUniqueThs: _fnGetUniqueThs,
15061		_fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15062		_fnFilterComplete: _fnFilterComplete,
15063		_fnFilterCustom: _fnFilterCustom,
15064		_fnFilterColumn: _fnFilterColumn,
15065		_fnFilter: _fnFilter,
15066		_fnFilterCreateSearch: _fnFilterCreateSearch,
15067		_fnEscapeRegex: _fnEscapeRegex,
15068		_fnFilterData: _fnFilterData,
15069		_fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15070		_fnUpdateInfo: _fnUpdateInfo,
15071		_fnInfoMacros: _fnInfoMacros,
15072		_fnInitialise: _fnInitialise,
15073		_fnInitComplete: _fnInitComplete,
15074		_fnLengthChange: _fnLengthChange,
15075		_fnFeatureHtmlLength: _fnFeatureHtmlLength,
15076		_fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15077		_fnPageChange: _fnPageChange,
15078		_fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15079		_fnProcessingDisplay: _fnProcessingDisplay,
15080		_fnFeatureHtmlTable: _fnFeatureHtmlTable,
15081		_fnScrollDraw: _fnScrollDraw,
15082		_fnApplyToChildren: _fnApplyToChildren,
15083		_fnCalculateColumnWidths: _fnCalculateColumnWidths,
15084		_fnThrottle: _fnThrottle,
15085		_fnConvertToWidth: _fnConvertToWidth,
15086		_fnGetWidestNode: _fnGetWidestNode,
15087		_fnGetMaxLenString: _fnGetMaxLenString,
15088		_fnStringToCss: _fnStringToCss,
15089		_fnSortFlatten: _fnSortFlatten,
15090		_fnSort: _fnSort,
15091		_fnSortAria: _fnSortAria,
15092		_fnSortListener: _fnSortListener,
15093		_fnSortAttachListener: _fnSortAttachListener,
15094		_fnSortingClasses: _fnSortingClasses,
15095		_fnSortData: _fnSortData,
15096		_fnSaveState: _fnSaveState,
15097		_fnLoadState: _fnLoadState,
15098		_fnSettingsFromNode: _fnSettingsFromNode,
15099		_fnLog: _fnLog,
15100		_fnMap: _fnMap,
15101		_fnBindAction: _fnBindAction,
15102		_fnCallbackReg: _fnCallbackReg,
15103		_fnCallbackFire: _fnCallbackFire,
15104		_fnLengthOverflow: _fnLengthOverflow,
15105		_fnRenderer: _fnRenderer,
15106		_fnDataSource: _fnDataSource,
15107		_fnRowAttributes: _fnRowAttributes,
15108		_fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15109		                                // in 1.10, so this dead-end function is
15110		                                // added to prevent errors
15111	} );
15112	
15113
15114	// jQuery access
15115	$.fn.dataTable = DataTable;
15116
15117	// Provide access to the host jQuery object (circular reference)
15118	DataTable.$ = $;
15119
15120	// Legacy aliases
15121	$.fn.dataTableSettings = DataTable.settings;
15122	$.fn.dataTableExt = DataTable.ext;
15123
15124	// With a capital `D` we return a DataTables API instance rather than a
15125	// jQuery object
15126	$.fn.DataTable = function ( opts ) {
15127		return $(this).dataTable( opts ).api();
15128	};
15129
15130	// All properties that are available to $.fn.dataTable should also be
15131	// available on $.fn.DataTable
15132	$.each( DataTable, function ( prop, val ) {
15133		$.fn.DataTable[ prop ] = val;
15134	} );
15135
15136
15137	// Information about events fired by DataTables - for documentation.
15138	/**
15139	 * Draw event, fired whenever the table is redrawn on the page, at the same
15140	 * point as fnDrawCallback. This may be useful for binding events or
15141	 * performing calculations when the table is altered at all.
15142	 *  @name DataTable#draw.dt
15143	 *  @event
15144	 *  @param {event} e jQuery event object
15145	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15146	 */
15147
15148	/**
15149	 * Search event, fired when the searching applied to the table (using the
15150	 * built-in global search, or column filters) is altered.
15151	 *  @name DataTable#search.dt
15152	 *  @event
15153	 *  @param {event} e jQuery event object
15154	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15155	 */
15156
15157	/**
15158	 * Page change event, fired when the paging of the table is altered.
15159	 *  @name DataTable#page.dt
15160	 *  @event
15161	 *  @param {event} e jQuery event object
15162	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15163	 */
15164
15165	/**
15166	 * Order event, fired when the ordering applied to the table is altered.
15167	 *  @name DataTable#order.dt
15168	 *  @event
15169	 *  @param {event} e jQuery event object
15170	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15171	 */
15172
15173	/**
15174	 * DataTables initialisation complete event, fired when the table is fully
15175	 * drawn, including Ajax data loaded, if Ajax data is required.
15176	 *  @name DataTable#init.dt
15177	 *  @event
15178	 *  @param {event} e jQuery event object
15179	 *  @param {object} oSettings DataTables settings object
15180	 *  @param {object} json The JSON object request from the server - only
15181	 *    present if client-side Ajax sourced data is used</li></ol>
15182	 */
15183
15184	/**
15185	 * State save event, fired when the table has changed state a new state save
15186	 * is required. This event allows modification of the state saving object
15187	 * prior to actually doing the save, including addition or other state
15188	 * properties (for plug-ins) or modification of a DataTables core property.
15189	 *  @name DataTable#stateSaveParams.dt
15190	 *  @event
15191	 *  @param {event} e jQuery event object
15192	 *  @param {object} oSettings DataTables settings object
15193	 *  @param {object} json The state information to be saved
15194	 */
15195
15196	/**
15197	 * State load event, fired when the table is loading state from the stored
15198	 * data, but prior to the settings object being modified by the saved state
15199	 * - allowing modification of the saved state is required or loading of
15200	 * state for a plug-in.
15201	 *  @name DataTable#stateLoadParams.dt
15202	 *  @event
15203	 *  @param {event} e jQuery event object
15204	 *  @param {object} oSettings DataTables settings object
15205	 *  @param {object} json The saved state information
15206	 */
15207
15208	/**
15209	 * State loaded event, fired when state has been loaded from stored data and
15210	 * the settings object has been modified by the loaded data.
15211	 *  @name DataTable#stateLoaded.dt
15212	 *  @event
15213	 *  @param {event} e jQuery event object
15214	 *  @param {object} oSettings DataTables settings object
15215	 *  @param {object} json The saved state information
15216	 */
15217
15218	/**
15219	 * Processing event, fired when DataTables is doing some kind of processing
15220	 * (be it, order, searcg or anything else). It can be used to indicate to
15221	 * the end user that there is something happening, or that something has
15222	 * finished.
15223	 *  @name DataTable#processing.dt
15224	 *  @event
15225	 *  @param {event} e jQuery event object
15226	 *  @param {object} oSettings DataTables settings object
15227	 *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15228	 */
15229
15230	/**
15231	 * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15232	 * request to made to the server for new data. This event is called before
15233	 * DataTables processed the returned data, so it can also be used to pre-
15234	 * process the data returned from the server, if needed.
15235	 *
15236	 * Note that this trigger is called in `fnServerData`, if you override
15237	 * `fnServerData` and which to use this event, you need to trigger it in you
15238	 * success function.
15239	 *  @name DataTable#xhr.dt
15240	 *  @event
15241	 *  @param {event} e jQuery event object
15242	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15243	 *  @param {object} json JSON returned from the server
15244	 *
15245	 *  @example
15246	 *     // Use a custom property returned from the server in another DOM element
15247	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15248	 *       $('#status').html( json.status );
15249	 *     } );
15250	 *
15251	 *  @example
15252	 *     // Pre-process the data returned from the server
15253	 *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15254	 *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15255	 *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15256	 *       }
15257	 *       // Note no return - manipulate the data directly in the JSON object.
15258	 *     } );
15259	 */
15260
15261	/**
15262	 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15263	 * or passing the bDestroy:true parameter in the initialisation object. This
15264	 * can be used to remove bound events, added DOM nodes, etc.
15265	 *  @name DataTable#destroy.dt
15266	 *  @event
15267	 *  @param {event} e jQuery event object
15268	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15269	 */
15270
15271	/**
15272	 * Page length change event, fired when number of records to show on each
15273	 * page (the length) is changed.
15274	 *  @name DataTable#length.dt
15275	 *  @event
15276	 *  @param {event} e jQuery event object
15277	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15278	 *  @param {integer} len New length
15279	 */
15280
15281	/**
15282	 * Column sizing has changed.
15283	 *  @name DataTable#column-sizing.dt
15284	 *  @event
15285	 *  @param {event} e jQuery event object
15286	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15287	 */
15288
15289	/**
15290	 * Column visibility has changed.
15291	 *  @name DataTable#column-visibility.dt
15292	 *  @event
15293	 *  @param {event} e jQuery event object
15294	 *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15295	 *  @param {int} column Column index
15296	 *  @param {bool} vis `false` if column now hidden, or `true` if visible
15297	 */
15298
15299	return $.fn.dataTable;
15300}));
15301
15302
15303/*! DataTables Bootstrap 3 integration
15304 * ©2011-2015 SpryMedia Ltd - datatables.net/license
15305 */
15306
15307/**
15308 * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
15309 * DataTables 1.10 or newer.
15310 *
15311 * This file sets the defaults and adds options to DataTables to style its
15312 * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
15313 * for further information.
15314 */
15315(function( factory ){
15316	if ( typeof define === 'function' && define.amd ) {
15317		// AMD
15318		define( ['jquery', 'datatables.net'], function ( $ ) {
15319			return factory( $, window, document );
15320		} );
15321	}
15322	else if ( typeof exports === 'object' ) {
15323		// CommonJS
15324		module.exports = function (root, $) {
15325			if ( ! root ) {
15326				root = window;
15327			}
15328
15329			if ( ! $ || ! $.fn.dataTable ) {
15330				// Require DataTables, which attaches to jQuery, including
15331				// jQuery if needed and have a $ property so we can access the
15332				// jQuery object that is used
15333				$ = require('datatables.net')(root, $).$;
15334			}
15335
15336			return factory( $, root, root.document );
15337		};
15338	}
15339	else {
15340		// Browser
15341		factory( jQuery, window, document );
15342	}
15343}(function( $, window, document, undefined ) {
15344'use strict';
15345var DataTable = $.fn.dataTable;
15346
15347
15348/* Set the defaults for DataTables initialisation */
15349$.extend( true, DataTable.defaults, {
15350	dom:
15351		"<'row'<'col-sm-6'l><'col-sm-6'f>>" +
15352		"<'row'<'col-sm-12'tr>>" +
15353		"<'row'<'col-sm-5'i><'col-sm-7'p>>",
15354	renderer: 'bootstrap'
15355} );
15356
15357
15358/* Default class modification */
15359$.extend( DataTable.ext.classes, {
15360	sWrapper:      "dataTables_wrapper form-inline dt-bootstrap",
15361	sFilterInput:  "form-control input-sm",
15362	sLengthSelect: "form-control input-sm",
15363	sProcessing:   "dataTables_processing panel panel-default"
15364} );
15365
15366
15367/* Bootstrap paging button renderer */
15368DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
15369	var api     = new DataTable.Api( settings );
15370	var classes = settings.oClasses;
15371	var lang    = settings.oLanguage.oPaginate;
15372	var aria = settings.oLanguage.oAria.paginate || {};
15373	var btnDisplay, btnClass, counter=0;
15374
15375	var attach = function( container, buttons ) {
15376		var i, ien, node, button;
15377		var clickHandler = function ( e ) {
15378			e.preventDefault();
15379			if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
15380				api.page( e.data.action ).draw( 'page' );
15381			}
15382		};
15383
15384		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
15385			button = buttons[i];
15386
15387			if ( $.isArray( button ) ) {
15388				attach( container, button );
15389			}
15390			else {
15391				btnDisplay = '';
15392				btnClass = '';
15393
15394				switch ( button ) {
15395					case 'ellipsis':
15396						btnDisplay = '&#x2026;';
15397						btnClass = 'disabled';
15398						break;
15399
15400					case 'first':
15401						btnDisplay = lang.sFirst;
15402						btnClass = button + (page > 0 ?
15403							'' : ' disabled');
15404						break;
15405
15406					case 'previous':
15407						btnDisplay = lang.sPrevious;
15408						btnClass = button + (page > 0 ?
15409							'' : ' disabled');
15410						break;
15411
15412					case 'next':
15413						btnDisplay = lang.sNext;
15414						btnClass = button + (page < pages-1 ?
15415							'' : ' disabled');
15416						break;
15417
15418					case 'last':
15419						btnDisplay = lang.sLast;
15420						btnClass = button + (page < pages-1 ?
15421							'' : ' disabled');
15422						break;
15423
15424					default:
15425						btnDisplay = button + 1;
15426						btnClass = page === button ?
15427							'active' : '';
15428						break;
15429				}
15430
15431				if ( btnDisplay ) {
15432					node = $('<li>', {
15433							'class': classes.sPageButton+' '+btnClass,
15434							'id': idx === 0 && typeof button === 'string' ?
15435								settings.sTableId +'_'+ button :
15436								null
15437						} )
15438						.append( $('<a>', {
15439								'href': '#',
15440								'aria-controls': settings.sTableId,
15441								'aria-label': aria[ button ],
15442								'data-dt-idx': counter,
15443								'tabindex': settings.iTabIndex
15444							} )
15445							.html( btnDisplay )
15446						)
15447						.appendTo( container );
15448
15449					settings.oApi._fnBindAction(
15450						node, {action: button}, clickHandler
15451					);
15452
15453					counter++;
15454				}
15455			}
15456		}
15457	};
15458
15459	// IE9 throws an 'unknown error' if document.activeElement is used
15460	// inside an iframe or frame. 
15461	var activeEl;
15462
15463	try {
15464		// Because this approach is destroying and recreating the paging
15465		// elements, focus is lost on the select button which is bad for
15466		// accessibility. So we want to restore focus once the draw has
15467		// completed
15468		activeEl = $(host).find(document.activeElement).data('dt-idx');
15469	}
15470	catch (e) {}
15471
15472	attach(
15473		$(host).empty().html('<ul class="pagination"/>').children('ul'),
15474		buttons
15475	);
15476
15477	if ( activeEl !== undefined ) {
15478		$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
15479	}
15480};
15481
15482
15483return DataTable;
15484}));
15485
15486
15487/*! Responsive 2.2.1
15488 * 2014-2017 SpryMedia Ltd - datatables.net/license
15489 */
15490
15491/**
15492 * @summary     Responsive
15493 * @description Responsive tables plug-in for DataTables
15494 * @version     2.2.1
15495 * @file        dataTables.responsive.js
15496 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
15497 * @contact     www.sprymedia.co.uk/contact
15498 * @copyright   Copyright 2014-2017 SpryMedia Ltd.
15499 *
15500 * This source file is free software, available under the following license:
15501 *   MIT license - http://datatables.net/license/mit
15502 *
15503 * This source file is distributed in the hope that it will be useful, but
15504 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15505 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
15506 *
15507 * For details please refer to: http://www.datatables.net
15508 */
15509(function( factory ){
15510	if ( typeof define === 'function' && define.amd ) {
15511		// AMD
15512		define( ['jquery', 'datatables.net'], function ( $ ) {
15513			return factory( $, window, document );
15514		} );
15515	}
15516	else if ( typeof exports === 'object' ) {
15517		// CommonJS
15518		module.exports = function (root, $) {
15519			if ( ! root ) {
15520				root = window;
15521			}
15522
15523			if ( ! $ || ! $.fn.dataTable ) {
15524				$ = require('datatables.net')(root, $).$;
15525			}
15526
15527			return factory( $, root, root.document );
15528		};
15529	}
15530	else {
15531		// Browser
15532		factory( jQuery, window, document );
15533	}
15534}(function( $, window, document, undefined ) {
15535'use strict';
15536var DataTable = $.fn.dataTable;
15537
15538
15539/**
15540 * Responsive is a plug-in for the DataTables library that makes use of
15541 * DataTables' ability to change the visibility of columns, changing the
15542 * visibility of columns so the displayed columns fit into the table container.
15543 * The end result is that complex tables will be dynamically adjusted to fit
15544 * into the viewport, be it on a desktop, tablet or mobile browser.
15545 *
15546 * Responsive for DataTables has two modes of operation, which can used
15547 * individually or combined:
15548 *
15549 * * Class name based control - columns assigned class names that match the
15550 *   breakpoint logic can be shown / hidden as required for each breakpoint.
15551 * * Automatic control - columns are automatically hidden when there is no
15552 *   room left to display them. Columns removed from the right.
15553 *
15554 * In additional to column visibility control, Responsive also has built into
15555 * options to use DataTables' child row display to show / hide the information
15556 * from the table that has been hidden. There are also two modes of operation
15557 * for this child row display:
15558 *
15559 * * Inline - when the control element that the user can use to show / hide
15560 *   child rows is displayed inside the first column of the table.
15561 * * Column - where a whole column is dedicated to be the show / hide control.
15562 *
15563 * Initialisation of Responsive is performed by:
15564 *
15565 * * Adding the class `responsive` or `dt-responsive` to the table. In this case
15566 *   Responsive will automatically be initialised with the default configuration
15567 *   options when the DataTable is created.
15568 * * Using the `responsive` option in the DataTables configuration options. This
15569 *   can also be used to specify the configuration options, or simply set to
15570 *   `true` to use the defaults.
15571 *
15572 *  @class
15573 *  @param {object} settings DataTables settings object for the host table
15574 *  @param {object} [opts] Configuration options
15575 *  @requires jQuery 1.7+
15576 *  @requires DataTables 1.10.3+
15577 *
15578 *  @example
15579 *      $('#example').DataTable( {
15580 *        responsive: true
15581 *      } );
15582 *    } );
15583 */
15584var Responsive = function ( settings, opts ) {
15585	// Sanity check that we are using DataTables 1.10 or newer
15586	if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.10' ) ) {
15587		throw 'DataTables Responsive requires DataTables 1.10.10 or newer';
15588	}
15589
15590	this.s = {
15591		dt: new DataTable.Api( settings ),
15592		columns: [],
15593		current: []
15594	};
15595
15596	// Check if responsive has already been initialised on this table
15597	if ( this.s.dt.settings()[0].responsive ) {
15598		return;
15599	}
15600
15601	// details is an object, but for simplicity the user can give it as a string
15602	// or a boolean
15603	if ( opts && typeof opts.details === 'string' ) {
15604		opts.details = { type: opts.details };
15605	}
15606	else if ( opts && opts.details === false ) {
15607		opts.details = { type: false };
15608	}
15609	else if ( opts && opts.details === true ) {
15610		opts.details = { type: 'inline' };
15611	}
15612
15613	this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
15614	settings.responsive = this;
15615	this._constructor();
15616};
15617
15618$.extend( Responsive.prototype, {
15619	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15620	 * Constructor
15621	 */
15622
15623	/**
15624	 * Initialise the Responsive instance
15625	 *
15626	 * @private
15627	 */
15628	_constructor: function ()
15629	{
15630		var that = this;
15631		var dt = this.s.dt;
15632		var dtPrivateSettings = dt.settings()[0];
15633		var oldWindowWidth = $(window).width();
15634
15635		dt.settings()[0]._responsive = this;
15636
15637		// Use DataTables' throttle function to avoid processor thrashing on
15638		// resize
15639		$(window).on( 'resize.dtr orientationchange.dtr', DataTable.util.throttle( function () {
15640			// iOS has a bug whereby resize can fire when only scrolling
15641			// See: http://stackoverflow.com/questions/8898412
15642			var width = $(window).width();
15643
15644			if ( width !== oldWindowWidth ) {
15645				that._resize();
15646				oldWindowWidth = width;
15647			}
15648		} ) );
15649
15650		// DataTables doesn't currently trigger an event when a row is added, so
15651		// we need to hook into its private API to enforce the hidden rows when
15652		// new data is added
15653		dtPrivateSettings.oApi._fnCallbackReg( dtPrivateSettings, 'aoRowCreatedCallback', function (tr, data, idx) {
15654			if ( $.inArray( false, that.s.current ) !== -1 ) {
15655				$('>td, >th', tr).each( function ( i ) {
15656					var idx = dt.column.index( 'toData', i );
15657
15658					if ( that.s.current[idx] === false ) {
15659						$(this).css('display', 'none');
15660					}
15661				} );
15662			}
15663		} );
15664
15665		// Destroy event handler
15666		dt.on( 'destroy.dtr', function () {
15667			dt.off( '.dtr' );
15668			$( dt.table().body() ).off( '.dtr' );
15669			$(window).off( 'resize.dtr orientationchange.dtr' );
15670
15671			// Restore the columns that we've hidden
15672			$.each( that.s.current, function ( i, val ) {
15673				if ( val === false ) {
15674					that._setColumnVis( i, true );
15675				}
15676			} );
15677		} );
15678
15679		// Reorder the breakpoints array here in case they have been added out
15680		// of order
15681		this.c.breakpoints.sort( function (a, b) {
15682			return a.width < b.width ? 1 :
15683				a.width > b.width ? -1 : 0;
15684		} );
15685
15686		this._classLogic();
15687		this._resizeAuto();
15688
15689		// Details handler
15690		var details = this.c.details;
15691
15692		if ( details.type !== false ) {
15693			that._detailsInit();
15694
15695			// DataTables will trigger this event on every column it shows and
15696			// hides individually
15697			dt.on( 'column-visibility.dtr', function (e, ctx, col, vis, recalc) {
15698				if ( recalc ) {
15699					that._classLogic();
15700					that._resizeAuto();
15701					that._resize();
15702				}
15703			} );
15704
15705			// Redraw the details box on each draw which will happen if the data
15706			// has changed. This is used until DataTables implements a native
15707			// `updated` event for rows
15708			dt.on( 'draw.dtr', function () {
15709				that._redrawChildren();
15710			} );
15711
15712			$(dt.table().node()).addClass( 'dtr-'+details.type );
15713		}
15714
15715		dt.on( 'column-reorder.dtr', function (e, settings, details) {
15716			that._classLogic();
15717			that._resizeAuto();
15718			that._resize();
15719		} );
15720
15721		// Change in column sizes means we need to calc
15722		dt.on( 'column-sizing.dtr', function () {
15723			that._resizeAuto();
15724			that._resize();
15725		});
15726
15727		// On Ajax reload we want to reopen any child rows which are displayed
15728		// by responsive
15729		dt.on( 'preXhr.dtr', function () {
15730			var rowIds = [];
15731			dt.rows().every( function () {
15732				if ( this.child.isShown() ) {
15733					rowIds.push( this.id(true) );
15734				}
15735			} );
15736
15737			dt.one( 'draw.dtr', function () {
15738				that._resizeAuto();
15739				that._resize();
15740
15741				dt.rows( rowIds ).every( function () {
15742					that._detailsDisplay( this, false );
15743				} );
15744			} );
15745		});
15746
15747		dt.on( 'init.dtr', function (e, settings, details) {
15748			that._resizeAuto();
15749			that._resize();
15750
15751			// If columns were hidden, then DataTables needs to adjust the
15752			// column sizing
15753			if ( $.inArray( false, that.s.current ) ) {
15754				dt.columns.adjust();
15755			}
15756		} );
15757
15758		// First pass - draw the table for the current viewport size
15759		this._resize();
15760	},
15761
15762
15763	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
15764	 * Private methods
15765	 */
15766
15767	/**
15768	 * Calculate the visibility for the columns in a table for a given
15769	 * breakpoint. The result is pre-determined based on the class logic if
15770	 * class names are used to control all columns, but the width of the table
15771	 * is also used if there are columns which are to be automatically shown
15772	 * and hidden.
15773	 *
15774	 * @param  {string} breakpoint Breakpoint name to use for the calculation
15775	 * @return {array} Array of boolean values initiating the visibility of each
15776	 *   column.
15777	 *  @private
15778	 */
15779	_columnsVisiblity: function ( breakpoint )
15780	{
15781		var dt = this.s.dt;
15782		var columns = this.s.columns;
15783		var i, ien;
15784
15785		// Create an array that defines the column ordering based first on the
15786		// column's priority, and secondly the column index. This allows the
15787		// columns to be removed from the right if the priority matches
15788		var order = columns
15789			.map( function ( col, idx ) {
15790				return {
15791					columnIdx: idx,
15792					priority: col.priority
15793				};
15794			} )
15795			.sort( function ( a, b ) {
15796				if ( a.priority !== b.priority ) {
15797					return a.priority - b.priority;
15798				}
15799				return a.columnIdx - b.columnIdx;
15800			} );
15801
15802		// Class logic - determine which columns are in this breakpoint based
15803		// on the classes. If no class control (i.e. `auto`) then `-` is used
15804		// to indicate this to the rest of the function
15805		var display = $.map( columns, function ( col ) {
15806			return col.auto && col.minWidth === null ?
15807				false :
15808				col.auto === true ?
15809					'-' :
15810					$.inArray( breakpoint, col.includeIn ) !== -1;
15811		} );
15812
15813		// Auto column control - first pass: how much width is taken by the
15814		// ones that must be included from the non-auto columns
15815		var requiredWidth = 0;
15816		for ( i=0, ien=display.length ; i<ien ; i++ ) {
15817			if ( display[i] === true ) {
15818				requiredWidth += columns[i].minWidth;
15819			}
15820		}
15821
15822		// Second pass, use up any remaining width for other columns. For
15823		// scrolling tables we need to subtract the width of the scrollbar. It
15824		// may not be requires which makes this sub-optimal, but it would
15825		// require another full redraw to make complete use of those extra few
15826		// pixels
15827		var scrolling = dt.settings()[0].oScroll;
15828		var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
15829		var widthAvailable = dt.table().container().offsetWidth - bar;
15830		var usedWidth = widthAvailable - requiredWidth;
15831
15832		// Control column needs to always be included. This makes it sub-
15833		// optimal in terms of using the available with, but to stop layout
15834		// thrashing or overflow. Also we need to account for the control column
15835		// width first so we know how much width is available for the other
15836		// columns, since the control column might not be the first one shown
15837		for ( i=0, ien=display.length ; i<ien ; i++ ) {
15838			if ( columns[i].control ) {
15839				usedWidth -= columns[i].minWidth;
15840			}
15841		}
15842
15843		// Allow columns to be shown (counting by priority and then right to
15844		// left) until we run out of room
15845		var empty = false;
15846		for ( i=0, ien=order.length ; i<ien ; i++ ) {
15847			var colIdx = order[i].columnIdx;
15848
15849			if ( display[colIdx] === '-' && ! columns[colIdx].control && columns[colIdx].minWidth ) {
15850				// Once we've found a column that won't fit we don't let any
15851				// others display either, or columns might disappear in the
15852				// middle of the table
15853				if ( empty || usedWidth - columns[colIdx].minWidth < 0 ) {
15854					empty = true;
15855					display[colIdx] = false;
15856				}
15857				else {
15858					display[colIdx] = true;
15859				}
15860
15861				usedWidth -= columns[colIdx].minWidth;
15862			}
15863		}
15864
15865		// Determine if the 'control' column should be shown (if there is one).
15866		// This is the case when there is a hidden column (that is not the
15867		// control column). The two loops look inefficient here, but they are
15868		// trivial and will fly through. We need to know the outcome from the
15869		// first , before the action in the second can be taken
15870		var showControl = false;
15871
15872		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
15873			if ( ! columns[i].control && ! columns[i].never && ! display[i] ) {
15874				showControl = true;
15875				break;
15876			}
15877		}
15878
15879		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
15880			if ( columns[i].control ) {
15881				display[i] = showControl;
15882			}
15883		}
15884
15885		// Finally we need to make sure that there is at least one column that
15886		// is visible
15887		if ( $.inArray( true, display ) === -1 ) {
15888			display[0] = true;
15889		}
15890
15891		return display;
15892	},
15893
15894
15895	/**
15896	 * Create the internal `columns` array with information about the columns
15897	 * for the table. This includes determining which breakpoints the column
15898	 * will appear in, based upon class names in the column, which makes up the
15899	 * vast majority of this method.
15900	 *
15901	 * @private
15902	 */
15903	_classLogic: function ()
15904	{
15905		var that = this;
15906		var calc = {};
15907		var breakpoints = this.c.breakpoints;
15908		var dt = this.s.dt;
15909		var columns = dt.columns().eq(0).map( function (i) {
15910			var column = this.column(i);
15911			var className = column.header().className;
15912			var priority = dt.settings()[0].aoColumns[i].responsivePriority;
15913
15914			if ( priority === undefined ) {
15915				var dataPriority = $(column.header()).data('priority');
15916
15917				priority = dataPriority !== undefined ?
15918					dataPriority * 1 :
15919					10000;
15920			}
15921
15922			return {
15923				className: className,
15924				includeIn: [],
15925				auto:      false,
15926				control:   false,
15927				never:     className.match(/\bnever\b/) ? true : false,
15928				priority:  priority
15929			};
15930		} );
15931
15932		// Simply add a breakpoint to `includeIn` array, ensuring that there are
15933		// no duplicates
15934		var add = function ( colIdx, name ) {
15935			var includeIn = columns[ colIdx ].includeIn;
15936
15937			if ( $.inArray( name, includeIn ) === -1 ) {
15938				includeIn.push( name );
15939			}
15940		};
15941
15942		var column = function ( colIdx, name, operator, matched ) {
15943			var size, i, ien;
15944
15945			if ( ! operator ) {
15946				columns[ colIdx ].includeIn.push( name );
15947			}
15948			else if ( operator === 'max-' ) {
15949				// Add this breakpoint and all smaller
15950				size = that._find( name ).width;
15951
15952				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
15953					if ( breakpoints[i].width <= size ) {
15954						add( colIdx, breakpoints[i].name );
15955					}
15956				}
15957			}
15958			else if ( operator === 'min-' ) {
15959				// Add this breakpoint and all larger
15960				size = that._find( name ).width;
15961
15962				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
15963					if ( breakpoints[i].width >= size ) {
15964						add( colIdx, breakpoints[i].name );
15965					}
15966				}
15967			}
15968			else if ( operator === 'not-' ) {
15969				// Add all but this breakpoint
15970				for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
15971					if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
15972						add( colIdx, breakpoints[i].name );
15973					}
15974				}
15975			}
15976		};
15977
15978		// Loop over each column and determine if it has a responsive control
15979		// class
15980		columns.each( function ( col, i ) {
15981			var classNames = col.className.split(' ');
15982			var hasClass = false;
15983
15984			// Split the class name up so multiple rules can be applied if needed
15985			for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
15986				var className = $.trim( classNames[k] );
15987
15988				if ( className === 'all' ) {
15989					// Include in all
15990					hasClass = true;
15991					col.includeIn = $.map( breakpoints, function (a) {
15992						return a.name;
15993					} );
15994					return;
15995				}
15996				else if ( className === 'none' || col.never ) {
15997					// Include in none (default) and no auto
15998					hasClass = true;
15999					return;
16000				}
16001				else if ( className === 'control' ) {
16002					// Special column that is only visible, when one of the other
16003					// columns is hidden. This is used for the details control
16004					hasClass = true;
16005					col.control = true;
16006					return;
16007				}
16008
16009				$.each( breakpoints, function ( j, breakpoint ) {
16010					// Does this column have a class that matches this breakpoint?
16011					var brokenPoint = breakpoint.name.split('-');
16012					var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
16013					var match = className.match( re );
16014
16015					if ( match ) {
16016						hasClass = true;
16017
16018						if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
16019							// Class name matches breakpoint name fully
16020							column( i, breakpoint.name, match[1], match[2]+match[3] );
16021						}
16022						else if ( match[2] === brokenPoint[0] && ! match[3] ) {
16023							// Class name matched primary breakpoint name with no qualifier
16024							column( i, breakpoint.name, match[1], match[2] );
16025						}
16026					}
16027				} );
16028			}
16029
16030			// If there was no control class, then automatic sizing is used
16031			if ( ! hasClass ) {
16032				col.auto = true;
16033			}
16034		} );
16035
16036		this.s.columns = columns;
16037	},
16038
16039
16040	/**
16041	 * Show the details for the child row
16042	 *
16043	 * @param  {DataTables.Api} row    API instance for the row
16044	 * @param  {boolean}        update Update flag
16045	 * @private
16046	 */
16047	_detailsDisplay: function ( row, update )
16048	{
16049		var that = this;
16050		var dt = this.s.dt;
16051		var details = this.c.details;
16052
16053		if ( details && details.type !== false ) {
16054			var res = details.display( row, update, function () {
16055				return details.renderer(
16056					dt, row[0], that._detailsObj(row[0])
16057				);
16058			} );
16059
16060			if ( res === true || res === false ) {
16061				$(dt.table().node()).triggerHandler( 'responsive-display.dt', [dt, row, res, update] );
16062			}
16063		}
16064	},
16065
16066
16067	/**
16068	 * Initialisation for the details handler
16069	 *
16070	 * @private
16071	 */
16072	_detailsInit: function ()
16073	{
16074		var that    = this;
16075		var dt      = this.s.dt;
16076		var details = this.c.details;
16077
16078		// The inline type always uses the first child as the target
16079		if ( details.type === 'inline' ) {
16080			details.target = 'td:first-child, th:first-child';
16081		}
16082
16083		// Keyboard accessibility
16084		dt.on( 'draw.dtr', function () {
16085			that._tabIndexes();
16086		} );
16087		that._tabIndexes(); // Initial draw has already happened
16088
16089		$( dt.table().body() ).on( 'keyup.dtr', 'td, th', function (e) {
16090			if ( e.keyCode === 13 && $(this).data('dtr-keyboard') ) {
16091				$(this).click();
16092			}
16093		} );
16094
16095		// type.target can be a string jQuery selector or a column index
16096		var target   = details.target;
16097		var selector = typeof target === 'string' ? target : 'td, th';
16098
16099		// Click handler to show / hide the details rows when they are available
16100		$( dt.table().body() )
16101			.on( 'click.dtr mousedown.dtr mouseup.dtr', selector, function (e) {
16102				// If the table is not collapsed (i.e. there is no hidden columns)
16103				// then take no action
16104				if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
16105					return;
16106				}
16107
16108				// Check that the row is actually a DataTable's controlled node
16109				if ( $.inArray( $(this).closest('tr').get(0), dt.rows().nodes().toArray() ) === -1 ) {
16110					return;
16111				}
16112
16113				// For column index, we determine if we should act or not in the
16114				// handler - otherwise it is already okay
16115				if ( typeof target === 'number' ) {
16116					var targetIdx = target < 0 ?
16117						dt.columns().eq(0).length + target :
16118						target;
16119
16120					if ( dt.cell( this ).index().column !== targetIdx ) {
16121						return;
16122					}
16123				}
16124
16125				// $().closest() includes itself in its check
16126				var row = dt.row( $(this).closest('tr') );
16127
16128				// Check event type to do an action
16129				if ( e.type === 'click' ) {
16130					// The renderer is given as a function so the caller can execute it
16131					// only when they need (i.e. if hiding there is no point is running
16132					// the renderer)
16133					that._detailsDisplay( row, false );
16134				}
16135				else if ( e.type === 'mousedown' ) {
16136					// For mouse users, prevent the focus ring from showing
16137					$(this).css('outline', 'none');
16138				}
16139				else if ( e.type === 'mouseup' ) {
16140					// And then re-allow at the end of the click
16141					$(this).blur().css('outline', '');
16142				}
16143			} );
16144	},
16145
16146
16147	/**
16148	 * Get the details to pass to a renderer for a row
16149	 * @param  {int} rowIdx Row index
16150	 * @private
16151	 */
16152	_detailsObj: function ( rowIdx )
16153	{
16154		var that = this;
16155		var dt = this.s.dt;
16156
16157		return $.map( this.s.columns, function( col, i ) {
16158			// Never and control columns should not be passed to the renderer
16159			if ( col.never || col.control ) {
16160				return;
16161			}
16162
16163			return {
16164				title:       dt.settings()[0].aoColumns[ i ].sTitle,
16165				data:        dt.cell( rowIdx, i ).render( that.c.orthogonal ),
16166				hidden:      dt.column( i ).visible() && !that.s.current[ i ],
16167				columnIndex: i,
16168				rowIndex:    rowIdx
16169			};
16170		} );
16171	},
16172
16173
16174	/**
16175	 * Find a breakpoint object from a name
16176	 *
16177	 * @param  {string} name Breakpoint name to find
16178	 * @return {object}      Breakpoint description object
16179	 * @private
16180	 */
16181	_find: function ( name )
16182	{
16183		var breakpoints = this.c.breakpoints;
16184
16185		for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
16186			if ( breakpoints[i].name === name ) {
16187				return breakpoints[i];
16188			}
16189		}
16190	},
16191
16192
16193	/**
16194	 * Re-create the contents of the child rows as the display has changed in
16195	 * some way.
16196	 *
16197	 * @private
16198	 */
16199	_redrawChildren: function ()
16200	{
16201		var that = this;
16202		var dt = this.s.dt;
16203
16204		dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
16205			var row = dt.row( idx );
16206
16207			that._detailsDisplay( dt.row( idx ), true );
16208		} );
16209	},
16210
16211
16212	/**
16213	 * Alter the table display for a resized viewport. This involves first
16214	 * determining what breakpoint the window currently is in, getting the
16215	 * column visibilities to apply and then setting them.
16216	 *
16217	 * @private
16218	 */
16219	_resize: function ()
16220	{
16221		var that = this;
16222		var dt = this.s.dt;
16223		var width = $(window).width();
16224		var breakpoints = this.c.breakpoints;
16225		var breakpoint = breakpoints[0].name;
16226		var columns = this.s.columns;
16227		var i, ien;
16228		var oldVis = this.s.current.slice();
16229
16230		// Determine what breakpoint we are currently at
16231		for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
16232			if ( width <= breakpoints[i].width ) {
16233				breakpoint = breakpoints[i].name;
16234				break;
16235			}
16236		}
16237		
16238		// Show the columns for that break point
16239		var columnsVis = this._columnsVisiblity( breakpoint );
16240		this.s.current = columnsVis;
16241
16242		// Set the class before the column visibility is changed so event
16243		// listeners know what the state is. Need to determine if there are
16244		// any columns that are not visible but can be shown
16245		var collapsedClass = false;
16246		for ( i=0, ien=columns.length ; i<ien ; i++ ) {
16247			if ( columnsVis[i] === false && ! columns[i].never && ! columns[i].control ) {
16248				collapsedClass = true;
16249				break;
16250			}
16251		}
16252
16253		$( dt.table().node() ).toggleClass( 'collapsed', collapsedClass );
16254
16255		var changed = false;
16256		var visible = 0;
16257
16258		dt.columns().eq(0).each( function ( colIdx, i ) {
16259			if ( columnsVis[i] === true ) {
16260				visible++;
16261			}
16262
16263			if ( columnsVis[i] !== oldVis[i] ) {
16264				changed = true;
16265				that._setColumnVis( colIdx, columnsVis[i] );
16266			}
16267		} );
16268
16269		if ( changed ) {
16270			this._redrawChildren();
16271
16272			// Inform listeners of the change
16273			$(dt.table().node()).trigger( 'responsive-resize.dt', [dt, this.s.current] );
16274
16275			// If no records, update the "No records" display element
16276			if ( dt.page.info().recordsDisplay === 0 ) {
16277				$('td', dt.table().body()).eq(0).attr('colspan', visible);
16278			}
16279		}
16280	},
16281
16282
16283	/**
16284	 * Determine the width of each column in the table so the auto column hiding
16285	 * has that information to work with. This method is never going to be 100%
16286	 * perfect since column widths can change slightly per page, but without
16287	 * seriously compromising performance this is quite effective.
16288	 *
16289	 * @private
16290	 */
16291	_resizeAuto: function ()
16292	{
16293		var dt = this.s.dt;
16294		var columns = this.s.columns;
16295
16296		// Are we allowed to do auto sizing?
16297		if ( ! this.c.auto ) {
16298			return;
16299		}
16300
16301		// Are there any columns that actually need auto-sizing, or do they all
16302		// have classes defined
16303		if ( $.inArray( true, $.map( columns, function (c) { return c.auto; }
16303 ) ) === -1 ) {
16304			return;
16305		}
16306
16307		// Need to restore all children. They will be reinstated by a re-render
16308		if ( ! $.isEmptyObject( _childNodeStore ) ) {
16309			$.each( _childNodeStore, function ( key ) {
16310				var idx = key.split('-');
16311
16312				_childNodesRestore( dt, idx[0]*1, idx[1]*1 );
16313			} );
16314		}
16315
16316		// Clone the table with the current data in it
16317		var tableWidth   = dt.table().node().offsetWidth;
16318		var columnWidths = dt.columns;
16319		var clonedTable  = dt.table().node().cloneNode( false );
16320		var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
16321		var clonedBody   = $( dt.table().body() ).clone( false, false ).empty().appendTo( clonedTable ); // use jQuery because of IE8
16322
16323		// Header
16324		var headerCells = dt.columns()
16325			.header()
16326			.filter( function (idx) {
16327				return dt.column(idx).visible();
16328			} )
16329			.to$()
16330			.clone( false )
16331			.css( 'display', 'table-cell' )
16332			.css( 'min-width', 0 );
16333
16334		// Body rows - we don't need to take account of DataTables' column
16335		// visibility since we implement our own here (hence the `display` set)
16336		$(clonedBody)
16337			.append( $(dt.rows( { page: 'current' } ).nodes()).clone( false ) )
16338			.find( 'th, td' ).css( 'display', '' );
16339
16340		// Footer
16341		var footer = dt.table().footer();
16342		if ( footer ) {
16343			var clonedFooter = $( footer.cloneNode( false ) ).appendTo( clonedTable );
16344			var footerCells = dt.columns()
16345				.footer()
16346				.filter( function (idx) {
16347					return dt.column(idx).visible();
16348				} )
16349				.to$()
16350				.clone( false )
16351				.css( 'display', 'table-cell' );
16352
16353			$('<tr/>')
16354				.append( footerCells )
16355				.appendTo( clonedFooter );
16356		}
16357
16358		$('<tr/>')
16359			.append( headerCells )
16360			.appendTo( clonedHeader );
16361
16362		// In the inline case extra padding is applied to the first column to
16363		// give space for the show / hide icon. We need to use this in the
16364		// calculation
16365		if ( this.c.details.type === 'inline' ) {
16366			$(clonedTable).addClass( 'dtr-inline collapsed' );
16367		}
16368		
16369		// It is unsafe to insert elements with the same name into the DOM
16370		// multiple times. For example, cloning and inserting a checked radio
16371		// clears the chcecked state of the original radio.
16372		$( clonedTable ).find( '[name]' ).removeAttr( 'name' );
16373		
16374		var inserted = $('<div/>')
16375			.css( {
16376				width: 1,
16377				height: 1,
16378				overflow: 'hidden',
16379				clear: 'both'
16380			} )
16381			.append( clonedTable );
16382
16383		inserted.insertBefore( dt.table().node() );
16384
16385		// The cloned header now contains the smallest that each column can be
16386		headerCells.each( function (i) {
16387			var idx = dt.column.index( 'fromVisible', i );
16388			columns[ idx ].minWidth =  this.offsetWidth || 0;
16389		} );
16390
16391		inserted.remove();
16392	},
16393
16394	/**
16395	 * Set a column's visibility.
16396	 *
16397	 * We don't use DataTables' column visibility controls in order to ensure
16398	 * that column visibility can Responsive can no-exist. Since only IE8+ is
16399	 * supported (and all evergreen browsers of course) the control of the
16400	 * display attribute works well.
16401	 *
16402	 * @param {integer} col      Column index
16403	 * @param {boolean} showHide Show or hide (true or false)
16404	 * @private
16405	 */
16406	_setColumnVis: function ( col, showHide )
16407	{
16408		var dt = this.s.dt;
16409		var display = showHide ? '' : 'none'; // empty string will remove the attr
16410
16411		$( dt.column( col ).header() ).css( 'display', display );
16412		$( dt.column( col ).footer() ).css( 'display', display );
16413		dt.column( col ).nodes().to$().css( 'display', display );
16414
16415		// If the are child nodes stored, we might need to reinsert them
16416		if ( ! $.isEmptyObject( _childNodeStore ) ) {
16417			dt.cells( null, col ).indexes().each( function (idx) {
16418				_childNodesRestore( dt, idx.row, idx.column );
16419			} );
16420		}
16421	},
16422
16423
16424	/**
16425	 * Update the cell tab indexes for keyboard accessibility. This is called on
16426	 * every table draw - that is potentially inefficient, but also the least
16427	 * complex option given that column visibility can change on the fly. Its a
16428	 * shame user-focus was removed from CSS 3 UI, as it would have solved this
16429	 * issue with a single CSS statement.
16430	 *
16431	 * @private
16432	 */
16433	_tabIndexes: function ()
16434	{
16435		var dt = this.s.dt;
16436		var cells = dt.cells( { page: 'current' } ).nodes().to$();
16437		var ctx = dt.settings()[0];
16438		var target = this.c.details.target;
16439
16440		cells.filter( '[data-dtr-keyboard]' ).removeData( '[data-dtr-keyboard]' );
16441
16442		var selector = typeof target === 'number' ?
16443			':eq('+target+')' :
16444			target;
16445
16446		// This is a bit of a hack - we need to limit the selected nodes to just
16447		// those of this table
16448		if ( selector === 'td:first-child, th:first-child' ) {
16449			selector = '>td:first-child, >th:first-child';
16450		}
16451
16452		$( selector, dt.rows( { page: 'current' } ).nodes() )
16453			.attr( 'tabIndex', ctx.iTabIndex )
16454			.data( 'dtr-keyboard', 1 );
16455	}
16456} );
16457
16458
16459/**
16460 * List of default breakpoints. Each item in the array is an object with two
16461 * properties:
16462 *
16463 * * `name` - the breakpoint name.
16464 * * `width` - the breakpoint width
16465 *
16466 * @name Responsive.breakpoints
16467 * @static
16468 */
16469Responsive.breakpoints = [
16470	{ name: 'desktop',  width: Infinity },
16471	{ name: 'tablet-l', width: 1024 },
16472	{ name: 'tablet-p', width: 768 },
16473	{ name: 'mobile-l', width: 480 },
16474	{ name: 'mobile-p', width: 320 }
16475];
16476
16477
16478/**
16479 * Display methods - functions which define how the hidden data should be shown
16480 * in the table.
16481 *
16482 * @namespace
16483 * @name Responsive.defaults
16484 * @static
16485 */
16486Responsive.display = {
16487	childRow: function ( row, update, render ) {
16488		if ( update ) {
16489			if ( $(row.node()).hasClass('parent') ) {
16490				row.child( render(), 'child' ).show();
16491
16492				return true;
16493			}
16494		}
16495		else {
16496			if ( ! row.child.isShown()  ) {
16497				row.child( render(), 'child' ).show();
16498				$( row.node() ).addClass( 'parent' );
16499
16500				return true;
16501			}
16502			else {
16503				row.child( false );
16504				$( row.node() ).removeClass( 'parent' );
16505
16506				return false;
16507			}
16508		}
16509	},
16510
16511	childRowImmediate: function ( row, update, render ) {
16512		if ( (! update && row.child.isShown()) || ! row.responsive.hasHidden() ) {
16513			// User interaction and the row is show, or nothing to show
16514			row.child( false );
16515			$( row.node() ).removeClass( 'parent' );
16516
16517			return false;
16518		}
16519		else {
16520			// Display
16521			row.child( render(), 'child' ).show();
16522			$( row.node() ).addClass( 'parent' );
16523
16524			return true;
16525		}
16526	},
16527
16528	// This is a wrapper so the modal options for Bootstrap and jQuery UI can
16529	// have options passed into them. This specific one doesn't need to be a
16530	// function but it is for consistency in the `modal` name
16531	modal: function ( options ) {
16532		return function ( row, update, render ) {
16533			if ( ! update ) {
16534				// Show a modal
16535				var close = function () {
16536					modal.remove(); // will tidy events for us
16537					$(document).off( 'keypress.dtr' );
16538				};
16539
16540				var modal = $('<div class="dtr-modal"/>')
16541					.append( $('<div class="dtr-modal-display"/>')
16542						.append( $('<div class="dtr-modal-content"/>')
16543							.append( render() )
16544						)
16545						.append( $('<div class="dtr-modal-close">&times;</div>' )
16546							.click( function () {
16547								close();
16548							} )
16549						)
16550					)
16551					.append( $('<div class="dtr-modal-background"/>')
16552						.click( function () {
16553							close();
16554						} )
16555					)
16556					.appendTo( 'body' );
16557
16558				$(document).on( 'keyup.dtr', function (e) {
16559					if ( e.keyCode === 27 ) {
16560						e.stopPropagation();
16561
16562						close();
16563					}
16564				} );
16565			}
16566			else {
16567				$('div.dtr-modal-content')
16568					.empty()
16569					.append( render() );
16570			}
16571
16572			if ( options && options.header ) {
16573				$('div.dtr-modal-content').prepend(
16574					'<h2>'+options.header( row )+'</h2>'
16575				);
16576			}
16577		};
16578	}
16579};
16580
16581
16582var _childNodeStore = {};
16583
16584function _childNodes( dt, row, col ) {
16585	var name = row+'-'+col;
16586
16587	if ( _childNodeStore[ name ] ) {
16588		return _childNodeStore[ name ];
16589	}
16590
16591	// https://jsperf.com/childnodes-array-slice-vs-loop
16592	var nodes = [];
16593	var children = dt.cell( row, col ).node().childNodes;
16594	for ( var i=0, ien=children.length ; i<ien ; i++ ) {
16595		nodes.push( children[i] );
16596	}
16597
16598	_childNodeStore[ name ] = nodes;
16599
16600	return nodes;
16601}
16602
16603function _childNodesRestore( dt, row, col ) {
16604	var name = row+'-'+col;
16605
16606	if ( ! _childNodeStore[ name ] ) {
16607		return;
16608	}
16609
16610	var node = dt.cell( row, col ).node();
16611	var store = _childNodeStore[ name ];
16612	var parent = store[0].parentNode;
16613	var parentChildren = parent.childNodes;
16614	var a = [];
16615
16616	for ( var i=0, ien=parentChildren.length ; i<ien ; i++ ) {
16617		a.push( parentChildren[i] );
16618	}
16619
16620	for ( var j=0, jen=a.length ; j<jen ; j++ ) {
16621		node.appendChild( a[j] );
16622	}
16623
16624	_childNodeStore[ name ] = undefined;
16625}
16626
16627
16628/**
16629 * Display methods - functions which define how the hidden data should be shown
16630 * in the table.
16631 *
16632 * @namespace
16633 * @name Responsive.defaults
16634 * @static
16635 */
16636Responsive.renderer = {
16637	listHiddenNodes: function () {
16638		return function ( api, rowIdx, columns ) {
16639			var ul = $('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>');
16640			var found = false;
16641
16642			var data = $.each( columns, function ( i, col ) {
16643				if ( col.hidden ) {
16644					$(
16645						'<li data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
16646							'<span class="dtr-title">'+
16647								col.title+
16648							'</span> '+
16649						'</li>'
16650					)
16651						.append( $('<span class="dtr-data"/>').append( _childNodes( api, col.rowIndex, col.columnIndex ) ) )// api.cell( col.rowIndex, col.columnIndex ).node().childNodes ) )
16652						.appendTo( ul );
16653
16654					found = true;
16655				}
16656			} );
16657
16658			return found ?
16659				ul :
16660				false;
16661		};
16662	},
16663
16664	listHidden: function () {
16665		return function ( api, rowIdx, columns ) {
16666			var data = $.map( columns, function ( col ) {
16667				return col.hidden ?
16668					'<li data-dtr-index="'+col.columnIndex+'" data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
16669						'<span class="dtr-title">'+
16670							col.title+
16671						'</span> '+
16672						'<span class="dtr-data">'+
16673							col.data+
16674						'</span>'+
16675					'</li>' :
16676					'';
16677			} ).join('');
16678
16679			return data ?
16680				$('<ul data-dtr-index="'+rowIdx+'" class="dtr-details"/>').append( data ) :
16681				false;
16682		}
16683	},
16684
16685	tableAll: function ( options ) {
16686		options = $.extend( {
16687			tableClass: ''
16688		}, options );
16689
16690		return function ( api, rowIdx, columns ) {
16691			var data = $.map( columns, function ( col ) {
16692				return '<tr data-dt-row="'+col.rowIndex+'" data-dt-column="'+col.columnIndex+'">'+
16693						'<td>'+col.title+':'+'</td> '+
16694						'<td>'+col.data+'</td>'+
16695					'</tr>';
16696			} ).join('');
16697
16698			return $('<table class="'+options.tableClass+' dtr-details" width="100%"/>').append( data );
16699		}
16700	}
16701};
16702
16703/**
16704 * Responsive default settings for initialisation
16705 *
16706 * @namespace
16707 * @name Responsive.defaults
16708 * @static
16709 */
16710Responsive.defaults = {
16711	/**
16712	 * List of breakpoints for the instance. Note that this means that each
16713	 * instance can have its own breakpoints. Additionally, the breakpoints
16714	 * cannot be changed once an instance has been creased.
16715	 *
16716	 * @type {Array}
16717	 * @default Takes the value of `Responsive.breakpoints`
16718	 */
16719	breakpoints: Responsive.breakpoints,
16720
16721	/**
16722	 * Enable / disable auto hiding calculations. It can help to increase
16723	 * performance slightly if you disable this option, but all columns would
16724	 * need to have breakpoint classes assigned to them
16725	 *
16726	 * @type {Boolean}
16727	 * @default  `true`
16728	 */
16729	auto: true,
16730
16731	/**
16732	 * Details control. If given as a string value, the `type` property of the
16733	 * default object is set to that value, and the defaults used for the rest
16734	 * of the object - this is for ease of implementation.
16735	 *
16736	 * The object consists of the following properties:
16737	 *
16738	 * * `display` - A function that is used to show and hide the hidden details
16739	 * * `renderer` - function that is called for display of the child row data.
16740	 *   The default function will show the data from the hidden columns
16741	 * * `target` - Used as the selector for what objects to attach the child
16742	 *   open / close to
16743	 * * `type` - `false` to disable the details display, `inline` or `column`
16744	 *   for the two control types
16745	 *
16746	 * @type {Object|string}
16747	 */
16748	details: {
16749		display: Responsive.display.childRow,
16750
16751		renderer: Responsive.renderer.listHidden(),
16752
16753		target: 0,
16754
16755		type: 'inline'
16756	},
16757
16758	/**
16759	 * Orthogonal data request option. This is used to define the data type
16760	 * requested when Responsive gets the data to show in the child row.
16761	 *
16762	 * @type {String}
16763	 */
16764	orthogonal: 'display'
16765};
16766
16767
16768/*
16769 * API
16770 */
16771var Api = $.fn.dataTable.Api;
16772
16773// Doesn't do anything - work around for a bug in DT... Not documented
16774Api.register( 'responsive()', function () {
16775	return this;
16776} );
16777
16778Api.register( 'responsive.index()', function ( li ) {
16779	li = $(li);
16780
16781	return {
16782		column: li.data('dtr-index'),
16783		row:    li.parent().data('dtr-index')
16784	};
16785} );
16786
16787Api.register( 'responsive.rebuild()', function () {
16788	return this.iterator( 'table', function ( ctx ) {
16789		if ( ctx._responsive ) {
16790			ctx._responsive._classLogic();
16791		}
16792	} );
16793} );
16794
16795Api.register( 'responsive.recalc()', function () {
16796	return this.iterator( 'table', function ( ctx ) {
16797		if ( ctx._responsive ) {
16798			ctx._responsive._resizeAuto();
16799			ctx._responsive._resize();
16800		}
16801	} );
16802} );
16803
16804Api.register( 'responsive.hasHidden()', function () {
16805	var ctx = this.context[0];
16806
16807	return ctx._responsive ?
16808		$.inArray( false, ctx._responsive.s.current ) !== -1 :
16809		false;
16810} );
16811
16812Api.registerPlural( 'columns().responsiveHidden()', 'column().responsiveHidden()', function () {
16813	return this.iterator( 'column', function ( settings, column ) {
16814		return settings._responsive ?
16815			settings._responsive.s.current[ column ] :
16816			false;
16817	}, 1 );
16818} );
16819
16820
16821/**
16822 * Version information
16823 *
16824 * @name Responsive.version
16825 * @static
16826 */
16827Responsive.version = '2.2.1';
16828
16829
16830$.fn.dataTable.Responsive = Responsive;
16831$.fn.DataTable.Responsive = Responsive;
16832
16833// Attach a listener to the document which listens for DataTables initialisation
16834// events so we can automatically initialise
16835$(document).on( 'preInit.dt.dtr', function (e, settings, json) {
16836	if ( e.namespace !== 'dt' ) {
16837		return;
16838	}
16839
16840	if ( $(settings.nTable).hasClass( 'responsive' ) ||
16841		 $(settings.nTable).hasClass( 'dt-responsive' ) ||
16842		 settings.oInit.responsive ||
16843		 DataTable.defaults.responsive
16844	) {
16845		var init = settings.oInit.responsive;
16846
16847		if ( init !== false ) {
16848			new Responsive( settings, $.isPlainObject( init ) ? init : {}  );
16849		}
16850	}
16851} );
16852
16853
16854return Responsive;
16855}));
16856
16857
16858
16859/*!
16860 Responsive 2.2.2
16861 2014-2018 SpryMedia Ltd - datatables.net/license
16862*/
16863(function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(l){return d(l,window,document)}):"object"===typeof exports?module.exports=function(l,j){l||(l=window);if(!j||!j.fn.dataTable)j=require("datatables.net")(l,j).$;return d(j,l,l.document)}:d(jQuery,window,document)})(function(d,l,j,q){function t(a,b,c){var e=b+"-"+c;if(n[e])return n[e];for(var d=[],a=a.cell(b,c).node().childNodes,b=0,c=a.length;b<c;b++)d.push(a[b]);return n[e]=d}function r(a,b,d){var e=b+
16864"-"+d;if(n[e]){for(var a=a.cell(b,d).node(),d=n[e][0].parentNode.childNodes,b=[],f=0,g=d.length;f<g;f++)b.push(d[f]);d=0;for(f=b.length;d<f;d++)a.appendChild(b[d]);n[e]=q}}var o=d.fn.dataTable,i=function(a,b){if(!o.versionCheck||!o.versionCheck("1.10.10"))throw"DataTables Responsive requires DataTables 1.10.10 or newer";this.s={dt:new o.Api(a),columns:[],current:[]};this.s.dt.settings()[0].responsive||(b&&"string"===typeof b.details?b.details={type:b.details}:b&&!1===b.details?b.details={type:!1}:
16865b&&!0===b.details&&(b.details={type:"inline"}),this.c=d.extend(!0,{},i.defaults,o.defaults.responsive,b),a.responsive=this,this._constructor())};d.extend(i.prototype,{_constructor:function(){var a=this,b=this.s.dt,c=b.settings()[0],e=d(l).width();b.settings()[0]._responsive=this;d(l).on("resize.dtr orientationchange.dtr",o.util.throttle(function(){var b=d(l).width();b!==e&&(a._resize(),e=b)}));c.oApi._fnCallbackReg(c,"aoRowCreatedCallback",function(e){-1!==d.inArray(!1,a.s.current)&&d(">td, >th",
16866e).each(function(e){e=b.column.index("toData",e);!1===a.s.current[e]&&d(this).css("display","none")})});b.on("destroy.dtr",function(){b.off(".dtr");d(b.table().body()).off(".dtr");d(l).off("resize.dtr orientationchange.dtr");d.each(a.s.current,function(b,e){!1===e&&a._setColumnVis(b,!0)})});this.c.breakpoints.sort(function(a,b){return a.width<b.width?1:a.width>b.width?-1:0});this._classLogic();this._resizeAuto();c=this.c.details;!1!==c.type&&(a._detailsInit(),b.on("column-visibility.dtr",function(){a._timer&&
16867clearTimeout(a._timer);a._timer=setTimeout(function(){a._timer=null;a._classLogic();a._resizeAuto();a._resize();a._redrawChildren()},100)}),b.on("draw.dtr",function(){a._redrawChildren()}
16867),d(b.table().node()).addClass("dtr-"+c.type));b.on("column-reorder.dtr",function(){a._classLogic();a._resizeAuto();a._resize()});b.on("column-sizing.dtr",function(){a._resizeAuto();a._resize()});b.on("preXhr.dtr",function(){var e=[];b.rows().every(function(){this.child.isShown()&&e.push(this.id(true))});b.one("draw.dtr",
16868function(){a._resizeAuto();a._resize();b.rows(e).every(function(){a._detailsDisplay(this,false)})})});b.on("init.dtr",function(){a._resizeAuto();a._resize();d.inArray(false,a.s.current)&&b.columns.adjust()});this._resize()},_columnsVisiblity:function(a){var b=this.s.dt,c=this.s.columns,e,f,g=c.map(function(a,b){return{columnIdx:b,priority:a.priority}}).sort(function(a,b){return a.priority!==b.priority?a.priority-b.priority:a.columnIdx-b.columnIdx}),h=d.map(c,function(e,c){return!1===b.column(c).visible()?
16869"not-visible":e.auto&&null===e.minWidth?!1:!0===e.auto?"-":-1!==d.inArray(a,e.includeIn)}),m=0;e=0;for(f=h.length;e<f;e++)!0===h[e]&&(m+=c[e].minWidth);e=b.settings()[0].oScroll;e=e.sY||e.sX?e.iBarWidth:0;m=b.table().container().offsetWidth-e-m;e=0;for(f=h.length;e<f;e++)c[e].control&&(m-=c[e].minWidth);var s=!1;e=0;for(f=g.length;e<f;e++){var k=g[e].columnIdx;"-"===h[k]&&(!c[k].control&&c[k].minWidth)&&(s||0>m-c[k].minWidth?(s=!0,h[k]=!1):h[k]=!0,m-=c[k].minWidth)}g=!1;e=0;for(f=c.length;e<f;e++)if(!c[e].control&&
16870!c[e].never&&!1===h[e]){g=!0;break}e=0;for(f=c.length;e<f;e++)c[e].control&&(h[e]=g),"not-visible"===h[e]&&(h[e]=!1);-1===d.inArray(!0,h)&&(h[0]=!0);return h},_classLogic:function(){var a=this,b=this.c.breakpoints,c=this.s.dt,e=c.columns().eq(0).map(function(a){var b=this.column(a),e=b.header().className,a=c.settings()[0].aoColumns[a].responsivePriority;a===q&&(b=d(b.header()).data("priority"),a=b!==q?1*b:1E4);return{className:e,includeIn:[],auto:!1,control:!1,never:e.match(/\bnever\b/)?!0:!1,priority:a}}),
16871f=function(a,b){var c=e[a].includeIn;-1===d.inArray(b,c)&&c.push(b)},g=function(d,c,g,k){if(g)if("max-"===g){k=a._find(c).width;c=0;for(g=b.length;c<g;c++)b[c].width<=k&&f(d,b[c].name)}else if("min-"===g){k=a._find(c).width;c=0;for(g=b.length;c<g;c++)b[c].width>=k&&f(d,b[c].name)}else{if("not-"===g){c=0;for(g=b.length;c<g;c++)-1===b[c].name.indexOf(k)&&f(d,b[c].name)}}else e[d].includeIn.push(c)};e.each(function(a,e){for(var c=a.className.split(" "),f=!1,i=0,l=c.length;i<l;i++){var j=d.trim(c[i]);
16872if("all"===j){f=!0;a.includeIn=d.map(b,function(a){return a.name});return}if("none"===j||a.never){f=!0;return}
16872if("control"===j){f=!0;a.control=!0;return}d.each(b,function(a,b){var d=b.name.split("-"),c=j.match(RegExp("(min\\-|max\\-|not\\-)?("+d[0]+")(\\-[_a-zA-Z0-9])?"));c&&(f=!0,c[2]===d[0]&&c[3]==="-"+d[1]?g(e,b.name,c[1],c[2]+c[3]):c[2]===d[0]&&!c[3]&&g(e,b.name,c[1],c[2]))})}f||(a.auto=!0)});this.s.columns=e},_detailsDisplay:function(a,b){var c=this,e=this.s.dt,f=this.c.details;if(f&&!1!==f.type){var g=
16873f.display(a,b,function(){return f.renderer(e,a[0],c._detailsObj(a[0]))});(!0===g||!1===g)&&d(e.table().node()).triggerHandler("responsive-display.dt",[e,a,g,b])}},_detailsInit:function(){var a=this,b=this.s.dt,c=this.c.details;"inline"===c.type&&(c.target="td:first-child, th:first-child");b.on("draw.dtr",function(){a._tabIndexes()});a._tabIndexes();d(b.table().body()).on("keyup.dtr","td, th",function(a){a.keyCode===13&&d(this).data("dtr-keyboard")&&d(this).click()});var e=c.target;d(b.table().body()).on("click.dtr mousedown.dtr mouseup.dtr",
16874"string"===typeof e?e:"td, th",function(c){if(d(b.table().node()).hasClass("collapsed")&&d.inArray(d(this).closest("tr").get(0),b.rows().nodes().toArray())!==-1){if(typeof e==="number"){var g=e<0?b.columns().eq(0).length+e:e;if(b.cell(this).index().column!==g)return}g=b.row(d(this).closest("tr"));c.type==="click"?a._detailsDisplay(g,false):c.type==="mousedown"?d(this).css("outline","none"):c.type==="mouseup"&&d(this).blur().css("outline","")}})},_detailsObj:function(a){var b=this,c=this.s.dt;return d.map(this.s.columns,
16875function(e,d){if(!e.never&&!e.control)return{title:c.settings()[0].aoColumns[d].sTitle,data:c.cell(a,d).render(b.c.orthogonal),hidden:c.column(d).visible()&&!b.s.current[d],columnIndex:d,rowIndex:a}})},_find:function(a){for(var b=this.c.breakpoints,c=0,e=b.length;c<e;c++)if(b[c].name===a)return b[c]},_redrawChildren:function(){var a=this,b=this.s.dt;b.rows({page:"current"}).iterator("row",function(c,e){b.row(e);a._detailsDisplay(b.row(e),!0)})},_resize:function(){var a=this,b=this.s.dt,c=d(l).width(),
16876e=this.c.breakpoints,f=e[0].name,g=this.s.columns,h,m=this.s.current.slice();for(h=e.length-1;0<=h;h--)if(c<=e[h].width){f=e[h].name;break}var i=this._columnsVisiblity(f);this.s.current=i;e=!1;h=0;for(c=g.length;h<c;h++)if(!1===i[h]&&!g[h].never&&!g[h].control&&!1===!b.column(h).visible()){e=!0;break}d(b.table().node()).toggleClass("collapsed",e);var k=!1,j=0;b.columns().eq(0).each(function(b,c){!0===i[c]&&j++;i[c]!==m[c]&&(k=!0,a._setColumnVis(b,i[c]))});k&&(this._redrawChildren(),d(b.table().node()).trigger("responsive-resize.dt",
16877[b,this.s.current]),0===b.page.info().recordsDisplay&&d("td",b.table().body()).eq(0).attr("colspan",j))},_resizeAuto:function(){var a=this.s.dt,b=this.s.columns;if(this.c.auto&&-1!==d.inArray(!0,d.map(b,function(a){return a.auto}))){d.isEmptyObject(n)||d.each(n,function(b){b=b.split("-");r(a,1*b[0],1*b[1])});a.table().node();var c=a.table().node().cloneNode(!1),e=d(a.table().header().cloneNode(!1)).appendTo(c),f=d(a.table().body()).clone(!1,!1).empty().appendTo(c),g=a.columns().header().filter(function(b){return a.column(b).visible()}).to$().clone(!1).css("display",
16878"table-cell").css("min-width",0);d(f).append(d(a.rows({page:"current"}).nodes()).clone(!1)).find("th, td").css("display","");if(f=a.table().footer()){var f=d(f.cloneNode(!1)).appendTo(c),h=a.columns().footer().filter(function(b){return a.column(b).visible()}).to$().clone(!1).css("display","table-cell");d("<tr/>").append(h).appendTo(f)}d("<tr/>").append(g).appendTo(e);"inline"===this.c.details.type&&d(c).addClass("dtr-inline collapsed");d(c).find("[name]").removeAttr("name");d(c).css("position","relative");
16879c=d("<div/>").css({width:1,height:1,overflow:"hidden",clear:"both"}).append(c);c.insertBefore(a.table().node());g.each(function(c){c=a.column.index("fromVisible",c);b[c].minWidth=this.offsetWidth||0});c.remove()}},_setColumnVis:function(a,b){var c=this.s.dt,e=b?"":"none";d(c.column(a).header()).css("display",e);d(c.column(a).footer()).css("display",e);c.column(a).nodes().to$().css("display",e);d.isEmptyObject(n)||c.cells(null,a).indexes().each(function(a){r(c,a.row,a.column)})},_tabIndexes:function(){var a=
16880this.s.dt,b=a.cells({page:"current"}).nodes().to$(),c=a.settings()[0],e=this.c.details.target;b.filter("[data-dtr-keyboard]").removeData("[data-dtr-keyboard]");"number"===typeof e?a.cells(null,e,{page:"current"}).nodes().to$().attr("tabIndex",c.iTabIndex).data("dtr-keyboard",1):("td:first-child, th:first-child"===e&&(e=">td:first-child, >th:first-child"),d(e,a.rows({page:"current"}).nodes()).attr("tabIndex",c.iTabIndex).data("dtr-keyboard",1))}});i.breakpoints=[{name:"desktop",width:Infinity},{name:"tablet-l",
16881width:1024},{name:"tablet-p",width:768},{name:"mobile-l",width:480},{name:"mobile-p",width:320}];i.display={childRow:function(a,b,c){if(b){if(d(a.node()).hasClass("parent"))return a.child(c(),"child").show(),!0}else{if(a.child.isShown())return a.child(!1),d(a.node()).removeClass("parent"),!1;a.child(c(),"child").show();d(a.node()).addClass("parent");return!0}},childRowImmediate:function(a,b,c){if(!b&&a.child.isShown()||!a.responsive.hasHidden())return a.child(!1),d(a.node()).removeClass("parent"),
16882!1;a.child(c(),"child").show();d(a.node()).addClass("parent");return!0},modal:function(a){return function(b,c,e){if(c)d("div.dtr-modal-content").empty().append(e());else{var f=function(){g.remove();d(j).off("keypress.dtr")},g=d('<div class="dtr-modal"/>').append(d('<div class="dtr-modal-display"/>').append(d('<div class="dtr-modal-content"/>').append(e())).append(d('<div class="dtr-modal-close">&times;</div>').click(function(){f()}))).append(d('<div class="dtr-modal-background"/>').click(function(){f()})).appendTo("body");
16883d(j).on("keyup.dtr",function(a){27===a.keyCode&&(a.stopPropagation(),f())})}a&&a.header&&d("div.dtr-modal-content").prepend("<h2>"+a.header(b)+"</h2>")}}};var n={};i.renderer={listHiddenNodes:function(){return function(a,b,c){var e=d('<ul data-dtr-index="'+b+'" class="dtr-details"/>'),f=!1;d.each(c,function(b,c){c.hidden&&(d('<li data-dtr-index="'+c.columnIndex+'" data-dt-row="'+c.rowIndex+'" data-dt-column="'+c.columnIndex+'"><span class="dtr-title">'+c.title+"</span> </li>").append(d('<span class="dtr-data"/>').append(t(a,
16884c.rowIndex,c.columnIndex))).appendTo(e),f=!0)});return f?e:!1}},listHidden:function(){return function(a,b,c){return(a=d.map(c,function(a){return a.hidden?'<li data-dtr-index="'+a.columnIndex+'" data-dt-row="'+a.rowIndex+'" data-dt-column="'+a.columnIndex+'"><span class="dtr-title">'+a.title+'</span> <span class="dtr-data">'+a.data+"</span></li>":""}).join(""))?d('<ul data-dtr-index="'+b+'" class="dtr-details"/>').append(a):!1}},tableAll:function(a){a=d.extend({tableClass:""},a);return function(b,
16885c,e){b=d.map(e,function(a){return'<tr data-dt-row="'+a.rowIndex+'" data-dt-column="'+a.columnIndex+'"><td>'+a.title+":</td> <td>"+a.data+"</td></tr>"}).join("");return d('<table class="'+a.tableClass+' dtr-details" width="100%"/>').append(b)}}};i.defaults={breakpoints:i.breakpoints,auto:!0,details:{display:i.display.childRow,renderer:i.renderer.listHidden(),target:0,type:"inline"},orthogonal:"display"};var p=d.fn.dataTable.Api;p.register("responsive()",function(){return this});p.register("responsive.index()",
16886function(a){a=d(a);return{column:a.data("dtr-index"),row:a.parent().data("dtr-index")}});p.register("responsive.rebuild()",function(){return this.iterator("table",function(a){a._responsive&&a._responsive._classLogic()})});p.register("responsive.recalc()",function(){return this.iterator("table",function(a){a._responsive&&(a._responsive._resizeAuto(),a._responsive._resize())})});p.register("responsive.hasHidden()",function(){var a=this.context[0];return a._responsive?-1!==d.inArray(!1,a._responsive.s.current):
16887!1});p.registerPlural("columns().responsiveHidden()","column().responsiveHidden()",function(){return this.iterator("column",function(a,b){return a._responsive?a._responsive.s.current[b]:!1},1)});i.version="2.2.2";d.fn.dataTable.Responsive=i;d.fn.DataTable.Responsive=i;d(j).on("preInit.dt.dtr",function(a,b){if("dt"===a.namespace&&(d(b.nTable).hasClass("responsive")||d(b.nTable).hasClass("dt-responsive")||b.oInit.responsive||o.defaults.responsive)){var c=b.oInit.responsive;!1!==c&&new i(b,d.isPlainObject(c)?
16888c:{})}});return i});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.