src/pyams_skin/resources/js/myams-dataTables.js
changeset 566 a1707c607eec
parent 565 318533413200
child 567 bca1726b1d85
equal deleted inserted replaced
565:318533413200 566:a1707c607eec
     1 /*
       
     2  * MyAMS extensions to jquery-dataTables plug-in
       
     3  * Version 0.1.0
       
     4  * ©2014-2015 Thierry Florac <tflorac@ulthar.net>
       
     5  */
       
     6 
       
     7 
       
     8 (function($, globals) {
       
     9 
       
    10 	"use strict";
       
    11 
       
    12 	/**
       
    13 	 * Update default values for DataTables initialization
       
    14 	 */
       
    15 	$.extend(true, $.fn.dataTable.defaults, {
       
    16 		"sDom": "R<'dt-top-row'CLF>r<'dt-wrapper't><'dt-row dt-bottom-row'<'row'<'col-sm-6'i><'col-sm-6 text-right'p>>",
       
    17 		"sPaginationType": "bootstrap",
       
    18 		"oLanguage": {
       
    19 			"sLengthMenu": "_MENU_",
       
    20 			"sSearch": "_INPUT_"
       
    21 		}
       
    22 	});
       
    23 
       
    24 
       
    25 	/**
       
    26 	 * Default class modification
       
    27 	 */
       
    28 	$.extend($.fn.dataTableExt.oStdClasses, {
       
    29 		"sWrapper": "dataTables_wrapper form-inline"
       
    30 	});
       
    31 
       
    32 
       
    33 	/**
       
    34 	 * API method to get paging information
       
    35 	 */
       
    36 	$.fn.dataTableExt.oApi.fnPagingInfo = function (oSettings) {
       
    37 		return {
       
    38 			"iStart":         oSettings._iDisplayStart,
       
    39 			"iEnd":           oSettings.fnDisplayEnd(),
       
    40 			"iLength":        oSettings._iDisplayLength,
       
    41 			"iTotal":         oSettings.fnRecordsTotal(),
       
    42 			"iFilteredTotal": oSettings.fnRecordsDisplay(),
       
    43 			"iPage":          oSettings._iDisplayLength === -1 ? 0 : Math.ceil( oSettings._iDisplayStart / oSettings._iDisplayLength ),
       
    44 			"iTotalPages":    oSettings._iDisplayLength === -1 ? 0 : Math.ceil( oSettings.fnRecordsDisplay() / oSettings._iDisplayLength )
       
    45 		};
       
    46 	};
       
    47 
       
    48 
       
    49 	/**
       
    50 	 * Custom sorting plug-in
       
    51 	 */
       
    52 	$.fn.dataTableExt.aTypes.unshift(
       
    53 		function(sData) {
       
    54 			if (sData !== null && sData.match(/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/[0-3][0-9]{3}$/)) {
       
    55 				return 'date-euro';
       
    56 			}
       
    57 			return null;
       
    58 		}
       
    59 	);
       
    60 
       
    61 	$.fn.dataTableExt.aTypes.unshift(
       
    62 		function(sData) {
       
    63 			if (sData !== null && sData.match(/^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/[0-3][0-9]{3} - ([0-1][0-9]|2[0-3]):[0-5][0-9]$/)) {
       
    64 				return 'datetime-euro';
       
    65 			}
       
    66 			return null;
       
    67 		}
       
    68 	);
       
    69 
       
    70 	$.extend($.fn.dataTableExt.oSort, {
       
    71 
       
    72 		// numeric-comma column sorter
       
    73 		"numeric-comma-asc": function(a, b) {
       
    74 			var x = a.replace(/,/, ".").replace(/ /g, '');
       
    75 			var y = b.replace(/,/, ".").replace(/ /g, '');
       
    76 			x = parseFloat(x);
       
    77 			y = parseFloat(y);
       
    78 			return ((x < y) ? -1 : ((x > y) ?  1 : 0));
       
    79 		},
       
    80 		"numeric-comma-desc": function(a, b) {
       
    81 			var x = a.replace(/,/, ".").replace(/ /g, '');
       
    82 			var y = b.replace(/,/, ".").replace(/ /g, '');
       
    83 			x = parseFloat(x);
       
    84 			y = parseFloat(y);
       
    85 			return ((x < y) ?  1 : ((x > y) ? -1 : 0));
       
    86 		},
       
    87 
       
    88 		// date-euro column sorter
       
    89 		"date-euro-pre": function(a) {
       
    90 			var trimmed = $.trim(a);
       
    91 			var x;
       
    92 			if (trimmed !== '') {
       
    93 				var frDate= trimmed.split('/');
       
    94 				x = (frDate[2] + frDate[1] + frDate[0]) * 1;
       
    95 			} else {
       
    96 				x = 10000000; // = l'an 1000 ...
       
    97 			}
       
    98 			return x;
       
    99 		},
       
   100 
       
   101 		"date-euro-asc": function(a, b) {
       
   102 			return a - b;
       
   103 		},
       
   104 
       
   105 		"date-euro-desc": function(a, b) {
       
   106 			return b - a;
       
   107 		},
       
   108 
       
   109 		// datetime-euro column sorter
       
   110 		"datetime-euro-pre": function(a) {
       
   111 			var trimmed = $.trim(a);
       
   112 			var x;
       
   113 			if (trimmed !== '') {
       
   114 				var frDateTime = trimmed.split(' - ');
       
   115 				var frDate= frDateTime[0].split('/');
       
   116 				var frTime = frDateTime[1].split(':');
       
   117 				x = (frDate[2] + frDate[1] + frDate[0] + frTime[0] + frTime[1]) * 1;
       
   118 			} else {
       
   119 				x = 100000000000; // = l'an 1000 ...
       
   120 			}
       
   121 			return x;
       
   122 		},
       
   123 
       
   124 		"datetime-euro-asc": function(a, b) {
       
   125 			return a - b;
       
   126 		},
       
   127 
       
   128 		"datetime-euro-desc": function(a, b) {
       
   129 			return b - a;
       
   130 		}
       
   131 	});
       
   132 
       
   133 
       
   134 	/**
       
   135 	 * Bootstrap style pagination control
       
   136 	 */
       
   137 	$.extend($.fn.dataTableExt.oPagination, {
       
   138 		"bootstrap": {
       
   139 			"fnInit": function(oSettings, nPaging, fnDraw) {
       
   140 				var oLang = oSettings.oLanguage.oPaginate;
       
   141 				var fnClickHandler = function (e) {
       
   142 					e.preventDefault();
       
   143 					if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
       
   144 						fnDraw(oSettings);
       
   145 					}
       
   146 				};
       
   147 
       
   148 				$(nPaging).append(
       
   149 					'<ul class="pagination">' +
       
   150 						'<li class="prev disabled"><a href="#">' + oLang.sPrevious + '</a></li>' +
       
   151 						'<li class="next disabled"><a href="#">' + oLang.sNext + '</a></li>' +
       
   152 					'</ul>'
       
   153 				);
       
   154 				var els = $('a', nPaging);
       
   155 				$(els[0]).on('click.DT', { action: "previous" }, fnClickHandler);
       
   156 				$(els[1]).on('click.DT', { action: "next" }, fnClickHandler);
       
   157 			},
       
   158 
       
   159 			"fnUpdate": function (oSettings, fnDraw) {
       
   160 				var iListLength = 5;
       
   161 				var oPaging = oSettings.oInstance.fnPagingInfo();
       
   162 				var an = oSettings.aanFeatures.p;
       
   163 				var i,
       
   164 					j,
       
   165 					sClass,
       
   166 					iStart,
       
   167 					iEnd,
       
   168 					iLen,
       
   169 					iHalf=Math.floor(iListLength/2);
       
   170 
       
   171 				if (oPaging.iTotalPages < iListLength) {
       
   172 					iStart = 1;
       
   173 					iEnd = oPaging.iTotalPages;
       
   174 				} else if (oPaging.iPage <= iHalf) {
       
   175 					iStart = 1;
       
   176 					iEnd = iListLength;
       
   177 				} else if (oPaging.iPage >= (oPaging.iTotalPages-iHalf)) {
       
   178 					iStart = oPaging.iTotalPages - iListLength + 1;
       
   179 					iEnd = oPaging.iTotalPages;
       
   180 				} else {
       
   181 					iStart = oPaging.iPage - iHalf + 1;
       
   182 					iEnd = iStart + iListLength - 1;
       
   183 				}
       
   184 
       
   185 				for (i=0, iLen=an.length ; i<iLen ; i++) {
       
   186 					// Remove the middle elements
       
   187 					$('li:gt(0)', an[i]).filter(':not(:last)').remove();
       
   188 
       
   189 					// Add the new list items and their event handlers
       
   190 					for (j=iStart ; j<=iEnd ; j++) {
       
   191 						sClass = (j === oPaging.iPage+1) ? 'class="active"' : '';
       
   192 						$('<li '+sClass+'><a href="#">'+j+'</a></li>')
       
   193 							.insertBefore( $('li:last', an[i])[0] )
       
   194 							.on('click', function (e) {
       
   195 								e.preventDefault();
       
   196 								oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
       
   197 								fnDraw( oSettings );
       
   198 							});
       
   199 					}
       
   200 
       
   201 					// Add / remove disabled classes from the static elements
       
   202 					if (oPaging.iPage === 0) {
       
   203 						$('li:first', an[i]).addClass('disabled');
       
   204 					} else {
       
   205 						$('li:first', an[i]).removeClass('disabled');
       
   206 					}
       
   207 
       
   208 					if (oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0) {
       
   209 						$('li:last', an[i]).addClass('disabled');
       
   210 					} else {
       
   211 						$('li:last', an[i]).removeClass('disabled');
       
   212 					}
       
   213 				}
       
   214 			}
       
   215 		}
       
   216 	});
       
   217 
       
   218 
       
   219 	/**
       
   220 	 * Bootstrap style full pagination control
       
   221 	 */
       
   222 	$.extend( $.fn.dataTableExt.oPagination, {
       
   223 		"bootstrap_full": {
       
   224 			"fnInit": function(oSettings, nPaging, fnDraw) {
       
   225 				var oLang = oSettings.oLanguage.oPaginate;
       
   226 				var fnClickHandler = function (e) {
       
   227 					e.preventDefault();
       
   228 					if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
       
   229 						fnDraw(oSettings);
       
   230 					}
       
   231 				};
       
   232 
       
   233 				$(nPaging).append(
       
   234 					'<ul class="pagination">' +
       
   235 						'<li class="first disabled"><a href="#">' + oLang.sFirst + '</a></li>' +
       
   236 						'<li class="prev disabled"><a href="#">' + oLang.sPrevious + '</a></li>' +
       
   237 						'<li class="next disabled"><a href="#">' + oLang.sNext + '</a></li>' +
       
   238 						'<li class="last disabled"><a href="#">' + oLang.sLast + '</a></li>' +
       
   239 					'</ul>'
       
   240 				);
       
   241 				var els = $('a', nPaging);
       
   242 				$(els[0]).on('click.DT', { action: "first" }, fnClickHandler);
       
   243 				$(els[1]).on('click.DT', { action: "previous" }, fnClickHandler);
       
   244 				$(els[2]).on('click.DT', { action: "next" }, fnClickHandler);
       
   245 				$(els[3]).on('click.DT', { action: "last" }, fnClickHandler);
       
   246 			},
       
   247 
       
   248 			"fnUpdate": function (oSettings, fnDraw) {
       
   249 				var iListLength = 5;
       
   250 				var oPaging = oSettings.oInstance.fnPagingInfo();
       
   251 				var an = oSettings.aanFeatures.p;
       
   252 				var i,
       
   253 					j,
       
   254 					sClass,
       
   255 					iStart,
       
   256 					iLen,
       
   257 					iEnd,
       
   258 					iHalf=Math.floor(iListLength/2);
       
   259 
       
   260 				if (oPaging.iTotalPages < iListLength) {
       
   261 					iStart = 1;
       
   262 					iEnd = oPaging.iTotalPages;
       
   263 				} else if (oPaging.iPage <= iHalf) {
       
   264 					iStart = 1;
       
   265 					iEnd = iListLength;
       
   266 				} else if (oPaging.iPage >= (oPaging.iTotalPages-iHalf)) {
       
   267 					iStart = oPaging.iTotalPages - iListLength + 1;
       
   268 					iEnd = oPaging.iTotalPages;
       
   269 				} else {
       
   270 					iStart = oPaging.iPage - iHalf + 1;
       
   271 					iEnd = iStart + iListLength - 1;
       
   272 				}
       
   273 
       
   274 				for (i=0, iLen=an.length ; i<iLen ; i++) {
       
   275 					// Remove the middle elements
       
   276 					$('li', an[i]).filter(":not(.first)").filter(":not(.last)").filter(":not(.prev)").filter(":not(.next)").remove();
       
   277 
       
   278 					// Add the new list items and their event handlers
       
   279 					for (j=iStart ; j<=iEnd ; j++) {
       
   280 						sClass = (j === oPaging.iPage+1) ? 'class="active"' : '';
       
   281 						$('<li '+sClass+'><a href="#">'+j+'</a></li>')
       
   282 							.insertBefore( $('li.next', an[i])[0] )
       
   283 							.on('click', function (e) {
       
   284 								e.preventDefault();
       
   285 								oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
       
   286 								fnDraw( oSettings );
       
   287 							});
       
   288 					}
       
   289 
       
   290 					// Add / remove disabled classes from the static elements
       
   291 					if (oPaging.iPage === 0) {
       
   292 						$('li.first', an[i]).addClass('disabled');
       
   293 						$('li.prev', an[i]).addClass('disabled');
       
   294 					} else {
       
   295 						$('li.prev', an[i]).removeClass('disabled');
       
   296 						$('li.first', an[i]).removeClass('disabled');
       
   297 					}
       
   298 
       
   299 					if (oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0) {
       
   300 						$('li.last', an[i]).addClass('disabled');
       
   301 						$('li.next', an[i]).addClass('disabled');
       
   302 					} else {
       
   303 						$('li.next', an[i]).removeClass('disabled');
       
   304 						$('li.last', an[i]).removeClass('disabled');
       
   305 					}
       
   306 				}
       
   307 			}
       
   308 		}
       
   309 	} );
       
   310 
       
   311 
       
   312 	/**
       
   313 	 * Bootstrap style pagination control with only previous/next buttons
       
   314 	 */
       
   315 	$.extend($.fn.dataTableExt.oPagination, {
       
   316 		"bootstrap_prevnext": {
       
   317 			"fnInit": function(oSettings, nPaging, fnDraw) {
       
   318 				var oLang = oSettings.oLanguage.oPaginate;
       
   319 				var fnClickHandler = function (e) {
       
   320 					e.preventDefault();
       
   321 					if (oSettings.oApi._fnPageChange(oSettings, e.data.action)) {
       
   322 						fnDraw(oSettings);
       
   323 					}
       
   324 				};
       
   325 
       
   326 				$(nPaging).append(
       
   327 					'<ul class="pagination">' +
       
   328 						'<li class="first disabled"><a href="#"><i class="fa fa-fw fa-fast-backward"></i></a></li>' +
       
   329 						'<li class="prev disabled"><a href="#"><i class="fa fa-fw fa-step-backward"></i></a></li>' +
       
   330 						'<li class="next disabled"><a href="#"><i class="fa fa-fw fa-step-forward"></i></a></li>' +
       
   331 						'<li class="last disabled"><a href="#"><i class="fa fa-fw fa-fast-forward"></i></a></li>' +
       
   332 					'</ul>'
       
   333 				);
       
   334 				var els = $('a', nPaging);
       
   335 				$(els[0]).on('click.DT', { action: "first" }, fnClickHandler);
       
   336 				$(els[1]).on('click.DT', { action: "previous" }, fnClickHandler);
       
   337 				$(els[2]).on('click.DT', { action: "next" }, fnClickHandler);
       
   338 				$(els[3]).on('click.DT', { action: "last" }, fnClickHandler);
       
   339 			},
       
   340 
       
   341 			"fnUpdate": function (oSettings, fnDraw) {
       
   342 				var iListLength = 5;
       
   343 				var oPaging = oSettings.oInstance.fnPagingInfo();
       
   344 				var an = oSettings.aanFeatures.p;
       
   345 				var i,
       
   346 					j,
       
   347 					sClass,
       
   348 					iStart,
       
   349 					iEnd,
       
   350 					iLen,
       
   351 					iHalf=Math.floor(iListLength/2);
       
   352 
       
   353 				if (oPaging.iTotalPages < iListLength) {
       
   354 					iStart = 1;
       
   355 					iEnd = oPaging.iTotalPages;
       
   356 				} else if (oPaging.iPage <= iHalf) {
       
   357 					iStart = 1;
       
   358 					iEnd = iListLength;
       
   359 				} else if (oPaging.iPage >= (oPaging.iTotalPages-iHalf)) {
       
   360 					iStart = oPaging.iTotalPages - iListLength + 1;
       
   361 					iEnd = oPaging.iTotalPages;
       
   362 				} else {
       
   363 					iStart = oPaging.iPage - iHalf + 1;
       
   364 					iEnd = iStart + iListLength - 1;
       
   365 				}
       
   366 
       
   367 				for (i=0, iLen=an.length ; i<iLen ; i++) {
       
   368 					// Add / remove disabled classes from the static elements
       
   369 					if (oPaging.iPage === 0) {
       
   370 						$('li.first', an[i]).addClass('disabled');
       
   371 						$('li.prev', an[i]).addClass('disabled');
       
   372 					} else {
       
   373 						$('li.prev', an[i]).removeClass('disabled');
       
   374 						$('li.first', an[i]).removeClass('disabled');
       
   375 					}
       
   376 
       
   377 					if (oPaging.iPage === oPaging.iTotalPages-1 || oPaging.iTotalPages === 0) {
       
   378 						$('li.last', an[i]).addClass('disabled');
       
   379 						$('li.next', an[i]).addClass('disabled');
       
   380 					} else {
       
   381 						$('li.next', an[i]).removeClass('disabled');
       
   382 						$('li.last', an[i]).removeClass('disabled');
       
   383 					}
       
   384 				}
       
   385 			}
       
   386 		}
       
   387 	});
       
   388 
       
   389 
       
   390 	/*
       
   391 	 * TableTools Bootstrap compatibility
       
   392 	 * Required TableTools 2.1+
       
   393 	 */
       
   394 	if ($.fn.DataTable.TableTools) {
       
   395 
       
   396 		// Set the classes that TableTools uses to something suitable for Bootstrap
       
   397 		$.extend(true, $.fn.DataTable.TableTools.classes, {
       
   398 			"container": "DTTT btn-group",
       
   399 			"buttons": {
       
   400 				"normal": "btn btn-default btn-sm",
       
   401 				"disabled": "disabled"
       
   402 			},
       
   403 			"collection": {
       
   404 				"container": "DTTT_dropdown dropdown-menu",
       
   405 				"buttons": {
       
   406 					"normal": "",
       
   407 					"disabled": "disabled"
       
   408 				}
       
   409 			},
       
   410 			"print": {
       
   411 				"info": "DTTT_print_info modal"
       
   412 			},
       
   413 			"select": {
       
   414 				"row": "active"
       
   415 			}
       
   416 		} );
       
   417 
       
   418 		// Have the collection use a bootstrap compatible dropdown
       
   419 		$.extend(true, $.fn.DataTable.TableTools.DEFAULTS.oTags, {
       
   420 			"collection": {
       
   421 				"container": "ul",
       
   422 				"button": "li",
       
   423 				"liner": "a"
       
   424 			}
       
   425 		});
       
   426 	}
       
   427 
       
   428 
       
   429 	/**
       
   430 	 * Length and filter extensions
       
   431 	 * Just replace 'l' and 'f' in sDom property by 'L' and 'F' to use them
       
   432 	 */
       
   433 
       
   434 	/**
       
   435 	 * Bootstrap length factory
       
   436 	 */
       
   437 	var bl_factory = function($, DataTable) {
       
   438 
       
   439 		var BootstrapLength = function(oSettings, oInit) {
       
   440 
       
   441 			if (!this.CLASS || this.CLASS !== 'BootstrapLength') {
       
   442 				if (globals.alert) {
       
   443 					globals.alert("Warning: BootstrapLength must be initialized with the 'new' keyword");
       
   444 				}
       
   445 			}
       
   446 			if (typeof(oInit) === 'undefined') {
       
   447 				oInit = {};
       
   448 			}
       
   449 			if ($.fn.dataTable.camelToHungarian) {
       
   450 				$.fn.dataTable.camelToHungarian(BootstrapLength.defaults, oInit);
       
   451 			}
       
   452 
       
   453 			this.s = {
       
   454 				dt: null,
       
   455 				oInit: oInit,
       
   456 				hidden: true,
       
   457 				abOriginal: []
       
   458 			};
       
   459 			this.dom = {
       
   460 				wrapper: null,
       
   461 				input: null
       
   462 			};
       
   463 			BootstrapLength.aInstances.push(this);
       
   464 
       
   465 			this.s.dt = $.fn.dataTable.Api ?
       
   466 				new $.fn.dataTable.Api(oSettings).settings()[0]
       
   467 				: oSettings;
       
   468 
       
   469 			this._fnConstruct(oInit);
       
   470 			return this;
       
   471 		};
       
   472 
       
   473 		BootstrapLength.prototype = {
       
   474 
       
   475 			input: function() {
       
   476 				return this.dom.wrapper;
       
   477 			},
       
   478 
       
   479 			fnRebuild: function() {
       
   480 				return this.rebuild();
       
   481 			},
       
   482 
       
   483 			rebuild: function() {
       
   484 			},
       
   485 
       
   486 			_fnConstruct: function(init) {
       
   487 				var self = this;
       
   488 				var dt = self.s.dt;
       
   489 				if (dt.oScroll.bInfinite) {
       
   490 					return;
       
   491 				}
       
   492 				var sName = dt.sTableId + '_length';
       
   493 				var sMenu = $('<select size="1"></select>').attr('name', sName);
       
   494 				var i, iLen;
       
   495 				var aLengthMenu = dt.aLengthMenu;
       
   496 				if (aLengthMenu.length === 2 &&
       
   497 					typeof(aLengthMenu[0]) === 'object' &&
       
   498 					typeof(aLengthMenu[1]) === 'object') {
       
   499 					for (i=0, iLen=aLengthMenu[0].length; i < iLen; i++) {
       
   500 						$('<option />').attr('value', aLengthMenu[0][i])
       
   501 									   .text(aLengthMenu[1][i])
       
   502 									   .appendTo(sMenu);
       
   503 					}
       
   504 				} else {
       
   505 					for (i=0, iLen=aLengthMenu.length; i < iLen; i++) {
       
   506 						$('<option />').attr('value', aLengthMenu[i])
       
   507 									   .text(aLengthMenu[i])
       
   508 									   .appendTo(sMenu);
       
   509 					}
       
   510 				}
       
   511 				var nLength = $('<div>').addClass(dt.oClasses.sLength)
       
   512 										.append($('<span></span>').addClass('ams-form')
       
   513 																  .append($('<label></label>').addClass('select')
       
   514 																							  .css('width', 60)
       
   515 																							  .append(sMenu)
       
   516 																							  .append($('<i></i>'))));
       
   517 				if (!dt.aanFeatures.L) {
       
   518 					nLength.attr('id', dt.sTableId + '_length');
       
   519 				}
       
   520 				this.dom.wrapper = nLength.get(0);
       
   521 
       
   522 				$('select option[value="' + dt._iDisplayLength + '"]', nLength).attr("selected", true);
       
   523 				$("select", nLength).on('change.DT', function(e) {
       
   524 					var iVal = $(this).val();
       
   525 					var n = dt.aanFeatures.L;
       
   526 					for (i = 0, iLen = n.length; i < iLen; i++) {
       
   527 						if (n[i] !== this.parentNode) {
       
   528 							$("select", n[i]).val(iVal);
       
   529 						}
       
   530 					}
       
   531 					dt._iDisplayLength = parseInt(iVal, 10);
       
   532 					dt.oInstance._fnCalculateEnd(dt);
       
   533 					if (dt.fnDisplayEnd() === dt.fnRecordsDisplay()) {
       
   534 						dt._iDisplayStart = dt.fnDisplayEnd() - dt._iDisplayLength;
       
   535 						if (dt._iDisplayStart < 0) {
       
   536 							dt._iDisplayStart = 0;
       
   537 						}
       
   538 					}
       
   539 					if (dt._iDisplayLength === -1) {
       
   540 						dt._iDisplayStart = 0;
       
   541 					}
       
   542 					dt.oInstance._fnDraw();
       
   543 				});
       
   544 				$("select", nLength).attr("aria-controls", dt.sTableId);
       
   545 			}
       
   546 		};
       
   547 
       
   548 		BootstrapLength.fnRebuild = function(oTable) {};
       
   549 
       
   550 		BootstrapLength.defaults = {};
       
   551 		BootstrapLength.aInstances = [];
       
   552 		BootstrapLength.prototype.CLASS = 'BootstrapLength';
       
   553 
       
   554 		BootstrapLength.VERSION = '1.0.0';
       
   555 		BootstrapLength.prototype.VERSION = BootstrapLength.VERSION;
       
   556 
       
   557 		if ((typeof($.fn.dataTable) === 'function') &&
       
   558 			(typeof($.fn.dataTableExt.fnVersionCheck) === 'function') &&
       
   559 			$.fn.dataTableExt.fnVersionCheck('1.7.0')) {
       
   560 			$.fn.dataTableExt.aoFeatures.push({
       
   561 				fnInit: function(oSettings) {
       
   562 					var init = oSettings.oInit;
       
   563 					var Length = new BootstrapLength(oSettings, init.bootstrapLength || init.oBootstrapLength || {});
       
   564 					return Length.input();
       
   565 				},
       
   566 				cFeature: 'L',
       
   567 				sFeature: "BootstrapLength"
       
   568 			});
       
   569 		} else {
       
   570 			if (globals.alert) {
       
   571 				globals.alert("Warning: BootstrapLength required DataTables 1.7 or greater...");
       
   572 			}
       
   573 		}
       
   574 
       
   575 		$.fn.dataTable.BootstrapLength = BootstrapLength;
       
   576 		return BootstrapLength;
       
   577 
       
   578 	};
       
   579 
       
   580 	if (!$.fn.dataTable.BootstrapLength) {
       
   581 		bl_factory($, $.fn.dataTable);
       
   582 	}
       
   583 
       
   584 
       
   585 	/**
       
   586 	 * Bootstrap filter factory
       
   587 	 */
       
   588 	var bf_factory = function($, DataTable) {
       
   589 
       
   590 		var BootstrapFilter = function(oSettings, oInit) {
       
   591 
       
   592 			if (!this.CLASS || this.CLASS !== 'BootstrapFilter') {
       
   593 				if (globals.alert) {
       
   594 					globals.alert("Warning: BootstrapFilter must be initialized with the 'new' keyword");
       
   595 				}
       
   596 			}
       
   597 			if (typeof(oInit) === 'undefined') {
       
   598 				oInit = {};
       
   599 			}
       
   600 			if ($.fn.dataTable.camelToHungarian) {
       
   601 				$.fn.dataTable.camelToHungarian(BootstrapFilter.defaults, oInit);
       
   602 			}
       
   603 
       
   604 			this.s = {
       
   605 				dt: null,
       
   606 				oInit: oInit,
       
   607 				hidden: true,
       
   608 				abOriginal: []
       
   609 			};
       
   610 			this.dom = {
       
   611 				wrapper: null,
       
   612 				input: null
       
   613 			};
       
   614 			BootstrapFilter.aInstances.push(this);
       
   615 
       
   616 			this.s.dt = $.fn.dataTable.Api ?
       
   617 				new $.fn.dataTable.Api(oSettings).settings()[0]
       
   618 				: oSettings;
       
   619 
       
   620 			this._fnConstruct(oInit);
       
   621 			return this;
       
   622 		};
       
   623 
       
   624 		BootstrapFilter.prototype = {
       
   625 
       
   626 			input: function() {
       
   627 				return this.dom.wrapper;
       
   628 			},
       
   629 
       
   630 			fnRebuild: function() {
       
   631 				return this.rebuild();
       
   632 			},
       
   633 
       
   634 			rebuild: function() {
       
   635 			},
       
   636 
       
   637 			_fnConstruct: function(init) {
       
   638 				var self = this;
       
   639 				var dt = self.s.dt;
       
   640 				var oPreviousSearch = dt.oPreviousSearch;
       
   641 				var sSearchStr = '<input type="text">';
       
   642 				var nFilter = $('<div>').addClass(dt.oClasses.sFilter)
       
   643 										.html('<div class="input-group">' +
       
   644 													'<span class="input-group-addon"><i class="fa fa-search"></i></span>' +
       
   645 													sSearchStr +
       
   646 											  '</div>');
       
   647 				if (!dt.aanFeatures.F)
       
   648 					nFilter.attr('id', dt.sTableId + '_filter');
       
   649 				this.dom.wrapper = nFilter.get(0);
       
   650 
       
   651 				var jqFilter = $('input[type="text"]', nFilter);
       
   652 				nFilter.data('DT_Input', jqFilter[0]);
       
   653 				jqFilter.val(oPreviousSearch.sSearch.replace('"', "&quot;"))
       
   654 						.addClass('form-control')
       
   655 						.attr('placeholder', dt.oLanguage.sSearch)
       
   656 						.attr('aria-control', dt.sTableId)
       
   657 						.on('keyup.DT', function(e) {
       
   658 							var n = dt.aanFeatures.F;
       
   659 							var val = $(this).val();
       
   660 							for (var i = 0, iLen = n.length; i < iLen; i++) {
       
   661 								if (n[i] !== $(this).parents("div.dataTables_filter")[0]) {
       
   662 									$(n[i]).data('DT_Input').val(val);
       
   663 								}
       
   664 							}
       
   665 							if (val !== oPreviousSearch.sSearch) {
       
   666 								dt.oInstance._fnFilterComplete({
       
   667 									sSearch: val,
       
   668 									bRegex: oPreviousSearch.bRegex,
       
   669 									bSmart: oPreviousSearch.bSmart,
       
   670 									bCaseInsensitive: oPreviousSearch.bCaseInsensitive
       
   671 								});
       
   672 							}
       
   673 						})
       
   674 						.on('keypress.DT', function(e) {
       
   675 							if (e.keyCode === 13) {
       
   676 								return false;
       
   677 							}
       
   678 						});
       
   679 			}
       
   680 		};
       
   681 
       
   682 		BootstrapFilter.fnRebuild = function(oTable) {};
       
   683 
       
   684 		BootstrapFilter.defaults = {};
       
   685 		BootstrapFilter.aInstances = [];
       
   686 		BootstrapFilter.prototype.CLASS = 'BootstrapFilter';
       
   687 
       
   688 		BootstrapFilter.VERSION = '1.0.0';
       
   689 		BootstrapFilter.prototype.VERSION = BootstrapFilter.VERSION;
       
   690 
       
   691 		if ((typeof($.fn.dataTable) === 'function') &&
       
   692 			(typeof($.fn.dataTableExt.fnVersionCheck) === 'function') &&
       
   693 			$.fn.dataTableExt.fnVersionCheck('1.7.0')) {
       
   694 			$.fn.dataTableExt.aoFeatures.push({
       
   695 				fnInit: function(oSettings) {
       
   696 					var init = oSettings.oInit;
       
   697 					var filter = new BootstrapFilter(oSettings, init.bootstrapFilter || init.oBootstrapFilter || {});
       
   698 					return filter.input();
       
   699 				},
       
   700 				cFeature: 'F',
       
   701 				sFeature: "BootstrapFilter"
       
   702 			});
       
   703 		} else {
       
   704 			if (globals.alert) {
       
   705 				globals.alert("Warning: BootstrapFilter required DataTables 1.7 or greater...");
       
   706 			}
       
   707 		}
       
   708 
       
   709 		$.fn.dataTable.BootstrapFilter = BootstrapFilter;
       
   710 		return BootstrapFilter;
       
   711 
       
   712 	};
       
   713 
       
   714 	if (!$.fn.dataTable.BootstrapFilter) {
       
   715 		bf_factory($, $.fn.dataTable);
       
   716 	}
       
   717 
       
   718 })(jQuery, this);