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||" ")+"</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||" ")+"</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=" ";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">×</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=["­",'<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( / /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>'<' and '>' - div elements</li> 11869 * <li>'<"class" and '>' - div with a class</li> 11870 * <li>'<"#id" and '>' - div with an ID</li> 11871 * </ul> 11872 * </li> 11873 * <li>Examples: 11874 * <ul> 11875 * <li>'<"wrapper"flipt>'</li> 11876 * <li>'<lf<t>ip>'</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": '<"top"i>rt<"bottom"flp><"clear">' 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) == '£' ) { 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">…</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, '<').replace(/>/g, '>').replace(/"/g, '"') : 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 = '…'; 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">×</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">×</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.