Commit c0a612e8745585e510a4bdbff8bc3bd9b40da91e

Authored by 李强
1 parent 17670853

5.30号增加站点和路段功能提交

src/main/java/com/bsth/controller/LineInformationController.java
... ... @@ -4,7 +4,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
4 4 import org.springframework.web.bind.annotation.RestController;
5 5  
6 6 import com.bsth.entity.LineInformation;
7   -import com.bsth.entity.Section;
8 7  
9 8 /**
10 9 *
... ...
src/main/java/com/bsth/controller/StationRouteController.java
1 1 package com.bsth.controller;
2 2  
  3 +import org.springframework.beans.factory.annotation.Autowired;
3 4 import org.springframework.web.bind.annotation.RequestMapping;
4 5 import org.springframework.web.bind.annotation.RestController;
5 6  
6 7 import com.bsth.entity.StationRoute;
  8 +import com.bsth.service.StationRouteService;
7 9  
8 10 /**
9 11 *
... ... @@ -23,5 +25,25 @@ import com.bsth.entity.StationRoute;
23 25 @RestController
24 26 @RequestMapping("stationroute")
25 27 public class StationRouteController extends BaseController<StationRoute, Integer> {
  28 +
  29 + @Autowired
  30 + StationRouteService service;
  31 +
  32 + /*
  33 + public Page<StationRoute> list(Map<String, Object> map,
  34 + @RequestParam(defaultValue = "0") int page,
  35 + @RequestParam(defaultValue = "5") int size,
  36 + @RequestParam(defaultValue = "id") String order,
  37 + @RequestParam(defaultValue = "DESC") String direction) {
  38 +
  39 + Direction d;
  40 +
  41 + if(null != direction && direction.equals("ASC"))
  42 + d = Direction.ASC;
  43 + else
  44 + d = Direction.DESC;
  45 +
  46 + return service.list(map, new PageRequest(page, size, new Sort(d, order)));
  47 + }*/
26 48  
27 49 }
... ...
src/main/resources/static/index.html
... ... @@ -34,8 +34,12 @@
34 34 <!-- 日期控件 -->
35 35 <link href="/metronic_v4.5.4/plugins/bootstrap-datetimepicker-2/css/bootstrap-datetimepicker.min.css" rel="stylesheet" type="text/css" />
36 36  
  37 +<!-- table 表格控件 -->
  38 +<link href="/metronic_v4.5.4/plugins/bootstrap-datatables/css/datatables.bootstrap.css" rel="stylesheet" type="text/css" />
  39 +<link href="/metronic_v4.5.4/plugins/bootstrap-datatables/css/datatables.css" rel="stylesheet" type="text/css" />
37 40 <style type="text/css">
38 41 .searchForm{
  42 +
39 43 }
40 44 .searchForm .form-group .control-label{
41 45 padding-right: 0px;
... ... @@ -268,7 +272,10 @@ tr.row-active td {
268 272 <script src="/assets/plugins/pinyin.js"></script>
269 273 <!-- 日期控件 -->
270 274 <script src="/metronic_v4.5.4/plugins/bootstrap-datetimepicker-2/js/bootstrap-datetimepicker.min.js" type="text/javascript"></script>
271   -
  275 +<!-- 表格控件 -->
  276 +<script src="/metronic_v4.5.4/scripts/datatable.js" type="text/javascript"></script>
  277 +<script src="/metronic_v4.5.4/plugins/bootstrap-datatables/datatables.js" type="text/javascript"></script>
  278 +<script src="/metronic_v4.5.4/plugins/bootstrap-datatables/datatables.bootstrap.js" type="text/javascript"></script>
272 279 <!-- 地图相关 -->
273 280 <!-- 百度 -->
274 281 <script src="http://api.map.baidu.com/api?v=2.0&ak=IGGrr4UjwIYzatoCRFKEL8sT" ></script>
... ...
src/main/resources/static/metronic_v4.5.4/plugins/bootstrap-datatables/css/datatables.bootstrap.css 0 → 100644
  1 +table.dataTable {
  2 + clear: both;
  3 + margin-top: 6px !important;
  4 + margin-bottom: 6px !important;
  5 + max-width: none !important;
  6 +}
  7 +table.dataTable td, table.dataTable th {
  8 + -webkit-box-sizing: content-box;
  9 + -moz-box-sizing: content-box;
  10 + box-sizing: content-box;
  11 +}
  12 +table.dataTable td.dataTables_empty, table.dataTable th.dataTables_empty {
  13 + text-align: center;
  14 +}
  15 +table.dataTable.nowrap th, table.dataTable.nowrap td {
  16 + white-space: nowrap;
  17 +}
  18 +div.dataTables_wrapper div.dataTables_length label {
  19 + font-weight: normal;
  20 + text-align: left;
  21 + white-space: nowrap;
  22 +}
  23 +div.dataTables_wrapper div.dataTables_length select {
  24 + width: 75px;
  25 + display: inline-block;
  26 +}
  27 +div.dataTables_wrapper div.dataTables_filter {
  28 + text-align: right;
  29 +}
  30 +div.dataTables_wrapper div.dataTables_filter label {
  31 + font-weight: normal;
  32 + white-space: nowrap;
  33 + text-align: left;
  34 +}
  35 +div.dataTables_wrapper div.dataTables_filter input {
  36 + margin-left: 0.5em;
  37 + display: inline-block;
  38 + width: auto;
  39 +}
  40 +div.dataTables_wrapper div.dataTables_info {
  41 + padding-top: 8px;
  42 + white-space: nowrap;
  43 +}
  44 +div.dataTables_wrapper div.dataTables_paginate {
  45 + margin: 0;
  46 + white-space: nowrap;
  47 + text-align: right;
  48 +}
  49 +div.dataTables_wrapper div.dataTables_paginate ul.pagination {
  50 + margin: 2px 0;
  51 + white-space: nowrap;
  52 +}
  53 +table.dataTable thead>tr>th.sorting_asc, table.dataTable thead>tr>th.sorting_desc, table.dataTable thead>tr>th.sorting, table.dataTable thead>tr>td.sorting_asc, table.dataTable thead>tr>td.sorting_desc, table.dataTable thead>tr>td.sorting {
  54 + padding-right: 30px;
  55 +}
  56 +table.dataTable thead>tr>th:active, table.dataTable thead>tr>td:active {
  57 + outline: none;
  58 +}
  59 +table.dataTable thead .sorting, table.dataTable thead .sorting_asc, table.dataTable thead .sorting_desc, table.dataTable thead .sorting_asc_disabled, table.dataTable thead .sorting_desc_disabled {
  60 + cursor: pointer;
  61 + position: relative;
  62 +}
  63 +table.dataTable thead .sorting:after, table.dataTable thead .sorting_asc:after, table.dataTable thead .sorting_desc:after, table.dataTable thead .sorting_asc_disabled:after, table.dataTable thead .sorting_desc_disabled:after {
  64 + position: absolute;
  65 + bottom: 8px;
  66 + right: 8px;
  67 + display: block;
  68 + font-family: 'Glyphicons Halflings';
  69 + opacity: 0.5;
  70 +}
  71 +table.dataTable thead .sorting:after {
  72 + opacity: 0.2;
  73 + content: "\e150"}
  74 +table.dataTable thead .sorting_asc:after {
  75 + content: "\e155"}
  76 +table.dataTable thead .sorting_desc:after {
  77 + content: "\e156"}
  78 +table.dataTable thead .sorting_asc_disabled:after, table.dataTable thead .sorting_desc_disabled:after {
  79 + color: #eee;
  80 +}
  81 +div.dataTables_scrollHead table.dataTable {
  82 + margin-bottom: 0 !important;
  83 +}
  84 +div.dataTables_scrollBody table {
  85 + border-top: none;
  86 + margin-top: 0 !important;
  87 + margin-bottom: 0 !important;
  88 +}
  89 +div.dataTables_scrollBody table thead .sorting:after, div.dataTables_scrollBody table thead .sorting_asc:after, div.dataTables_scrollBody table thead .sorting_desc:after {
  90 + display: none;
  91 +}
  92 +div.dataTables_scrollBody table tbody tr:first-child th, div.dataTables_scrollBody table tbody tr:first-child td {
  93 + border-top: none;
  94 +}
  95 +div.dataTables_scrollFoot table {
  96 + margin-top: 0 !important;
  97 + border-top: none;
  98 +}
  99 +@media screen and (max-width: 767px) {
  100 + div.dataTables_wrapper div.dataTables_length, div.dataTables_wrapper div.dataTables_filter, div.dataTables_wrapper div.dataTables_info, div.dataTables_wrapper div.dataTables_paginate {
  101 + text-align: center;
  102 +}
  103 +}table.dataTable.table-condensed>thead>tr>th {
  104 + padding-right: 20px;
  105 +}
  106 +table.dataTable.table-condensed .sorting:after, table.dataTable.table-condensed .sorting_asc:after, table.dataTable.table-condensed .sorting_desc:after {
  107 + top: 6px;
  108 + right: 6px;
  109 +}
  110 +table.table-bordered.dataTable {
  111 + border-collapse: separate !important;
  112 +}
  113 +table.table-bordered.dataTable th, table.table-bordered.dataTable td {
  114 + border-left-width: 0;
  115 +}
  116 +table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable td:last-child, table.table-bordered.dataTable td:last-child {
  117 + border-right-width: 0;
  118 +}
  119 +table.table-bordered.dataTable tbody th, table.table-bordered.dataTable tbody td {
  120 + border-bottom-width: 0;
  121 +}
  122 +div.dataTables_scrollHead table.table-bordered {
  123 + border-bottom-width: 0;
  124 +}
0 125 \ No newline at end of file
... ...
src/main/resources/static/metronic_v4.5.4/plugins/bootstrap-datatables/css/datatables.css 0 → 100644
  1 +/*
  2 + * This combined file was created by the DataTables downloader builder:
  3 + * https://datatables.net/download
  4 + *
  5 + * To rebuild or modify this file with the latest versions of the included
  6 + * software please visit:
  7 + * https://datatables.net/download/#dt/jszip-2.5.0,pdfmake-0.1.18,dt-1.10.10,af-2.1.0,b-1.1.0,b-colvis-1.1.0,b-flash-1.1.0,b-html5-1.1.0,b-print-1.1.0,cr-1.3.0,fc-3.2.0,fh-3.1.0,r-2.0.0,rr-1.1.0,sc-1.4.0,se-1.1.0
  8 + *
  9 + * Included libraries:
  10 + * JSZip 2.5.0, pdfmake 0.1.18, DataTables 1.10.10, AutoFill 2.1.0, Buttons 1.1.0, Column visibility 1.1.0, Flash export 1.1.0, HTML5 export 1.1.0, Print view 1.1.0, ColReorder 1.3.0, FixedColumns 3.2.0, FixedHeader 3.1.0, Responsive 2.0.0, RowReorder 1.1.0, Scroller 1.4.0, Select 1.1.0
  11 + */
  12 +
  13 +/*
  14 + * Table styles
  15 + */
  16 +table.dataTable {
  17 + width: 100%;
  18 + margin: 0 auto;
  19 + clear: both;
  20 + border-collapse: separate;
  21 + border-spacing: 0;
  22 + /*
  23 + * Header and footer styles
  24 + */
  25 + /*
  26 + * Body styles
  27 + */
  28 +}
  29 +table.dataTable thead th,
  30 +table.dataTable tfoot th {
  31 + font-weight: bold;
  32 +}
  33 +table.dataTable thead th,
  34 +table.dataTable thead td {
  35 + padding: 10px 18px;
  36 + border-bottom: 1px solid #111;
  37 +}
  38 +table.dataTable thead th:active,
  39 +table.dataTable thead td:active {
  40 + outline: none;
  41 +}
  42 +table.dataTable tfoot th,
  43 +table.dataTable tfoot td {
  44 + padding: 10px 18px 6px 18px;
  45 + border-top: 1px solid #111;
  46 +}
  47 +table.dataTable thead .sorting,
  48 +table.dataTable thead .sorting_asc,
  49 +table.dataTable thead .sorting_desc {
  50 + cursor: pointer;
  51 + *cursor: hand;
  52 +}
  53 +table.dataTable thead .sorting,
  54 +table.dataTable thead .sorting_asc,
  55 +table.dataTable thead .sorting_desc,
  56 +table.dataTable thead .sorting_asc_disabled,
  57 +table.dataTable thead .sorting_desc_disabled {
  58 + background-repeat: no-repeat;
  59 + background-position: center right;
  60 +}
  61 +table.dataTable thead .sorting {
  62 + background-image: url("DataTables-1.10.10/images/sort_both.png");
  63 +}
  64 +table.dataTable thead .sorting_asc {
  65 + background-image: url("DataTables-1.10.10/images/sort_asc.png");
  66 +}
  67 +table.dataTable thead .sorting_desc {
  68 + background-image: url("DataTables-1.10.10/images/sort_desc.png");
  69 +}
  70 +table.dataTable thead .sorting_asc_disabled {
  71 + background-image: url("DataTables-1.10.10/images/sort_asc_disabled.png");
  72 +}
  73 +table.dataTable thead .sorting_desc_disabled {
  74 + background-image: url("DataTables-1.10.10/images/sort_desc_disabled.png");
  75 +}
  76 +table.dataTable tbody tr {
  77 + background-color: #ffffff;
  78 +}
  79 +table.dataTable tbody tr.selected {
  80 + background-color: #B0BED9;
  81 +}
  82 +table.dataTable tbody th,
  83 +table.dataTable tbody td {
  84 + padding: 8px 10px;
  85 +}
  86 +table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
  87 + border-top: 1px solid #ddd;
  88 +}
  89 +table.dataTable.row-border tbody tr:first-child th,
  90 +table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,
  91 +table.dataTable.display tbody tr:first-child td {
  92 + border-top: none;
  93 +}
  94 +table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {
  95 + border-top: 1px solid #ddd;
  96 + border-right: 1px solid #ddd;
  97 +}
  98 +table.dataTable.cell-border tbody tr th:first-child,
  99 +table.dataTable.cell-border tbody tr td:first-child {
  100 + border-left: 1px solid #ddd;
  101 +}
  102 +table.dataTable.cell-border tbody tr:first-child th,
  103 +table.dataTable.cell-border tbody tr:first-child td {
  104 + border-top: none;
  105 +}
  106 +table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
  107 + background-color: #f9f9f9;
  108 +}
  109 +table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
  110 + background-color: #acbad4;
  111 +}
  112 +table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover {
  113 + background-color: #f6f6f6;
  114 +}
  115 +table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected {
  116 + background-color: #aab7d1;
  117 +}
  118 +table.dataTable.order-column tbody tr > .sorting_1,
  119 +table.dataTable.order-column tbody tr > .sorting_2,
  120 +table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,
  121 +table.dataTable.display tbody tr > .sorting_2,
  122 +table.dataTable.display tbody tr > .sorting_3 {
  123 + background-color: #fafafa;
  124 +}
  125 +table.dataTable.order-column tbody tr.selected > .sorting_1,
  126 +table.dataTable.order-column tbody tr.selected > .sorting_2,
  127 +table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,
  128 +table.dataTable.display tbody tr.selected > .sorting_2,
  129 +table.dataTable.display tbody tr.selected > .sorting_3 {
  130 + background-color: #acbad5;
  131 +}
  132 +table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
  133 + background-color: #f1f1f1;
  134 +}
  135 +table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
  136 + background-color: #f3f3f3;
  137 +}
  138 +table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
  139 + background-color: whitesmoke;
  140 +}
  141 +table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
  142 + background-color: #a6b4cd;
  143 +}
  144 +table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
  145 + background-color: #a8b5cf;
  146 +}
  147 +table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
  148 + background-color: #a9b7d1;
  149 +}
  150 +table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
  151 + background-color: #fafafa;
  152 +}
  153 +table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
  154 + background-color: #fcfcfc;
  155 +}
  156 +table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
  157 + background-color: #fefefe;
  158 +}
  159 +table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
  160 + background-color: #acbad5;
  161 +}
  162 +table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
  163 + background-color: #aebcd6;
  164 +}
  165 +table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
  166 + background-color: #afbdd8;
  167 +}
  168 +table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
  169 + background-color: #eaeaea;
  170 +}
  171 +table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
  172 + background-color: #ececec;
  173 +}
  174 +table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
  175 + background-color: #efefef;
  176 +}
  177 +table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
  178 + background-color: #a2aec7;
  179 +}
  180 +table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
  181 + background-color: #a3b0c9;
  182 +}
  183 +table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
  184 + background-color: #a5b2cb;
  185 +}
  186 +table.dataTable.no-footer {
  187 + border-bottom: 1px solid #111;
  188 +}
  189 +table.dataTable.nowrap th, table.dataTable.nowrap td {
  190 + white-space: nowrap;
  191 +}
  192 +table.dataTable.compact thead th,
  193 +table.dataTable.compact thead td {
  194 + padding: 4px 17px 4px 4px;
  195 +}
  196 +table.dataTable.compact tfoot th,
  197 +table.dataTable.compact tfoot td {
  198 + padding: 4px;
  199 +}
  200 +table.dataTable.compact tbody th,
  201 +table.dataTable.compact tbody td {
  202 + padding: 4px;
  203 +}
  204 +table.dataTable th.dt-left,
  205 +table.dataTable td.dt-left {
  206 + text-align: left;
  207 +}
  208 +table.dataTable th.dt-center,
  209 +table.dataTable td.dt-center,
  210 +table.dataTable td.dataTables_empty {
  211 + text-align: center;
  212 +}
  213 +table.dataTable th.dt-right,
  214 +table.dataTable td.dt-right {
  215 + text-align: right;
  216 +}
  217 +table.dataTable th.dt-justify,
  218 +table.dataTable td.dt-justify {
  219 + text-align: justify;
  220 +}
  221 +table.dataTable th.dt-nowrap,
  222 +table.dataTable td.dt-nowrap {
  223 + white-space: nowrap;
  224 +}
  225 +table.dataTable thead th.dt-head-left,
  226 +table.dataTable thead td.dt-head-left,
  227 +table.dataTable tfoot th.dt-head-left,
  228 +table.dataTable tfoot td.dt-head-left {
  229 + text-align: left;
  230 +}
  231 +table.dataTable thead th.dt-head-center,
  232 +table.dataTable thead td.dt-head-center,
  233 +table.dataTable tfoot th.dt-head-center,
  234 +table.dataTable tfoot td.dt-head-center {
  235 + text-align: center;
  236 +}
  237 +table.dataTable thead th.dt-head-right,
  238 +table.dataTable thead td.dt-head-right,
  239 +table.dataTable tfoot th.dt-head-right,
  240 +table.dataTable tfoot td.dt-head-right {
  241 + text-align: right;
  242 +}
  243 +table.dataTable thead th.dt-head-justify,
  244 +table.dataTable thead td.dt-head-justify,
  245 +table.dataTable tfoot th.dt-head-justify,
  246 +table.dataTable tfoot td.dt-head-justify {
  247 + text-align: justify;
  248 +}
  249 +table.dataTable thead th.dt-head-nowrap,
  250 +table.dataTable thead td.dt-head-nowrap,
  251 +table.dataTable tfoot th.dt-head-nowrap,
  252 +table.dataTable tfoot td.dt-head-nowrap {
  253 + white-space: nowrap;
  254 +}
  255 +table.dataTable tbody th.dt-body-left,
  256 +table.dataTable tbody td.dt-body-left {
  257 + text-align: left;
  258 +}
  259 +table.dataTable tbody th.dt-body-center,
  260 +table.dataTable tbody td.dt-body-center {
  261 + text-align: center;
  262 +}
  263 +table.dataTable tbody th.dt-body-right,
  264 +table.dataTable tbody td.dt-body-right {
  265 + text-align: right;
  266 +}
  267 +table.dataTable tbody th.dt-body-justify,
  268 +table.dataTable tbody td.dt-body-justify {
  269 + text-align: justify;
  270 +}
  271 +table.dataTable tbody th.dt-body-nowrap,
  272 +table.dataTable tbody td.dt-body-nowrap {
  273 + white-space: nowrap;
  274 +}
  275 +
  276 +table.dataTable,
  277 +table.dataTable th,
  278 +table.dataTable td {
  279 + -webkit-box-sizing: content-box;
  280 + -moz-box-sizing: content-box;
  281 + box-sizing: content-box;
  282 +}
  283 +
  284 +/*
  285 + * Control feature layout
  286 + */
  287 +.dataTables_wrapper {
  288 + position: relative;
  289 + clear: both;
  290 + *zoom: 1;
  291 + zoom: 1;
  292 +}
  293 +.dataTables_wrapper .dataTables_length {
  294 + float: left;
  295 +}
  296 +.dataTables_wrapper .dataTables_filter {
  297 + float: right;
  298 + text-align: right;
  299 +}
  300 +.dataTables_wrapper .dataTables_filter input {
  301 + margin-left: 0.5em;
  302 +}
  303 +.dataTables_wrapper .dataTables_info {
  304 + clear: both;
  305 + float: left;
  306 + padding-top: 0.755em;
  307 +}
  308 +.dataTables_wrapper .dataTables_paginate {
  309 + float: right;
  310 + text-align: right;
  311 + padding-top: 0.25em;
  312 +}
  313 +.dataTables_wrapper .dataTables_paginate .paginate_button {
  314 + box-sizing: border-box;
  315 + display: inline-block;
  316 + min-width: 1.5em;
  317 + padding: 0.5em 1em;
  318 + margin-left: 2px;
  319 + text-align: center;
  320 + text-decoration: none !important;
  321 + cursor: pointer;
  322 + *cursor: hand;
  323 + color: #333 !important;
  324 + border: 1px solid transparent;
  325 + border-radius: 2px;
  326 +}
  327 +.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
  328 + color: #333 !important;
  329 + border: 1px solid #979797;
  330 + background-color: white;
  331 + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc));
  332 + /* Chrome,Safari4+ */
  333 + background: -webkit-linear-gradient(top, white 0%, #dcdcdc 100%);
  334 + /* Chrome10+,Safari5.1+ */
  335 + background: -moz-linear-gradient(top, white 0%, #dcdcdc 100%);
  336 + /* FF3.6+ */
  337 + background: -ms-linear-gradient(top, white 0%, #dcdcdc 100%);
  338 + /* IE10+ */
  339 + background: -o-linear-gradient(top, white 0%, #dcdcdc 100%);
  340 + /* Opera 11.10+ */
  341 + background: linear-gradient(to bottom, white 0%, #dcdcdc 100%);
  342 + /* W3C */
  343 +}
  344 +.dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
  345 + cursor: default;
  346 + color: #666 !important;
  347 + border: 1px solid transparent;
  348 + background: transparent;
  349 + box-shadow: none;
  350 +}
  351 +.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
  352 + color: white !important;
  353 + border: 1px solid #111;
  354 + background-color: #585858;
  355 + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
  356 + /* Chrome,Safari4+ */
  357 + background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
  358 + /* Chrome10+,Safari5.1+ */
  359 + background: -moz-linear-gradient(top, #585858 0%, #111 100%);
  360 + /* FF3.6+ */
  361 + background: -ms-linear-gradient(top, #585858 0%, #111 100%);
  362 + /* IE10+ */
  363 + background: -o-linear-gradient(top, #585858 0%, #111 100%);
  364 + /* Opera 11.10+ */
  365 + background: linear-gradient(to bottom, #585858 0%, #111 100%);
  366 + /* W3C */
  367 +}
  368 +.dataTables_wrapper .dataTables_paginate .paginate_button:active {
  369 + outline: none;
  370 + background-color: #2b2b2b;
  371 + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
  372 + /* Chrome,Safari4+ */
  373 + background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
  374 + /* Chrome10+,Safari5.1+ */
  375 + background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
  376 + /* FF3.6+ */
  377 + background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
  378 + /* IE10+ */
  379 + background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
  380 + /* Opera 11.10+ */
  381 + background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
  382 + /* W3C */
  383 + box-shadow: inset 0 0 3px #111;
  384 +}
  385 +.dataTables_wrapper .dataTables_paginate .ellipsis {
  386 + padding: 0 1em;
  387 +}
  388 +.dataTables_wrapper .dataTables_processing {
  389 + position: absolute;
  390 + top: 50%;
  391 + left: 50%;
  392 + width: 100%;
  393 + height: 40px;
  394 + margin-left: -50%;
  395 + margin-top: -25px;
  396 + padding-top: 20px;
  397 + text-align: center;
  398 + font-size: 1.2em;
  399 + background-color: white;
  400 + background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
  401 + background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
  402 + background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
  403 + background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
  404 + background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
  405 + background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
  406 +}
  407 +.dataTables_wrapper .dataTables_length,
  408 +.dataTables_wrapper .dataTables_filter,
  409 +.dataTables_wrapper .dataTables_info,
  410 +.dataTables_wrapper .dataTables_processing,
  411 +.dataTables_wrapper .dataTables_paginate {
  412 + color: #333;
  413 +}
  414 +.dataTables_wrapper .dataTables_scroll {
  415 + clear: both;
  416 +}
  417 +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
  418 + *margin-top: -1px;
  419 + -webkit-overflow-scrolling: touch;
  420 +}
  421 +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td {
  422 + vertical-align: middle;
  423 +}
  424 +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody th > div.dataTables_sizing,
  425 +.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody td > div.dataTables_sizing {
  426 + height: 0;
  427 + overflow: hidden;
  428 + margin: 0 !important;
  429 + padding: 0 !important;
  430 +}
  431 +.dataTables_wrapper.no-footer .dataTables_scrollBody {
  432 + border-bottom: 1px solid #111;
  433 +}
  434 +.dataTables_wrapper.no-footer div.dataTables_scrollHead table,
  435 +.dataTables_wrapper.no-footer div.dataTables_scrollBody table {
  436 + border-bottom: none;
  437 +}
  438 +.dataTables_wrapper:after {
  439 + visibility: hidden;
  440 + display: block;
  441 + content: "";
  442 + clear: both;
  443 + height: 0;
  444 +}
  445 +
  446 +@media screen and (max-width: 767px) {
  447 + .dataTables_wrapper .dataTables_info,
  448 + .dataTables_wrapper .dataTables_paginate {
  449 + float: none;
  450 + text-align: center;
  451 + }
  452 + .dataTables_wrapper .dataTables_paginate {
  453 + margin-top: 0.5em;
  454 + }
  455 +}
  456 +@media screen and (max-width: 640px) {
  457 + .dataTables_wrapper .dataTables_length,
  458 + .dataTables_wrapper .dataTables_filter {
  459 + float: none;
  460 + text-align: center;
  461 + }
  462 + .dataTables_wrapper .dataTables_filter {
  463 + margin-top: 0.5em;
  464 + }
  465 +}
  466 +
  467 +
  468 +div.dt-autofill-handle{position:absolute;height:8px;width:8px;z-index:102;box-sizing:border-box;border:1px solid #316ad1;background:linear-gradient(to bottom, #abcffb 0%, #4989de 100%)}div.dt-autofill-select{position:absolute;z-index:1001;background-color:#4989de;background-image:repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(255,255,255,0.5) 5px, rgba(255,255,255,0.5) 10px)}div.dt-autofill-select.top,div.dt-autofill-select.bottom{height:3px;margin-top:-1px}div.dt-autofill-select.left,div.dt-autofill-select.right{width:3px;margin-left:-1px}div.dt-autofill-list{position:fixed;top:50%;left:50%;width:500px;margin-left:-250px;background-color:white;border-radius:6px;box-shadow:0 0 5px #555;border:2px solid #444;z-index:11;box-sizing:border-box;padding:1.5em 2em}div.dt-autofill-list ul{display:table;margin:0;padding:0;list-style:none;width:100%}div.dt-autofill-list ul li{display:table-row}div.dt-autofill-list ul li:last-child div.dt-autofill-question,div.dt-autofill-list ul li:last-child div.dt-autofill-button{border-bottom:none}div.dt-autofill-list ul li:hover{background-color:#f6f6f6}div.dt-autofill-list div.dt-autofill-question{display:table-cell;padding:0.5em 0;border-bottom:1px solid #ccc}div.dt-autofill-list div.dt-autofill-question input[type=number]{padding:6px;width:30px;margin:-2px 0}div.dt-autofill-list div.dt-autofill-button{display:table-cell;padding:0.5em 0;border-bottom:1px solid #ccc}div.dt-autofill-list div.dt-autofill-button button{color:white;margin:0;padding:6px 12px;text-align:center;border:1px solid #2e6da4;background-color:#337ab7;border-radius:4px;cursor:pointer;vertical-align:middle}div.dt-autofill-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);background:radial-gradient(ellipse farthest-corner at center, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.7) 100%);z-index:10}
  469 +
  470 +
  471 +div.dt-button-info {
  472 + position: fixed;
  473 + top: 50%;
  474 + left: 50%;
  475 + width: 400px;
  476 + margin-top: -100px;
  477 + margin-left: -200px;
  478 + background-color: white;
  479 + border: 2px solid #111;
  480 + box-shadow: 3px 3px 8px rgba(0, 0, 0, 0.3);
  481 + border-radius: 3px;
  482 + text-align: center;
  483 + z-index: 21;
  484 +}
  485 +div.dt-button-info h2 {
  486 + padding: 0.5em;
  487 + margin: 0;
  488 + font-weight: normal;
  489 + border-bottom: 1px solid #ddd;
  490 + background-color: #f3f3f3;
  491 +}
  492 +div.dt-button-info > div {
  493 + padding: 1em;
  494 +}
  495 +
  496 +button.dt-button,
  497 +div.dt-button,
  498 +a.dt-button {
  499 + position: relative;
  500 + display: inline-block;
  501 + box-sizing: border-box;
  502 + margin-right: 0.333em;
  503 + padding: 0.5em 1em;
  504 + border: 1px solid #999;
  505 + border-radius: 2px;
  506 + cursor: pointer;
  507 + font-size: 0.88em;
  508 + color: black;
  509 + white-space: nowrap;
  510 + overflow: hidden;
  511 + background-color: #e9e9e9;
  512 + /* Fallback */
  513 + background-image: -webkit-linear-gradient(top, white 0%, #e9e9e9 100%);
  514 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  515 + background-image: -moz-linear-gradient(top, white 0%, #e9e9e9 100%);
  516 + /* FF3.6 */
  517 + background-image: -ms-linear-gradient(top, white 0%, #e9e9e9 100%);
  518 + /* IE10 */
  519 + background-image: -o-linear-gradient(top, white 0%, #e9e9e9 100%);
  520 + /* Opera 11.10+ */
  521 + background-image: linear-gradient(top, white 0%, #e9e9e9 100%);
  522 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='white', EndColorStr='#e9e9e9');
  523 + -webkit-user-select: none;
  524 + -moz-user-select: none;
  525 + -ms-user-select: none;
  526 + user-select: none;
  527 + text-decoration: none;
  528 + outline: none;
  529 +}
  530 +button.dt-button.disabled,
  531 +div.dt-button.disabled,
  532 +a.dt-button.disabled {
  533 + color: #999;
  534 + border: 1px solid #d0d0d0;
  535 + cursor: default;
  536 + background-color: #f9f9f9;
  537 + /* Fallback */
  538 + background-image: -webkit-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
  539 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  540 + background-image: -moz-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
  541 + /* FF3.6 */
  542 + background-image: -ms-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
  543 + /* IE10 */
  544 + background-image: -o-linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
  545 + /* Opera 11.10+ */
  546 + background-image: linear-gradient(top, #ffffff 0%, #f9f9f9 100%);
  547 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#ffffff', EndColorStr='#f9f9f9');
  548 +}
  549 +button.dt-button:active:not(.disabled), button.dt-button.active:not(.disabled),
  550 +div.dt-button:active:not(.disabled),
  551 +div.dt-button.active:not(.disabled),
  552 +a.dt-button:active:not(.disabled),
  553 +a.dt-button.active:not(.disabled) {
  554 + background-color: #e2e2e2;
  555 + /* Fallback */
  556 + background-image: -webkit-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
  557 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  558 + background-image: -moz-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
  559 + /* FF3.6 */
  560 + background-image: -ms-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
  561 + /* IE10 */
  562 + background-image: -o-linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
  563 + /* Opera 11.10+ */
  564 + background-image: linear-gradient(top, #f3f3f3 0%, #e2e2e2 100%);
  565 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f3f3f3', EndColorStr='#e2e2e2');
  566 + box-shadow: inset 1px 1px 3px #999999;
  567 +}
  568 +button.dt-button:active:not(.disabled):hover:not(.disabled), button.dt-button.active:not(.disabled):hover:not(.disabled),
  569 +div.dt-button:active:not(.disabled):hover:not(.disabled),
  570 +div.dt-button.active:not(.disabled):hover:not(.disabled),
  571 +a.dt-button:active:not(.disabled):hover:not(.disabled),
  572 +a.dt-button.active:not(.disabled):hover:not(.disabled) {
  573 + box-shadow: inset 1px 1px 3px #999999;
  574 + background-color: #cccccc;
  575 + /* Fallback */
  576 + background-image: -webkit-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
  577 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  578 + background-image: -moz-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
  579 + /* FF3.6 */
  580 + background-image: -ms-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
  581 + /* IE10 */
  582 + background-image: -o-linear-gradient(top, #eaeaea 0%, #cccccc 100%);
  583 + /* Opera 11.10+ */
  584 + background-image: linear-gradient(top, #eaeaea 0%, #cccccc 100%);
  585 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#eaeaea', EndColorStr='#cccccc');
  586 +}
  587 +button.dt-button:hover,
  588 +div.dt-button:hover,
  589 +a.dt-button:hover {
  590 + text-decoration: none;
  591 +}
  592 +button.dt-button:hover:not(.disabled),
  593 +div.dt-button:hover:not(.disabled),
  594 +a.dt-button:hover:not(.disabled) {
  595 + border: 1px solid #666;
  596 + background-color: #e0e0e0;
  597 + /* Fallback */
  598 + background-image: -webkit-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
  599 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  600 + background-image: -moz-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
  601 + /* FF3.6 */
  602 + background-image: -ms-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
  603 + /* IE10 */
  604 + background-image: -o-linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
  605 + /* Opera 11.10+ */
  606 + background-image: linear-gradient(top, #f9f9f9 0%, #e0e0e0 100%);
  607 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f9f9f9', EndColorStr='#e0e0e0');
  608 +}
  609 +button.dt-button:focus:not(.disabled),
  610 +div.dt-button:focus:not(.disabled),
  611 +a.dt-button:focus:not(.disabled) {
  612 + border: 1px solid #426c9e;
  613 + text-shadow: 0 1px 0 #c4def1;
  614 + outline: none;
  615 + background-color: #79ace9;
  616 + /* Fallback */
  617 + background-image: -webkit-linear-gradient(top, #bddef4 0%, #79ace9 100%);
  618 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  619 + background-image: -moz-linear-gradient(top, #bddef4 0%, #79ace9 100%);
  620 + /* FF3.6 */
  621 + background-image: -ms-linear-gradient(top, #bddef4 0%, #79ace9 100%);
  622 + /* IE10 */
  623 + background-image: -o-linear-gradient(top, #bddef4 0%, #79ace9 100%);
  624 + /* Opera 11.10+ */
  625 + background-image: linear-gradient(top, #bddef4 0%, #79ace9 100%);
  626 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#bddef4', EndColorStr='#79ace9');
  627 +}
  628 +
  629 +.dt-button embed {
  630 + outline: none;
  631 +}
  632 +
  633 +div.dt-buttons {
  634 + position: relative;
  635 + float: left;
  636 +}
  637 +div.dt-buttons.buttons-right {
  638 + float: right;
  639 +}
  640 +
  641 +div.dt-button-collection {
  642 + position: absolute;
  643 + top: 0;
  644 + left: 0;
  645 + width: 150px;
  646 + margin-top: 3px;
  647 + padding: 8px 8px 4px 8px;
  648 + border: 1px solid #ccc;
  649 + border: 1px solid rgba(0, 0, 0, 0.4);
  650 + background-color: white;
  651 + overflow: hidden;
  652 + z-index: 2002;
  653 + border-radius: 5px;
  654 + box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.3);
  655 + z-index: 2002;
  656 + -webkit-column-gap: 8px;
  657 + -moz-column-gap: 8px;
  658 + -ms-column-gap: 8px;
  659 + -o-column-gap: 8px;
  660 + column-gap: 8px;
  661 +}
  662 +div.dt-button-collection button.dt-button,
  663 +div.dt-button-collection div.dt-button,
  664 +div.dt-button-collection a.dt-button {
  665 + position: relative;
  666 + left: 0;
  667 + right: 0;
  668 + display: block;
  669 + float: none;
  670 + margin-bottom: 4px;
  671 + margin-right: 0;
  672 +}
  673 +div.dt-button-collection button.dt-button:active:not(.disabled), div.dt-button-collection button.dt-button.active:not(.disabled),
  674 +div.dt-button-collection div.dt-button:active:not(.disabled),
  675 +div.dt-button-collection div.dt-button.active:not(.disabled),
  676 +div.dt-button-collection a.dt-button:active:not(.disabled),
  677 +div.dt-button-collection a.dt-button.active:not(.disabled) {
  678 + background-color: #dadada;
  679 + /* Fallback */
  680 + background-image: -webkit-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
  681 + /* Chrome 10+, Saf5.1+, iOS 5+ */
  682 + background-image: -moz-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
  683 + /* FF3.6 */
  684 + background-image: -ms-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
  685 + /* IE10 */
  686 + background-image: -o-linear-gradient(top, #f0f0f0 0%, #dadada 100%);
  687 + /* Opera 11.10+ */
  688 + background-image: linear-gradient(top, #f0f0f0 0%, #dadada 100%);
  689 + filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#f0f0f0', EndColorStr='#dadada');
  690 + box-shadow: inset 1px 1px 3px #666;
  691 +}
  692 +div.dt-button-collection.fixed {
  693 + position: fixed;
  694 + top: 50%;
  695 + left: 50%;
  696 + margin-left: -75px;
  697 + border-radius: 0;
  698 +}
  699 +div.dt-button-collection.fixed.two-column {
  700 + margin-left: -150px;
  701 +}
  702 +div.dt-button-collection.fixed.three-column {
  703 + margin-left: -225px;
  704 +}
  705 +div.dt-button-collection.fixed.four-column {
  706 + margin-left: -300px;
  707 +}
  708 +div.dt-button-collection > * {
  709 + -webkit-column-break-inside: avoid;
  710 + break-inside: avoid;
  711 +}
  712 +div.dt-button-collection.two-column {
  713 + width: 300px;
  714 + padding-bottom: 1px;
  715 + -webkit-column-count: 2;
  716 + -moz-column-count: 2;
  717 + -ms-column-count: 2;
  718 + -o-column-count: 2;
  719 + column-count: 2;
  720 +}
  721 +div.dt-button-collection.three-column {
  722 + width: 450px;
  723 + padding-bottom: 1px;
  724 + -webkit-column-count: 3;
  725 + -moz-column-count: 3;
  726 + -ms-column-count: 3;
  727 + -o-column-count: 3;
  728 + column-count: 3;
  729 +}
  730 +div.dt-button-collection.four-column {
  731 + width: 600px;
  732 + padding-bottom: 1px;
  733 + -webkit-column-count: 4;
  734 + -moz-column-count: 4;
  735 + -ms-column-count: 4;
  736 + -o-column-count: 4;
  737 + column-count: 4;
  738 +}
  739 +
  740 +div.dt-button-background {
  741 + position: fixed;
  742 + top: 0;
  743 + left: 0;
  744 + width: 100%;
  745 + height: 100%;
  746 + background: rgba(0, 0, 0, 0.7);
  747 + /* Fallback */
  748 + background: -ms-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
  749 + /* IE10 Consumer Preview */
  750 + background: -moz-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
  751 + /* Firefox */
  752 + background: -o-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
  753 + /* Opera */
  754 + background: -webkit-gradient(radial, center center, 0, center center, 497, color-stop(0, rgba(0, 0, 0, 0.3)), color-stop(1, rgba(0, 0, 0, 0.7)));
  755 + /* Webkit (Safari/Chrome 10) */
  756 + background: -webkit-radial-gradient(center, ellipse farthest-corner, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
  757 + /* Webkit (Chrome 11+) */
  758 + background: radial-gradient(ellipse farthest-corner at center, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.7) 100%);
  759 + /* W3C Markup, IE10 Release Preview */
  760 + z-index: 2001;
  761 +}
  762 +
  763 +@media screen and (max-width: 640px) {
  764 + div.dt-buttons {
  765 + float: none !important;
  766 + text-align: center;
  767 + }
  768 +}
  769 +
  770 +
  771 +table.DTCR_clonedTable {
  772 + background-color: rgba(255, 255, 255, 0.7);
  773 + z-index: 202;
  774 +}
  775 +
  776 +div.DTCR_pointer {
  777 + width: 1px;
  778 + background-color: #0259C4;
  779 + z-index: 201;
  780 +}
  781 +
  782 +
  783 +table.DTFC_Cloned thead,
  784 +table.DTFC_Cloned tfoot {
  785 + background-color: white;
  786 +}
  787 +
  788 +div.DTFC_Blocker {
  789 + background-color: white;
  790 +}
  791 +
  792 +div.DTFC_LeftWrapper table.dataTable,
  793 +div.DTFC_RightWrapper table.dataTable {
  794 + margin-bottom: 0;
  795 + z-index: 2;
  796 +}
  797 +div.DTFC_LeftWrapper table.dataTable.no-footer,
  798 +div.DTFC_RightWrapper table.dataTable.no-footer {
  799 + border-bottom: none;
  800 +}
  801 +
  802 +
  803 +table.fixedHeader-floating {
  804 + position: fixed !important;
  805 + background-color: white;
  806 +}
  807 +
  808 +table.fixedHeader-floating.no-footer {
  809 + border-bottom-width: 0;
  810 +}
  811 +
  812 +table.fixedHeader-locked {
  813 + position: absolute !important;
  814 + background-color: white;
  815 +}
  816 +
  817 +@media print {
  818 + table.fixedHeader-floating {
  819 + display: none;
  820 + }
  821 +}
  822 +
  823 +
  824 +table.dataTable.dtr-inline.collapsed > tbody > tr > td.child,
  825 +table.dataTable.dtr-inline.collapsed > tbody > tr > th.child,
  826 +table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty {
  827 + cursor: default !important;
  828 +}
  829 +table.dataTable.dtr-inline.collapsed > tbody > tr > td.child:before,
  830 +table.dataTable.dtr-inline.collapsed > tbody > tr > th.child:before,
  831 +table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty:before {
  832 + display: none !important;
  833 +}
  834 +table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
  835 +table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
  836 + position: relative;
  837 + padding-left: 30px;
  838 + cursor: pointer;
  839 +}
  840 +table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:before,
  841 +table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child:before {
  842 + top: 8px;
  843 + left: 4px;
  844 + height: 16px;
  845 + width: 16px;
  846 + display: block;
  847 + position: absolute;
  848 + color: white;
  849 + border: 2px solid white;
  850 + border-radius: 16px;
  851 + box-shadow: 0 0 3px #444;
  852 + box-sizing: content-box;
  853 + font-family: 'Courier New', Courier, monospace;
  854 + text-indent: 4px;
  855 + line-height: 16px;
  856 + content: '+';
  857 + background-color: #31b131;
  858 +}
  859 +table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child:before,
  860 +table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child:before {
  861 + content: '-';
  862 + background-color: #d33333;
  863 +}
  864 +table.dataTable.dtr-inline.collapsed > tbody > tr.child td:before {
  865 + display: none;
  866 +}
  867 +table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child,
  868 +table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child {
  869 + padding-left: 27px;
  870 +}
  871 +table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child:before,
  872 +table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child:before {
  873 + top: 5px;
  874 + left: 4px;
  875 + height: 14px;
  876 + width: 14px;
  877 + border-radius: 14px;
  878 + line-height: 14px;
  879 + text-indent: 3px;
  880 +}
  881 +table.dataTable.dtr-column > tbody > tr > td.control,
  882 +table.dataTable.dtr-column > tbody > tr > th.control {
  883 + position: relative;
  884 + cursor: pointer;
  885 +}
  886 +table.dataTable.dtr-column > tbody > tr > td.control:before,
  887 +table.dataTable.dtr-column > tbody > tr > th.control:before {
  888 + top: 50%;
  889 + left: 50%;
  890 + height: 16px;
  891 + width: 16px;
  892 + margin-top: -10px;
  893 + margin-left: -10px;
  894 + display: block;
  895 + position: absolute;
  896 + color: white;
  897 + border: 2px solid white;
  898 + border-radius: 16px;
  899 + box-shadow: 0 0 3px #444;
  900 + box-sizing: content-box;
  901 + font-family: 'Courier New', Courier, monospace;
  902 + text-indent: 4px;
  903 + line-height: 16px;
  904 + content: '+';
  905 + background-color: #31b131;
  906 +}
  907 +table.dataTable.dtr-column > tbody > tr.parent td.control:before,
  908 +table.dataTable.dtr-column > tbody > tr.parent th.control:before {
  909 + content: '-';
  910 + background-color: #d33333;
  911 +}
  912 +table.dataTable > tbody > tr.child {
  913 + padding: 0.5em 1em;
  914 +}
  915 +table.dataTable > tbody > tr.child:hover {
  916 + background: transparent !important;
  917 +}
  918 +table.dataTable > tbody > tr.child ul {
  919 + display: inline-block;
  920 + list-style-type: none;
  921 + margin: 0;
  922 + padding: 0;
  923 +}
  924 +table.dataTable > tbody > tr.child ul li {
  925 + border-bottom: 1px solid #efefef;
  926 + padding: 0.5em 0;
  927 +}
  928 +table.dataTable > tbody > tr.child ul li:first-child {
  929 + padding-top: 0;
  930 +}
  931 +table.dataTable > tbody > tr.child ul li:last-child {
  932 + border-bottom: none;
  933 +}
  934 +table.dataTable > tbody > tr.child span.dtr-title {
  935 + display: inline-block;
  936 + min-width: 75px;
  937 + font-weight: bold;
  938 +}
  939 +
  940 +div.dtr-modal {
  941 + position: fixed;
  942 + box-sizing: border-box;
  943 + top: 0;
  944 + left: 0;
  945 + height: 100%;
  946 + width: 100%;
  947 + z-index: 100;
  948 + padding: 10em 1em;
  949 +}
  950 +div.dtr-modal div.dtr-modal-display {
  951 + position: absolute;
  952 + top: 0;
  953 + left: 0;
  954 + bottom: 0;
  955 + right: 0;
  956 + width: 50%;
  957 + height: 50%;
  958 + overflow: auto;
  959 + margin: auto;
  960 + z-index: 102;
  961 + overflow: auto;
  962 + background-color: #f5f5f7;
  963 + border: 1px solid black;
  964 + border-radius: 0.5em;
  965 + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
  966 +}
  967 +div.dtr-modal div.dtr-modal-content {
  968 + position: relative;
  969 + padding: 1em;
  970 +}
  971 +div.dtr-modal div.dtr-modal-close {
  972 + position: absolute;
  973 + top: 6px;
  974 + right: 6px;
  975 + width: 22px;
  976 + height: 22px;
  977 + border: 1px solid #eaeaea;
  978 + background-color: #f9f9f9;
  979 + text-align: center;
  980 + border-radius: 3px;
  981 + cursor: pointer;
  982 + z-index: 12;
  983 +}
  984 +div.dtr-modal div.dtr-modal-close:hover {
  985 + background-color: #eaeaea;
  986 +}
  987 +div.dtr-modal div.dtr-modal-background {
  988 + position: fixed;
  989 + top: 0;
  990 + left: 0;
  991 + right: 0;
  992 + bottom: 0;
  993 + z-index: 101;
  994 + background: rgba(0, 0, 0, 0.6);
  995 +}
  996 +
  997 +@media screen and (max-width: 767px) {
  998 + div.dtr-modal div.dtr-modal-display {
  999 + width: 95%;
  1000 + }
  1001 +}
  1002 +
  1003 +
  1004 +table.dt-rowReorder-float {
  1005 + position: absolute !important;
  1006 + opacity: 0.8;
  1007 + table-layout: static;
  1008 + outline: 2px solid #888;
  1009 + outline-offset: -2px;
  1010 + z-index: 2001;
  1011 +}
  1012 +
  1013 +tr.dt-rowReorder-moving {
  1014 + outline: 2px solid #555;
  1015 + outline-offset: -2px;
  1016 +}
  1017 +
  1018 +body.dt-rowReorder-noOverflow {
  1019 + overflow-x: hidden;
  1020 +}
  1021 +
  1022 +table.dataTable td.reorder {
  1023 + text-align: center;
  1024 + cursor: move;
  1025 +}
  1026 +
  1027 +
  1028 +div.DTS tbody th,
  1029 +div.DTS tbody td {
  1030 + white-space: nowrap;
  1031 +}
  1032 +div.DTS tbody tr.even {
  1033 + background-color: white;
  1034 +}
  1035 +div.DTS div.DTS_Loading {
  1036 + z-index: 1;
  1037 +}
  1038 +div.DTS div.dataTables_scrollBody {
  1039 + background: repeating-linear-gradient(45deg, #edeeff, #edeeff 10px, white 10px, white 20px);
  1040 +}
  1041 +div.DTS div.dataTables_scrollBody table {
  1042 + z-index: 2;
  1043 +}
  1044 +div.DTS div.dataTables_paginate {
  1045 + display: none;
  1046 +}
  1047 +
  1048 +
  1049 +table.dataTable tbody > tr.selected,
  1050 +table.dataTable tbody > tr > .selected {
  1051 + background-color: #B0BED9;
  1052 +}
  1053 +table.dataTable.stripe tbody > tr.odd.selected,
  1054 +table.dataTable.stripe tbody > tr.odd > .selected, table.dataTable.display tbody > tr.odd.selected,
  1055 +table.dataTable.display tbody > tr.odd > .selected {
  1056 + background-color: #acbad4;
  1057 +}
  1058 +table.dataTable.hover tbody > tr.selected:hover,
  1059 +table.dataTable.hover tbody > tr > .selected:hover, table.dataTable.display tbody > tr.selected:hover,
  1060 +table.dataTable.display tbody > tr > .selected:hover {
  1061 + background-color: #aab7d1;
  1062 +}
  1063 +table.dataTable.order-column tbody > tr.selected > .sorting_1,
  1064 +table.dataTable.order-column tbody > tr.selected > .sorting_2,
  1065 +table.dataTable.order-column tbody > tr.selected > .sorting_3,
  1066 +table.dataTable.order-column tbody > tr > .selected, table.dataTable.display tbody > tr.selected > .sorting_1,
  1067 +table.dataTable.display tbody > tr.selected > .sorting_2,
  1068 +table.dataTable.display tbody > tr.selected > .sorting_3,
  1069 +table.dataTable.display tbody > tr > .selected {
  1070 + background-color: #acbad5;
  1071 +}
  1072 +table.dataTable.display tbody > tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody > tr.odd.selected > .sorting_1 {
  1073 + background-color: #a6b4cd;
  1074 +}
  1075 +table.dataTable.display tbody > tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody > tr.odd.selected > .sorting_2 {
  1076 + background-color: #a8b5cf;
  1077 +}
  1078 +table.dataTable.display tbody > tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody > tr.odd.selected > .sorting_3 {
  1079 + background-color: #a9b7d1;
  1080 +}
  1081 +table.dataTable.display tbody > tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody > tr.even.selected > .sorting_1 {
  1082 + background-color: #acbad5;
  1083 +}
  1084 +table.dataTable.display tbody > tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody > tr.even.selected > .sorting_2 {
  1085 + background-color: #aebcd6;
  1086 +}
  1087 +table.dataTable.display tbody > tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody > tr.even.selected > .sorting_3 {
  1088 + background-color: #afbdd8;
  1089 +}
  1090 +table.dataTable.display tbody > tr.odd > .selected, table.dataTable.order-column.stripe tbody > tr.odd > .selected {
  1091 + background-color: #a6b4cd;
  1092 +}
  1093 +table.dataTable.display tbody > tr.even > .selected, table.dataTable.order-column.stripe tbody > tr.even > .selected {
  1094 + background-color: #acbad5;
  1095 +}
  1096 +table.dataTable.display tbody > tr.selected:hover > .sorting_1, table.dataTable.order-column.hover tbody > tr.selected:hover > .sorting_1 {
  1097 + background-color: #a2aec7;
  1098 +}
  1099 +table.dataTable.display tbody > tr.selected:hover > .sorting_2, table.dataTable.order-column.hover tbody > tr.selected:hover > .sorting_2 {
  1100 + background-color: #a3b0c9;
  1101 +}
  1102 +table.dataTable.display tbody > tr.selected:hover > .sorting_3, table.dataTable.order-column.hover tbody > tr.selected:hover > .sorting_3 {
  1103 + background-color: #a5b2cb;
  1104 +}
  1105 +table.dataTable.display tbody > tr:hover > .selected,
  1106 +table.dataTable.display tbody > tr > .selected:hover, table.dataTable.order-column.hover tbody > tr:hover > .selected,
  1107 +table.dataTable.order-column.hover tbody > tr > .selected:hover {
  1108 + background-color: #a2aec7;
  1109 +}
  1110 +table.dataTable td.select-checkbox {
  1111 + position: relative;
  1112 +}
  1113 +table.dataTable td.select-checkbox:before, table.dataTable td.select-checkbox:after {
  1114 + display: block;
  1115 + position: absolute;
  1116 + top: 1.2em;
  1117 + left: 50%;
  1118 + width: 12px;
  1119 + height: 12px;
  1120 + box-sizing: border-box;
  1121 +}
  1122 +table.dataTable td.select-checkbox:before {
  1123 + content: ' ';
  1124 + margin-top: -6px;
  1125 + margin-left: -6px;
  1126 + border: 1px solid black;
  1127 + border-radius: 3px;
  1128 +}
  1129 +table.dataTable tr.selected td.select-checkbox:after {
  1130 + content: '\2714';
  1131 + margin-top: -11px;
  1132 + margin-left: -4px;
  1133 + text-align: center;
  1134 + text-shadow: 1px 1px #B0BED9, -1px -1px #B0BED9, 1px -1px #B0BED9, -1px 1px #B0BED9;
  1135 +}
  1136 +
  1137 +div.dataTables_wrapper span.select-info,
  1138 +div.dataTables_wrapper span.select-item {
  1139 + margin-left: 0.5em;
  1140 +}
  1141 +
  1142 +@media screen and (max-width: 640px) {
  1143 + div.dataTables_wrapper span.select-info,
  1144 + div.dataTables_wrapper span.select-item {
  1145 + margin-left: 0;
  1146 + display: block;
  1147 + }
  1148 +}
  1149 +
  1150 +
... ...
src/main/resources/static/metronic_v4.5.4/plugins/bootstrap-datatables/dataTables.bootstrap.js 0 → 100644
  1 +/*! DataTables Bootstrap 3 integration
  2 + * ©2011-2014 SpryMedia Ltd - datatables.net/license
  3 + */
  4 +
  5 +/**
  6 + * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
  7 + * DataTables 1.10 or newer.
  8 + *
  9 + * This file sets the defaults and adds options to DataTables to style its
  10 + * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
  11 + * for further information.
  12 + */
  13 +(function(window, document, undefined){
  14 +
  15 +var factory = function( $, DataTable ) {
  16 +"use strict";
  17 +
  18 +
  19 +/* Set the defaults for DataTables initialisation */
  20 +$.extend( true, DataTable.defaults, {
  21 + dom:
  22 + "<'row'<'col-sm-6'l><'col-sm-6'f>>" +
  23 + "<'row'<'col-sm-12'tr>>" +
  24 + "<'row'<'col-sm-5'i><'col-sm-7'p>>",
  25 + renderer: 'bootstrap'
  26 +} );
  27 +
  28 +
  29 +/* Default class modification */
  30 +$.extend( DataTable.ext.classes, {
  31 + sWrapper: "dataTables_wrapper form-inline dt-bootstrap",
  32 + sFilterInput: "form-control input-sm",
  33 + sLengthSelect: "form-control input-sm"
  34 +} );
  35 +
  36 +
  37 +/* Bootstrap paging button renderer */
  38 +DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
  39 + var api = new DataTable.Api( settings );
  40 + var classes = settings.oClasses;
  41 + var lang = settings.oLanguage.oPaginate;
  42 + var btnDisplay, btnClass, counter=0;
  43 +
  44 + var attach = function( container, buttons ) {
  45 + var i, ien, node, button;
  46 + var clickHandler = function ( e ) {
  47 + e.preventDefault();
  48 + if ( !$(e.currentTarget).hasClass('disabled') ) {
  49 + api.page( e.data.action ).draw( false );
  50 + }
  51 + };
  52 +
  53 + for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
  54 + button = buttons[i];
  55 +
  56 + if ( $.isArray( button ) ) {
  57 + attach( container, button );
  58 + }
  59 + else {
  60 + btnDisplay = '';
  61 + btnClass = '';
  62 +
  63 + switch ( button ) {
  64 + case 'ellipsis':
  65 + btnDisplay = '&hellip;';
  66 + btnClass = 'disabled';
  67 + break;
  68 +
  69 + case 'first':
  70 + btnDisplay = lang.sFirst;
  71 + btnClass = button + (page > 0 ?
  72 + '' : ' disabled');
  73 + break;
  74 +
  75 + case 'previous':
  76 + btnDisplay = lang.sPrevious;
  77 + btnClass = button + (page > 0 ?
  78 + '' : ' disabled');
  79 + break;
  80 +
  81 + case 'next':
  82 + btnDisplay = lang.sNext;
  83 + btnClass = button + (page < pages-1 ?
  84 + '' : ' disabled');
  85 + break;
  86 +
  87 + case 'last':
  88 + btnDisplay = lang.sLast;
  89 + btnClass = button + (page < pages-1 ?
  90 + '' : ' disabled');
  91 + break;
  92 +
  93 + default:
  94 + btnDisplay = button + 1;
  95 + btnClass = page === button ?
  96 + 'active' : '';
  97 + break;
  98 + }
  99 +
  100 + if ( btnDisplay ) {
  101 + node = $('<li>', {
  102 + 'class': classes.sPageButton+' '+btnClass,
  103 + 'id': idx === 0 && typeof button === 'string' ?
  104 + settings.sTableId +'_'+ button :
  105 + null
  106 + } )
  107 + .append( $('<a>', {
  108 + 'href': '#',
  109 + 'aria-controls': settings.sTableId,
  110 + 'data-dt-idx': counter,
  111 + 'tabindex': settings.iTabIndex
  112 + } )
  113 + .html( btnDisplay )
  114 + )
  115 + .appendTo( container );
  116 +
  117 + settings.oApi._fnBindAction(
  118 + node, {action: button}, clickHandler
  119 + );
  120 +
  121 + counter++;
  122 + }
  123 + }
  124 + }
  125 + };
  126 +
  127 + // IE9 throws an 'unknown error' if document.activeElement is used
  128 + // inside an iframe or frame.
  129 + var activeEl;
  130 +
  131 + try {
  132 + // Because this approach is destroying and recreating the paging
  133 + // elements, focus is lost on the select button which is bad for
  134 + // accessibility. So we want to restore focus once the draw has
  135 + // completed
  136 + activeEl = $(document.activeElement).data('dt-idx');
  137 + }
  138 + catch (e) {}
  139 +
  140 + attach(
  141 + $(host).empty().html('<ul class="pagination"/>').children('ul'),
  142 + buttons
  143 + );
  144 +
  145 + if ( activeEl ) {
  146 + $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
  147 + }
  148 +};
  149 +
  150 +
  151 +/*
  152 + * TableTools Bootstrap compatibility
  153 + * Required TableTools 2.1+
  154 + */
  155 +if ( DataTable.TableTools ) {
  156 + // Set the classes that TableTools uses to something suitable for Bootstrap
  157 + $.extend( true, DataTable.TableTools.classes, {
  158 + "container": "DTTT btn-group",
  159 + "buttons": {
  160 + "normal": "btn btn-default",
  161 + "disabled": "disabled"
  162 + },
  163 + "collection": {
  164 + "container": "DTTT_dropdown dropdown-menu",
  165 + "buttons": {
  166 + "normal": "",
  167 + "disabled": "disabled"
  168 + }
  169 + },
  170 + "print": {
  171 + "info": "DTTT_print_info"
  172 + },
  173 + "select": {
  174 + "row": "active"
  175 + }
  176 + } );
  177 +
  178 + // Have the collection use a bootstrap compatible drop down
  179 + $.extend( true, DataTable.TableTools.DEFAULTS.oTags, {
  180 + "collection": {
  181 + "container": "ul",
  182 + "button": "li",
  183 + "liner": "a"
  184 + }
  185 + } );
  186 +}
  187 +
  188 +}; // /factory
  189 +
  190 +
  191 +// Define as an AMD module if possible
  192 +if ( typeof define === 'function' && define.amd ) {
  193 + define( ['jquery', 'datatables'], factory );
  194 +}
  195 +else if ( typeof exports === 'object' ) {
  196 + // Node/CommonJS
  197 + factory( require('jquery'), require('datatables') );
  198 +}
  199 +else if ( jQuery ) {
  200 + // Otherwise simply initialise as normal, stopping multiple evaluation
  201 + factory( jQuery, jQuery.fn.dataTable );
  202 +}
  203 +
  204 +
  205 +})(window, document);
  206 +
... ...
src/main/resources/static/metronic_v4.5.4/plugins/bootstrap-datatables/datatables.js 0 → 100644
  1 +/*! DataTables 1.10.7
  2 + * ©2008-2014 SpryMedia Ltd - datatables.net/license
  3 + */
  4 +
  5 +/**
  6 + * @summary DataTables
  7 + * @description Paginate, search and order HTML tables
  8 + * @version 1.10.7
  9 + * @file jquery.dataTables.js
  10 + * @author SpryMedia Ltd (www.sprymedia.co.uk)
  11 + * @contact www.sprymedia.co.uk/contact
  12 + * @copyright Copyright 2008-2014 SpryMedia Ltd.
  13 + *
  14 + * This source file is free software, available under the following license:
  15 + * MIT license - http://datatables.net/license
  16 + *
  17 + * This source file is distributed in the hope that it will be useful, but
  18 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  19 + * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
  20 + *
  21 + * For details please refer to: http://www.datatables.net
  22 + */
  23 +
  24 +/*jslint evil: true, undef: true, browser: true */
  25 +/*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,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
  26 +
  27 +(/** @lends <global> */function( window, document, undefined ) {
  28 +
  29 +(function( factory ) {
  30 + "use strict";
  31 +
  32 + if ( typeof define === 'function' && define.amd ) {
  33 + // Define as an AMD module if possible
  34 + define( 'datatables', ['jquery'], factory );
  35 + }
  36 + else if ( typeof exports === 'object' ) {
  37 + // Node/CommonJS
  38 + module.exports = factory( require( 'jquery' ) );
  39 + }
  40 + else if ( jQuery && !jQuery.fn.dataTable ) {
  41 + // Define using browser globals otherwise
  42 + // Prevent multiple instantiations if the script is loaded twice
  43 + factory( jQuery );
  44 + }
  45 +}
  46 +(/** @lends <global> */function( $ ) {
  47 + "use strict";
  48 +
  49 + /**
  50 + * DataTables is a plug-in for the jQuery Javascript library. It is a highly
  51 + * flexible tool, based upon the foundations of progressive enhancement,
  52 + * which will add advanced interaction controls to any HTML table. For a
  53 + * full list of features please refer to
  54 + * [DataTables.net](href="http://datatables.net).
  55 + *
  56 + * Note that the `DataTable` object is not a global variable but is aliased
  57 + * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
  58 + * be accessed.
  59 + *
  60 + * @class
  61 + * @param {object} [init={}] Configuration object for DataTables. Options
  62 + * are defined by {@link DataTable.defaults}
  63 + * @requires jQuery 1.7+
  64 + *
  65 + * @example
  66 + * // Basic initialisation
  67 + * $(document).ready( function {
  68 + * $('#example').dataTable();
  69 + * } );
  70 + *
  71 + * @example
  72 + * // Initialisation with configuration options - in this case, disable
  73 + * // pagination and sorting.
  74 + * $(document).ready( function {
  75 + * $('#example').dataTable( {
  76 + * "paginate": false,
  77 + * "sort": false
  78 + * } );
  79 + * } );
  80 + */
  81 + var DataTable;
  82 +
  83 +
  84 + /*
  85 + * It is useful to have variables which are scoped locally so only the
  86 + * DataTables functions can access them and they don't leak into global space.
  87 + * At the same time these functions are often useful over multiple files in the
  88 + * core and API, so we list, or at least document, all variables which are used
  89 + * by DataTables as private variables here. This also ensures that there is no
  90 + * clashing of variable names and that they can easily referenced for reuse.
  91 + */
  92 +
  93 +
  94 + // Defined else where
  95 + // _selector_run
  96 + // _selector_opts
  97 + // _selector_first
  98 + // _selector_row_indexes
  99 +
  100 + var _ext; // DataTable.ext
  101 + var _Api; // DataTable.Api
  102 + var _api_register; // DataTable.Api.register
  103 + var _api_registerPlural; // DataTable.Api.registerPlural
  104 +
  105 + var _re_dic = {};
  106 + var _re_new_lines = /[\r\n]/g;
  107 + var _re_html = /<.*?>/g;
  108 + var _re_date_start = /^[\w\+\-]/;
  109 + var _re_date_end = /[\w\+\-]$/;
  110 +
  111 + // Escape regular expression special characters
  112 + var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
  113 +
  114 + // http://en.wikipedia.org/wiki/Foreign_exchange_market
  115 + // - \u20BD - Russian ruble.
  116 + // - \u20a9 - South Korean Won
  117 + // - \u20BA - Turkish Lira
  118 + // - \u20B9 - Indian Rupee
  119 + // - R - Brazil (R$) and South Africa
  120 + // - fr - Swiss Franc
  121 + // - kr - Swedish krona, Norwegian krone and Danish krone
  122 + // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
  123 + // standards as thousands separators.
  124 + var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
  125 +
  126 +
  127 + var _empty = function ( d ) {
  128 + return !d || d === true || d === '-' ? true : false;
  129 + };
  130 +
  131 +
  132 + var _intVal = function ( s ) {
  133 + var integer = parseInt( s, 10 );
  134 + return !isNaN(integer) && isFinite(s) ? integer : null;
  135 + };
  136 +
  137 + // Convert from a formatted number with characters other than `.` as the
  138 + // decimal place, to a Javascript number
  139 + var _numToDecimal = function ( num, decimalPoint ) {
  140 + // Cache created regular expressions for speed as this function is called often
  141 + if ( ! _re_dic[ decimalPoint ] ) {
  142 + _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
  143 + }
  144 + return typeof num === 'string' && decimalPoint !== '.' ?
  145 + num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
  146 + num;
  147 + };
  148 +
  149 +
  150 + var _isNumber = function ( d, decimalPoint, formatted ) {
  151 + var strType = typeof d === 'string';
  152 +
  153 + // If empty return immediately so there must be a number if it is a
  154 + // formatted string (this stops the string "k", or "kr", etc being detected
  155 + // as a formatted number for currency
  156 + if ( _empty( d ) ) {
  157 + return true;
  158 + }
  159 +
  160 + if ( decimalPoint && strType ) {
  161 + d = _numToDecimal( d, decimalPoint );
  162 + }
  163 +
  164 + if ( formatted && strType ) {
  165 + d = d.replace( _re_formatted_numeric, '' );
  166 + }
  167 +
  168 + return !isNaN( parseFloat(d) ) && isFinite( d );
  169 + };
  170 +
  171 +
  172 + // A string without HTML in it can be considered to be HTML still
  173 + var _isHtml = function ( d ) {
  174 + return _empty( d ) || typeof d === 'string';
  175 + };
  176 +
  177 +
  178 + var _htmlNumeric = function ( d, decimalPoint, formatted ) {
  179 + if ( _empty( d ) ) {
  180 + return true;
  181 + }
  182 +
  183 + var html = _isHtml( d );
  184 + return ! html ?
  185 + null :
  186 + _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
  187 + true :
  188 + null;
  189 + };
  190 +
  191 +
  192 + var _pluck = function ( a, prop, prop2 ) {
  193 + var out = [];
  194 + var i=0, ien=a.length;
  195 +
  196 + // Could have the test in the loop for slightly smaller code, but speed
  197 + // is essential here
  198 + if ( prop2 !== undefined ) {
  199 + for ( ; i<ien ; i++ ) {
  200 + if ( a[i] && a[i][ prop ] ) {
  201 + out.push( a[i][ prop ][ prop2 ] );
  202 + }
  203 + }
  204 + }
  205 + else {
  206 + for ( ; i<ien ; i++ ) {
  207 + if ( a[i] ) {
  208 + out.push( a[i][ prop ] );
  209 + }
  210 + }
  211 + }
  212 +
  213 + return out;
  214 + };
  215 +
  216 +
  217 + // Basically the same as _pluck, but rather than looping over `a` we use `order`
  218 + // as the indexes to pick from `a`
  219 + var _pluck_order = function ( a, order, prop, prop2 )
  220 + {
  221 + var out = [];
  222 + var i=0, ien=order.length;
  223 +
  224 + // Could have the test in the loop for slightly smaller code, but speed
  225 + // is essential here
  226 + if ( prop2 !== undefined ) {
  227 + for ( ; i<ien ; i++ ) {
  228 + if ( a[ order[i] ][ prop ] ) {
  229 + out.push( a[ order[i] ][ prop ][ prop2 ] );
  230 + }
  231 + }
  232 + }
  233 + else {
  234 + for ( ; i<ien ; i++ ) {
  235 + out.push( a[ order[i] ][ prop ] );
  236 + }
  237 + }
  238 +
  239 + return out;
  240 + };
  241 +
  242 +
  243 + var _range = function ( len, start )
  244 + {
  245 + var out = [];
  246 + var end;
  247 +
  248 + if ( start === undefined ) {
  249 + start = 0;
  250 + end = len;
  251 + }
  252 + else {
  253 + end = start;
  254 + start = len;
  255 + }
  256 +
  257 + for ( var i=start ; i<end ; i++ ) {
  258 + out.push( i );
  259 + }
  260 +
  261 + return out;
  262 + };
  263 +
  264 +
  265 + var _removeEmpty = function ( a )
  266 + {
  267 + var out = [];
  268 +
  269 + for ( var i=0, ien=a.length ; i<ien ; i++ ) {
  270 + if ( a[i] ) { // careful - will remove all falsy values!
  271 + out.push( a[i] );
  272 + }
  273 + }
  274 +
  275 + return out;
  276 + };
  277 +
  278 +
  279 + var _stripHtml = function ( d ) {
  280 + return d.replace( _re_html, '' );
  281 + };
  282 +
  283 +
  284 + /**
  285 + * Find the unique elements in a source array.
  286 + *
  287 + * @param {array} src Source array
  288 + * @return {array} Array of unique items
  289 + * @ignore
  290 + */
  291 + var _unique = function ( src )
  292 + {
  293 + // A faster unique method is to use object keys to identify used values,
  294 + // but this doesn't work with arrays or objects, which we must also
  295 + // consider. See jsperf.com/compare-array-unique-versions/4 for more
  296 + // information.
  297 + var
  298 + out = [],
  299 + val,
  300 + i, ien=src.length,
  301 + j, k=0;
  302 +
  303 + again: for ( i=0 ; i<ien ; i++ ) {
  304 + val = src[i];
  305 +
  306 + for ( j=0 ; j<k ; j++ ) {
  307 + if ( out[j] === val ) {
  308 + continue again;
  309 + }
  310 + }
  311 +
  312 + out.push( val );
  313 + k++;
  314 + }
  315 +
  316 + return out;
  317 + };
  318 +
  319 +
  320 +
  321 + /**
  322 + * Create a mapping object that allows camel case parameters to be looked up
  323 + * for their Hungarian counterparts. The mapping is stored in a private
  324 + * parameter called `_hungarianMap` which can be accessed on the source object.
  325 + * @param {object} o
  326 + * @memberof DataTable#oApi
  327 + */
  328 + function _fnHungarianMap ( o )
  329 + {
  330 + var
  331 + hungarian = 'a aa ai ao as b fn i m o s ',
  332 + match,
  333 + newKey,
  334 + map = {};
  335 +
  336 + $.each( o, function (key, val) {
  337 + match = key.match(/^([^A-Z]+?)([A-Z])/);
  338 +
  339 + if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
  340 + {
  341 + newKey = key.replace( match[0], match[2].toLowerCase() );
  342 + map[ newKey ] = key;
  343 +
  344 + if ( match[1] === 'o' )
  345 + {
  346 + _fnHungarianMap( o[key] );
  347 + }
  348 + }
  349 + } );
  350 +
  351 + o._hungarianMap = map;
  352 + }
  353 +
  354 +
  355 + /**
  356 + * Convert from camel case parameters to Hungarian, based on a Hungarian map
  357 + * created by _fnHungarianMap.
  358 + * @param {object} src The model object which holds all parameters that can be
  359 + * mapped.
  360 + * @param {object} user The object to convert from camel case to Hungarian.
  361 + * @param {boolean} force When set to `true`, properties which already have a
  362 + * Hungarian value in the `user` object will be overwritten. Otherwise they
  363 + * won't be.
  364 + * @memberof DataTable#oApi
  365 + */
  366 + function _fnCamelToHungarian ( src, user, force )
  367 + {
  368 + if ( ! src._hungarianMap ) {
  369 + _fnHungarianMap( src );
  370 + }
  371 +
  372 + var hungarianKey;
  373 +
  374 + $.each( user, function (key, val) {
  375 + hungarianKey = src._hungarianMap[ key ];
  376 +
  377 + if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
  378 + {
  379 + // For objects, we need to buzz down into the object to copy parameters
  380 + if ( hungarianKey.charAt(0) === 'o' )
  381 + {
  382 + // Copy the camelCase options over to the hungarian
  383 + if ( ! user[ hungarianKey ] ) {
  384 + user[ hungarianKey ] = {};
  385 + }
  386 + $.extend( true, user[hungarianKey], user[key] );
  387 +
  388 + _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
  389 + }
  390 + else {
  391 + user[hungarianKey] = user[ key ];
  392 + }
  393 + }
  394 + } );
  395 + }
  396 +
  397 +
  398 + /**
  399 + * Language compatibility - when certain options are given, and others aren't, we
  400 + * need to duplicate the values over, in order to provide backwards compatibility
  401 + * with older language files.
  402 + * @param {object} oSettings dataTables settings object
  403 + * @memberof DataTable#oApi
  404 + */
  405 + function _fnLanguageCompat( lang )
  406 + {
  407 + var defaults = DataTable.defaults.oLanguage;
  408 + var zeroRecords = lang.sZeroRecords;
  409 +
  410 + /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
  411 + * sZeroRecords - assuming that is given.
  412 + */
  413 + if ( ! lang.sEmptyTable && zeroRecords &&
  414 + defaults.sEmptyTable === "No data available in table" )
  415 + {
  416 + _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
  417 + }
  418 +
  419 + /* Likewise with loading records */
  420 + if ( ! lang.sLoadingRecords && zeroRecords &&
  421 + defaults.sLoadingRecords === "Loading..." )
  422 + {
  423 + _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
  424 + }
  425 +
  426 + // Old parameter name of the thousands separator mapped onto the new
  427 + if ( lang.sInfoThousands ) {
  428 + lang.sThousands = lang.sInfoThousands;
  429 + }
  430 +
  431 + var decimal = lang.sDecimal;
  432 + if ( decimal ) {
  433 + _addNumericSort( decimal );
  434 + }
  435 + }
  436 +
  437 +
  438 + /**
  439 + * Map one parameter onto another
  440 + * @param {object} o Object to map
  441 + * @param {*} knew The new parameter name
  442 + * @param {*} old The old parameter name
  443 + */
  444 + var _fnCompatMap = function ( o, knew, old ) {
  445 + if ( o[ knew ] !== undefined ) {
  446 + o[ old ] = o[ knew ];
  447 + }
  448 + };
  449 +
  450 +
  451 + /**
  452 + * Provide backwards compatibility for the main DT options. Note that the new
  453 + * options are mapped onto the old parameters, so this is an external interface
  454 + * change only.
  455 + * @param {object} init Object to map
  456 + */
  457 + function _fnCompatOpts ( init )
  458 + {
  459 + _fnCompatMap( init, 'ordering', 'bSort' );
  460 + _fnCompatMap( init, 'orderMulti', 'bSortMulti' );
  461 + _fnCompatMap( init, 'orderClasses', 'bSortClasses' );
  462 + _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
  463 + _fnCompatMap( init, 'order', 'aaSorting' );
  464 + _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );
  465 + _fnCompatMap( init, 'paging', 'bPaginate' );
  466 + _fnCompatMap( init, 'pagingType', 'sPaginationType' );
  467 + _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
  468 + _fnCompatMap( init, 'searching', 'bFilter' );
  469 +
  470 + // Column search objects are in an array, so it needs to be converted
  471 + // element by element
  472 + var searchCols = init.aoSearchCols;
  473 +
  474 + if ( searchCols ) {
  475 + for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
  476 + if ( searchCols[i] ) {
  477 + _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
  478 + }
  479 + }
  480 + }
  481 + }
  482 +
  483 +
  484 + /**
  485 + * Provide backwards compatibility for column options. Note that the new options
  486 + * are mapped onto the old parameters, so this is an external interface change
  487 + * only.
  488 + * @param {object} init Object to map
  489 + */
  490 + function _fnCompatCols ( init )
  491 + {
  492 + _fnCompatMap( init, 'orderable', 'bSortable' );
  493 + _fnCompatMap( init, 'orderData', 'aDataSort' );
  494 + _fnCompatMap( init, 'orderSequence', 'asSorting' );
  495 + _fnCompatMap( init, 'orderDataType', 'sortDataType' );
  496 +
  497 + // orderData can be given as an integer
  498 + var dataSort = init.aDataSort;
  499 + if ( dataSort && ! $.isArray( dataSort ) ) {
  500 + init.aDataSort = [ dataSort ];
  501 + }
  502 + }
  503 +
  504 +
  505 + /**
  506 + * Browser feature detection for capabilities, quirks
  507 + * @param {object} settings dataTables settings object
  508 + * @memberof DataTable#oApi
  509 + */
  510 + function _fnBrowserDetect( settings )
  511 + {
  512 + var browser = settings.oBrowser;
  513 +
  514 + // Scrolling feature / quirks detection
  515 + var n = $('<div/>')
  516 + .css( {
  517 + position: 'absolute',
  518 + top: 0,
  519 + left: 0,
  520 + height: 1,
  521 + width: 1,
  522 + overflow: 'hidden'
  523 + } )
  524 + .append(
  525 + $('<div/>')
  526 + .css( {
  527 + position: 'absolute',
  528 + top: 1,
  529 + left: 1,
  530 + width: 100,
  531 + overflow: 'scroll'
  532 + } )
  533 + .append(
  534 + $('<div class="test"/>')
  535 + .css( {
  536 + width: '100%',
  537 + height: 10
  538 + } )
  539 + )
  540 + )
  541 + .appendTo( 'body' );
  542 +
  543 + var test = n.find('.test');
  544 +
  545 + // IE6/7 will oversize a width 100% element inside a scrolling element, to
  546 + // include the width of the scrollbar, while other browsers ensure the inner
  547 + // element is contained without forcing scrolling
  548 + browser.bScrollOversize = test[0].offsetWidth === 100;
  549 +
  550 + // In rtl text layout, some browsers (most, but not all) will place the
  551 + // scrollbar on the left, rather than the right.
  552 + browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1;
  553 +
  554 + n.remove();
  555 + }
  556 +
  557 +
  558 + /**
  559 + * Array.prototype reduce[Right] method, used for browsers which don't support
  560 + * JS 1.6. Done this way to reduce code size, since we iterate either way
  561 + * @param {object} settings dataTables settings object
  562 + * @memberof DataTable#oApi
  563 + */
  564 + function _fnReduce ( that, fn, init, start, end, inc )
  565 + {
  566 + var
  567 + i = start,
  568 + value,
  569 + isSet = false;
  570 +
  571 + if ( init !== undefined ) {
  572 + value = init;
  573 + isSet = true;
  574 + }
  575 +
  576 + while ( i !== end ) {
  577 + if ( ! that.hasOwnProperty(i) ) {
  578 + continue;
  579 + }
  580 +
  581 + value = isSet ?
  582 + fn( value, that[i], i, that ) :
  583 + that[i];
  584 +
  585 + isSet = true;
  586 + i += inc;
  587 + }
  588 +
  589 + return value;
  590 + }
  591 +
  592 + /**
  593 + * Add a column to the list used for the table with default values
  594 + * @param {object} oSettings dataTables settings object
  595 + * @param {node} nTh The th element for this column
  596 + * @memberof DataTable#oApi
  597 + */
  598 + function _fnAddColumn( oSettings, nTh )
  599 + {
  600 + // Add column to aoColumns array
  601 + var oDefaults = DataTable.defaults.column;
  602 + var iCol = oSettings.aoColumns.length;
  603 + var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
  604 + "nTh": nTh ? nTh : document.createElement('th'),
  605 + "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
  606 + "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
  607 + "mData": oDefaults.mData ? oDefaults.mData : iCol,
  608 + idx: iCol
  609 + } );
  610 + oSettings.aoColumns.push( oCol );
  611 +
  612 + // Add search object for column specific search. Note that the `searchCols[ iCol ]`
  613 + // passed into extend can be undefined. This allows the user to give a default
  614 + // with only some of the parameters defined, and also not give a default
  615 + var searchCols = oSettings.aoPreSearchCols;
  616 + searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
  617 +
  618 + // Use the default column options function to initialise classes etc
  619 + _fnColumnOptions( oSettings, iCol, $(nTh).data() );
  620 + }
  621 +
  622 +
  623 + /**
  624 + * Apply options for a column
  625 + * @param {object} oSettings dataTables settings object
  626 + * @param {int} iCol column index to consider
  627 + * @param {object} oOptions object with sType, bVisible and bSearchable etc
  628 + * @memberof DataTable#oApi
  629 + */
  630 + function _fnColumnOptions( oSettings, iCol, oOptions )
  631 + {
  632 + var oCol = oSettings.aoColumns[ iCol ];
  633 + var oClasses = oSettings.oClasses;
  634 + var th = $(oCol.nTh);
  635 +
  636 + // Try to get width information from the DOM. We can't get it from CSS
  637 + // as we'd need to parse the CSS stylesheet. `width` option can override
  638 + if ( ! oCol.sWidthOrig ) {
  639 + // Width attribute
  640 + oCol.sWidthOrig = th.attr('width') || null;
  641 +
  642 + // Style attribute
  643 + var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
  644 + if ( t ) {
  645 + oCol.sWidthOrig = t[1];
  646 + }
  647 + }
  648 +
  649 + /* User specified column options */
  650 + if ( oOptions !== undefined && oOptions !== null )
  651 + {
  652 + // Backwards compatibility
  653 + _fnCompatCols( oOptions );
  654 +
  655 + // Map camel case parameters to their Hungarian counterparts
  656 + _fnCamelToHungarian( DataTable.defaults.column, oOptions );
  657 +
  658 + /* Backwards compatibility for mDataProp */
  659 + if ( oOptions.mDataProp !== undefined && !oOptions.mData )
  660 + {
  661 + oOptions.mData = oOptions.mDataProp;
  662 + }
  663 +
  664 + if ( oOptions.sType )
  665 + {
  666 + oCol._sManualType = oOptions.sType;
  667 + }
  668 +
  669 + // `class` is a reserved word in Javascript, so we need to provide
  670 + // the ability to use a valid name for the camel case input
  671 + if ( oOptions.className && ! oOptions.sClass )
  672 + {
  673 + oOptions.sClass = oOptions.className;
  674 + }
  675 +
  676 + $.extend( oCol, oOptions );
  677 + _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
  678 +
  679 + /* iDataSort to be applied (backwards compatibility), but aDataSort will take
  680 + * priority if defined
  681 + */
  682 + if ( oOptions.iDataSort !== undefined )
  683 + {
  684 + oCol.aDataSort = [ oOptions.iDataSort ];
  685 + }
  686 + _fnMap( oCol, oOptions, "aDataSort" );
  687 + }
  688 +
  689 + /* Cache the data get and set functions for speed */
  690 + var mDataSrc = oCol.mData;
  691 + var mData = _fnGetObjectDataFn( mDataSrc );
  692 + var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
  693 +
  694 + var attrTest = function( src ) {
  695 + return typeof src === 'string' && src.indexOf('@') !== -1;
  696 + };
  697 + oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
  698 + attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
  699 + );
  700 +
  701 + oCol.fnGetData = function (rowData, type, meta) {
  702 + var innerData = mData( rowData, type, undefined, meta );
  703 +
  704 + return mRender && type ?
  705 + mRender( innerData, type, rowData, meta ) :
  706 + innerData;
  707 + };
  708 + oCol.fnSetData = function ( rowData, val, meta ) {
  709 + return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
  710 + };
  711 +
  712 + // Indicate if DataTables should read DOM data as an object or array
  713 + // Used in _fnGetRowElements
  714 + if ( typeof mDataSrc !== 'number' ) {
  715 + oSettings._rowReadObject = true;
  716 + }
  717 +
  718 + /* Feature sorting overrides column specific when off */
  719 + if ( !oSettings.oFeatures.bSort )
  720 + {
  721 + oCol.bSortable = false;
  722 + th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
  723 + }
  724 +
  725 + /* Check that the class assignment is correct for sorting */
  726 + var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
  727 + var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
  728 + if ( !oCol.bSortable || (!bAsc && !bDesc) )
  729 + {
  730 + oCol.sSortingClass = oClasses.sSortableNone;
  731 + oCol.sSortingClassJUI = "";
  732 + }
  733 + else if ( bAsc && !bDesc )
  734 + {
  735 + oCol.sSortingClass = oClasses.sSortableAsc;
  736 + oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
  737 + }
  738 + else if ( !bAsc && bDesc )
  739 + {
  740 + oCol.sSortingClass = oClasses.sSortableDesc;
  741 + oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
  742 + }
  743 + else
  744 + {
  745 + oCol.sSortingClass = oClasses.sSortable;
  746 + oCol.sSortingClassJUI = oClasses.sSortJUI;
  747 + }
  748 + }
  749 +
  750 +
  751 + /**
  752 + * Adjust the table column widths for new data. Note: you would probably want to
  753 + * do a redraw after calling this function!
  754 + * @param {object} settings dataTables settings object
  755 + * @memberof DataTable#oApi
  756 + */
  757 + function _fnAdjustColumnSizing ( settings )
  758 + {
  759 + /* Not interested in doing column width calculation if auto-width is disabled */
  760 + if ( settings.oFeatures.bAutoWidth !== false )
  761 + {
  762 + var columns = settings.aoColumns;
  763 +
  764 + _fnCalculateColumnWidths( settings );
  765 + for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
  766 + {
  767 + columns[i].nTh.style.width = columns[i].sWidth;
  768 + }
  769 + }
  770 +
  771 + var scroll = settings.oScroll;
  772 + if ( scroll.sY !== '' || scroll.sX !== '')
  773 + {
  774 + _fnScrollDraw( settings );
  775 + }
  776 +
  777 + _fnCallbackFire( settings, null, 'column-sizing', [settings] );
  778 + }
  779 +
  780 +
  781 + /**
  782 + * Covert the index of a visible column to the index in the data array (take account
  783 + * of hidden columns)
  784 + * @param {object} oSettings dataTables settings object
  785 + * @param {int} iMatch Visible column index to lookup
  786 + * @returns {int} i the data index
  787 + * @memberof DataTable#oApi
  788 + */
  789 + function _fnVisibleToColumnIndex( oSettings, iMatch )
  790 + {
  791 + var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  792 +
  793 + return typeof aiVis[iMatch] === 'number' ?
  794 + aiVis[iMatch] :
  795 + null;
  796 + }
  797 +
  798 +
  799 + /**
  800 + * Covert the index of an index in the data array and convert it to the visible
  801 + * column index (take account of hidden columns)
  802 + * @param {int} iMatch Column index to lookup
  803 + * @param {object} oSettings dataTables settings object
  804 + * @returns {int} i the data index
  805 + * @memberof DataTable#oApi
  806 + */
  807 + function _fnColumnIndexToVisible( oSettings, iMatch )
  808 + {
  809 + var aiVis = _fnGetColumns( oSettings, 'bVisible' );
  810 + var iPos = $.inArray( iMatch, aiVis );
  811 +
  812 + return iPos !== -1 ? iPos : null;
  813 + }
  814 +
  815 +
  816 + /**
  817 + * Get the number of visible columns
  818 + * @param {object} oSettings dataTables settings object
  819 + * @returns {int} i the number of visible columns
  820 + * @memberof DataTable#oApi
  821 + */
  822 + function _fnVisbleColumns( oSettings )
  823 + {
  824 + return _fnGetColumns( oSettings, 'bVisible' ).length;
  825 + }
  826 +
  827 +
  828 + /**
  829 + * Get an array of column indexes that match a given property
  830 + * @param {object} oSettings dataTables settings object
  831 + * @param {string} sParam Parameter in aoColumns to look for - typically
  832 + * bVisible or bSearchable
  833 + * @returns {array} Array of indexes with matched properties
  834 + * @memberof DataTable#oApi
  835 + */
  836 + function _fnGetColumns( oSettings, sParam )
  837 + {
  838 + var a = [];
  839 +
  840 + $.map( oSettings.aoColumns, function(val, i) {
  841 + if ( val[sParam] ) {
  842 + a.push( i );
  843 + }
  844 + } );
  845 +
  846 + return a;
  847 + }
  848 +
  849 +
  850 + /**
  851 + * Calculate the 'type' of a column
  852 + * @param {object} settings dataTables settings object
  853 + * @memberof DataTable#oApi
  854 + */
  855 + function _fnColumnTypes ( settings )
  856 + {
  857 + var columns = settings.aoColumns;
  858 + var data = settings.aoData;
  859 + var types = DataTable.ext.type.detect;
  860 + var i, ien, j, jen, k, ken;
  861 + var col, cell, detectedType, cache;
  862 +
  863 + // For each column, spin over the
  864 + for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  865 + col = columns[i];
  866 + cache = [];
  867 +
  868 + if ( ! col.sType && col._sManualType ) {
  869 + col.sType = col._sManualType;
  870 + }
  871 + else if ( ! col.sType ) {
  872 + for ( j=0, jen=types.length ; j<jen ; j++ ) {
  873 + for ( k=0, ken=data.length ; k<ken ; k++ ) {
  874 + // Use a cache array so we only need to get the type data
  875 + // from the formatter once (when using multiple detectors)
  876 + if ( cache[k] === undefined ) {
  877 + cache[k] = _fnGetCellData( settings, k, i, 'type' );
  878 + }
  879 +
  880 + detectedType = types[j]( cache[k], settings );
  881 +
  882 + // If null, then this type can't apply to this column, so
  883 + // rather than testing all cells, break out. There is an
  884 + // exception for the last type which is `html`. We need to
  885 + // scan all rows since it is possible to mix string and HTML
  886 + // types
  887 + if ( ! detectedType && j !== types.length-1 ) {
  888 + break;
  889 + }
  890 +
  891 + // Only a single match is needed for html type since it is
  892 + // bottom of the pile and very similar to string
  893 + if ( detectedType === 'html' ) {
  894 + break;
  895 + }
  896 + }
  897 +
  898 + // Type is valid for all data points in the column - use this
  899 + // type
  900 + if ( detectedType ) {
  901 + col.sType = detectedType;
  902 + break;
  903 + }
  904 + }
  905 +
  906 + // Fall back - if no type was detected, always use string
  907 + if ( ! col.sType ) {
  908 + col.sType = 'string';
  909 + }
  910 + }
  911 + }
  912 + }
  913 +
  914 +
  915 + /**
  916 + * Take the column definitions and static columns arrays and calculate how
  917 + * they relate to column indexes. The callback function will then apply the
  918 + * definition found for a column to a suitable configuration object.
  919 + * @param {object} oSettings dataTables settings object
  920 + * @param {array} aoColDefs The aoColumnDefs array that is to be applied
  921 + * @param {array} aoCols The aoColumns array that defines columns individually
  922 + * @param {function} fn Callback function - takes two parameters, the calculated
  923 + * column index and the definition for that column.
  924 + * @memberof DataTable#oApi
  925 + */
  926 + function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
  927 + {
  928 + var i, iLen, j, jLen, k, kLen, def;
  929 + var columns = oSettings.aoColumns;
  930 +
  931 + // Column definitions with aTargets
  932 + if ( aoColDefs )
  933 + {
  934 + /* Loop over the definitions array - loop in reverse so first instance has priority */
  935 + for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
  936 + {
  937 + def = aoColDefs[i];
  938 +
  939 + /* Each definition can target multiple columns, as it is an array */
  940 + var aTargets = def.targets !== undefined ?
  941 + def.targets :
  942 + def.aTargets;
  943 +
  944 + if ( ! $.isArray( aTargets ) )
  945 + {
  946 + aTargets = [ aTargets ];
  947 + }
  948 +
  949 + for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
  950 + {
  951 + if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
  952 + {
  953 + /* Add columns that we don't yet know about */
  954 + while( columns.length <= aTargets[j] )
  955 + {
  956 + _fnAddColumn( oSettings );
  957 + }
  958 +
  959 + /* Integer, basic index */
  960 + fn( aTargets[j], def );
  961 + }
  962 + else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
  963 + {
  964 + /* Negative integer, right to left column counting */
  965 + fn( columns.length+aTargets[j], def );
  966 + }
  967 + else if ( typeof aTargets[j] === 'string' )
  968 + {
  969 + /* Class name matching on TH element */
  970 + for ( k=0, kLen=columns.length ; k<kLen ; k++ )
  971 + {
  972 + if ( aTargets[j] == "_all" ||
  973 + $(columns[k].nTh).hasClass( aTargets[j] ) )
  974 + {
  975 + fn( k, def );
  976 + }
  977 + }
  978 + }
  979 + }
  980 + }
  981 + }
  982 +
  983 + // Statically defined columns array
  984 + if ( aoCols )
  985 + {
  986 + for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
  987 + {
  988 + fn( i, aoCols[i] );
  989 + }
  990 + }
  991 + }
  992 +
  993 + /**
  994 + * Add a data array to the table, creating DOM node etc. This is the parallel to
  995 + * _fnGatherData, but for adding rows from a Javascript source, rather than a
  996 + * DOM source.
  997 + * @param {object} oSettings dataTables settings object
  998 + * @param {array} aData data array to be added
  999 + * @param {node} [nTr] TR element to add to the table - optional. If not given,
  1000 + * DataTables will create a row automatically
  1001 + * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  1002 + * if nTr is.
  1003 + * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
  1004 + * @memberof DataTable#oApi
  1005 + */
  1006 + function _fnAddData ( oSettings, aDataIn, nTr, anTds )
  1007 + {
  1008 + /* Create the object for storing information about this new row */
  1009 + var iRow = oSettings.aoData.length;
  1010 + var oData = $.extend( true, {}, DataTable.models.oRow, {
  1011 + src: nTr ? 'dom' : 'data'
  1012 + } );
  1013 +
  1014 + oData._aData = aDataIn;
  1015 + oSettings.aoData.push( oData );
  1016 +
  1017 + /* Create the cells */
  1018 + var nTd, sThisType;
  1019 + var columns = oSettings.aoColumns;
  1020 + for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  1021 + {
  1022 + // When working with a row, the data source object must be populated. In
  1023 + // all other cases, the data source object is already populated, so we
  1024 + // don't overwrite it, which might break bindings etc
  1025 + if ( nTr ) {
  1026 + _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
  1027 + }
  1028 + columns[i].sType = null;
  1029 + }
  1030 +
  1031 + /* Add to the display array */
  1032 + oSettings.aiDisplayMaster.push( iRow );
  1033 +
  1034 + /* Create the DOM information, or register it if already present */
  1035 + if ( nTr || ! oSettings.oFeatures.bDeferRender )
  1036 + {
  1037 + _fnCreateTr( oSettings, iRow, nTr, anTds );
  1038 + }
  1039 +
  1040 + return iRow;
  1041 + }
  1042 +
  1043 +
  1044 + /**
  1045 + * Add one or more TR elements to the table. Generally we'd expect to
  1046 + * use this for reading data from a DOM sourced table, but it could be
  1047 + * used for an TR element. Note that if a TR is given, it is used (i.e.
  1048 + * it is not cloned).
  1049 + * @param {object} settings dataTables settings object
  1050 + * @param {array|node|jQuery} trs The TR element(s) to add to the table
  1051 + * @returns {array} Array of indexes for the added rows
  1052 + * @memberof DataTable#oApi
  1053 + */
  1054 + function _fnAddTr( settings, trs )
  1055 + {
  1056 + var row;
  1057 +
  1058 + // Allow an individual node to be passed in
  1059 + if ( ! (trs instanceof $) ) {
  1060 + trs = $(trs);
  1061 + }
  1062 +
  1063 + return trs.map( function (i, el) {
  1064 + row = _fnGetRowElements( settings, el );
  1065 + return _fnAddData( settings, row.data, el, row.cells );
  1066 + } );
  1067 + }
  1068 +
  1069 +
  1070 + /**
  1071 + * Take a TR element and convert it to an index in aoData
  1072 + * @param {object} oSettings dataTables settings object
  1073 + * @param {node} n the TR element to find
  1074 + * @returns {int} index if the node is found, null if not
  1075 + * @memberof DataTable#oApi
  1076 + */
  1077 + function _fnNodeToDataIndex( oSettings, n )
  1078 + {
  1079 + return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
  1080 + }
  1081 +
  1082 +
  1083 + /**
  1084 + * Take a TD element and convert it into a column data index (not the visible index)
  1085 + * @param {object} oSettings dataTables settings object
  1086 + * @param {int} iRow The row number the TD/TH can be found in
  1087 + * @param {node} n The TD/TH element to find
  1088 + * @returns {int} index if the node is found, -1 if not
  1089 + * @memberof DataTable#oApi
  1090 + */
  1091 + function _fnNodeToColumnIndex( oSettings, iRow, n )
  1092 + {
  1093 + return $.inArray( n, oSettings.aoData[ iRow ].anCells );
  1094 + }
  1095 +
  1096 +
  1097 + /**
  1098 + * Get the data for a given cell from the internal cache, taking into account data mapping
  1099 + * @param {object} settings dataTables settings object
  1100 + * @param {int} rowIdx aoData row id
  1101 + * @param {int} colIdx Column index
  1102 + * @param {string} type data get type ('display', 'type' 'filter' 'sort')
  1103 + * @returns {*} Cell data
  1104 + * @memberof DataTable#oApi
  1105 + */
  1106 + function _fnGetCellData( settings, rowIdx, colIdx, type )
  1107 + {
  1108 + var draw = settings.iDraw;
  1109 + var col = settings.aoColumns[colIdx];
  1110 + var rowData = settings.aoData[rowIdx]._aData;
  1111 + var defaultContent = col.sDefaultContent;
  1112 + var cellData = col.fnGetData( rowData, type, {
  1113 + settings: settings,
  1114 + row: rowIdx,
  1115 + col: colIdx
  1116 + } );
  1117 +
  1118 + if ( cellData === undefined ) {
  1119 + if ( settings.iDrawError != draw && defaultContent === null ) {
  1120 + _fnLog( settings, 0, "Requested unknown parameter "+
  1121 + (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
  1122 + " for row "+rowIdx, 4 );
  1123 + settings.iDrawError = draw;
  1124 + }
  1125 + return defaultContent;
  1126 + }
  1127 +
  1128 + /* When the data source is null, we can use default column data */
  1129 + if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
  1130 + cellData = defaultContent;
  1131 + }
  1132 + else if ( typeof cellData === 'function' ) {
  1133 + // If the data source is a function, then we run it and use the return,
  1134 + // executing in the scope of the data object (for instances)
  1135 + return cellData.call( rowData );
  1136 + }
  1137 +
  1138 + if ( cellData === null && type == 'display' ) {
  1139 + return '';
  1140 + }
  1141 + return cellData;
  1142 + }
  1143 +
  1144 +
  1145 + /**
  1146 + * Set the value for a specific cell, into the internal data cache
  1147 + * @param {object} settings dataTables settings object
  1148 + * @param {int} rowIdx aoData row id
  1149 + * @param {int} colIdx Column index
  1150 + * @param {*} val Value to set
  1151 + * @memberof DataTable#oApi
  1152 + */
  1153 + function _fnSetCellData( settings, rowIdx, colIdx, val )
  1154 + {
  1155 + var col = settings.aoColumns[colIdx];
  1156 + var rowData = settings.aoData[rowIdx]._aData;
  1157 +
  1158 + col.fnSetData( rowData, val, {
  1159 + settings: settings,
  1160 + row: rowIdx,
  1161 + col: colIdx
  1162 + } );
  1163 + }
  1164 +
  1165 +
  1166 + // Private variable that is used to match action syntax in the data property object
  1167 + var __reArray = /\[.*?\]$/;
  1168 + var __reFn = /\(\)$/;
  1169 +
  1170 + /**
  1171 + * Split string on periods, taking into account escaped periods
  1172 + * @param {string} str String to split
  1173 + * @return {array} Split string
  1174 + */
  1175 + function _fnSplitObjNotation( str )
  1176 + {
  1177 + return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
  1178 + return s.replace(/\\./g, '.');
  1179 + } );
  1180 + }
  1181 +
  1182 +
  1183 + /**
  1184 + * Return a function that can be used to get data from a source object, taking
  1185 + * into account the ability to use nested objects as a source
  1186 + * @param {string|int|function} mSource The data source for the object
  1187 + * @returns {function} Data get function
  1188 + * @memberof DataTable#oApi
  1189 + */
  1190 + function _fnGetObjectDataFn( mSource )
  1191 + {
  1192 + if ( $.isPlainObject( mSource ) )
  1193 + {
  1194 + /* Build an object of get functions, and wrap them in a single call */
  1195 + var o = {};
  1196 + $.each( mSource, function (key, val) {
  1197 + if ( val ) {
  1198 + o[key] = _fnGetObjectDataFn( val );
  1199 + }
  1200 + } );
  1201 +
  1202 + return function (data, type, row, meta) {
  1203 + var t = o[type] || o._;
  1204 + return t !== undefined ?
  1205 + t(data, type, row, meta) :
  1206 + data;
  1207 + };
  1208 + }
  1209 + else if ( mSource === null )
  1210 + {
  1211 + /* Give an empty string for rendering / sorting etc */
  1212 + return function (data) { // type, row and meta also passed, but not used
  1213 + return data;
  1214 + };
  1215 + }
  1216 + else if ( typeof mSource === 'function' )
  1217 + {
  1218 + return function (data, type, row, meta) {
  1219 + return mSource( data, type, row, meta );
  1220 + };
  1221 + }
  1222 + else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
  1223 + mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
  1224 + {
  1225 + /* If there is a . in the source string then the data source is in a
  1226 + * nested object so we loop over the data for each level to get the next
  1227 + * level down. On each loop we test for undefined, and if found immediately
  1228 + * return. This allows entire objects to be missing and sDefaultContent to
  1229 + * be used if defined, rather than throwing an error
  1230 + */
  1231 + var fetchData = function (data, type, src) {
  1232 + var arrayNotation, funcNotation, out, innerSrc;
  1233 +
  1234 + if ( src !== "" )
  1235 + {
  1236 + var a = _fnSplitObjNotation( src );
  1237 +
  1238 + for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  1239 + {
  1240 + // Check if we are dealing with special notation
  1241 + arrayNotation = a[i].match(__reArray);
  1242 + funcNotation = a[i].match(__reFn);
  1243 +
  1244 + if ( arrayNotation )
  1245 + {
  1246 + // Array notation
  1247 + a[i] = a[i].replace(__reArray, '');
  1248 +
  1249 + // Condition allows simply [] to be passed in
  1250 + if ( a[i] !== "" ) {
  1251 + data = data[ a[i] ];
  1252 + }
  1253 + out = [];
  1254 +
  1255 + // Get the remainder of the nested object to get
  1256 + a.splice( 0, i+1 );
  1257 + innerSrc = a.join('.');
  1258 +
  1259 + // Traverse each entry in the array getting the properties requested
  1260 + for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
  1261 + out.push( fetchData( data[j], type, innerSrc ) );
  1262 + }
  1263 +
  1264 + // If a string is given in between the array notation indicators, that
  1265 + // is used to join the strings together, otherwise an array is returned
  1266 + var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
  1267 + data = (join==="") ? out : out.join(join);
  1268 +
  1269 + // The inner call to fetchData has already traversed through the remainder
  1270 + // of the source requested, so we exit from the loop
  1271 + break;
  1272 + }
  1273 + else if ( funcNotation )
  1274 + {
  1275 + // Function call
  1276 + a[i] = a[i].replace(__reFn, '');
  1277 + data = data[ a[i] ]();
  1278 + continue;
  1279 + }
  1280 +
  1281 + if ( data === null || data[ a[i] ] === undefined )
  1282 + {
  1283 + return undefined;
  1284 + }
  1285 + data = data[ a[i] ];
  1286 + }
  1287 + }
  1288 +
  1289 + return data;
  1290 + };
  1291 +
  1292 + return function (data, type) { // row and meta also passed, but not used
  1293 + return fetchData( data, type, mSource );
  1294 + };
  1295 + }
  1296 + else
  1297 + {
  1298 + /* Array or flat object mapping */
  1299 + return function (data, type) { // row and meta also passed, but not used
  1300 + return data[mSource];
  1301 + };
  1302 + }
  1303 + }
  1304 +
  1305 +
  1306 + /**
  1307 + * Return a function that can be used to set data from a source object, taking
  1308 + * into account the ability to use nested objects as a source
  1309 + * @param {string|int|function} mSource The data source for the object
  1310 + * @returns {function} Data set function
  1311 + * @memberof DataTable#oApi
  1312 + */
  1313 + function _fnSetObjectDataFn( mSource )
  1314 + {
  1315 + if ( $.isPlainObject( mSource ) )
  1316 + {
  1317 + /* Unlike get, only the underscore (global) option is used for for
  1318 + * setting data since we don't know the type here. This is why an object
  1319 + * option is not documented for `mData` (which is read/write), but it is
  1320 + * for `mRender` which is read only.
  1321 + */
  1322 + return _fnSetObjectDataFn( mSource._ );
  1323 + }
  1324 + else if ( mSource === null )
  1325 + {
  1326 + /* Nothing to do when the data source is null */
  1327 + return function () {};
  1328 + }
  1329 + else if ( typeof mSource === 'function' )
  1330 + {
  1331 + return function (data, val, meta) {
  1332 + mSource( data, 'set', val, meta );
  1333 + };
  1334 + }
  1335 + else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
  1336 + mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
  1337 + {
  1338 + /* Like the get, we need to get data from a nested object */
  1339 + var setData = function (data, val, src) {
  1340 + var a = _fnSplitObjNotation( src ), b;
  1341 + var aLast = a[a.length-1];
  1342 + var arrayNotation, funcNotation, o, innerSrc;
  1343 +
  1344 + for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
  1345 + {
  1346 + // Check if we are dealing with an array notation request
  1347 + arrayNotation = a[i].match(__reArray);
  1348 + funcNotation = a[i].match(__reFn);
  1349 +
  1350 + if ( arrayNotation )
  1351 + {
  1352 + a[i] = a[i].replace(__reArray, '');
  1353 + data[ a[i] ] = [];
  1354 +
  1355 + // Get the remainder of the nested object to set so we can recurse
  1356 + b = a.slice();
  1357 + b.splice( 0, i+1 );
  1358 + innerSrc = b.join('.');
  1359 +
  1360 + // Traverse each entry in the array setting the properties requested
  1361 + for ( var j=0, jLen=val.length ; j<jLen ; j++ )
  1362 + {
  1363 + o = {};
  1364 + setData( o, val[j], innerSrc );
  1365 + data[ a[i] ].push( o );
  1366 + }
  1367 +
  1368 + // The inner call to setData has already traversed through the remainder
  1369 + // of the source and has set the data, thus we can exit here
  1370 + return;
  1371 + }
  1372 + else if ( funcNotation )
  1373 + {
  1374 + // Function call
  1375 + a[i] = a[i].replace(__reFn, '');
  1376 + data = data[ a[i] ]( val );
  1377 + }
  1378 +
  1379 + // If the nested object doesn't currently exist - since we are
  1380 + // trying to set the value - create it
  1381 + if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
  1382 + {
  1383 + data[ a[i] ] = {};
  1384 + }
  1385 + data = data[ a[i] ];
  1386 + }
  1387 +
  1388 + // Last item in the input - i.e, the actual set
  1389 + if ( aLast.match(__reFn ) )
  1390 + {
  1391 + // Function call
  1392 + data = data[ aLast.replace(__reFn, '') ]( val );
  1393 + }
  1394 + else
  1395 + {
  1396 + // If array notation is used, we just want to strip it and use the property name
  1397 + // and assign the value. If it isn't used, then we get the result we want anyway
  1398 + data[ aLast.replace(__reArray, '') ] = val;
  1399 + }
  1400 + };
  1401 +
  1402 + return function (data, val) { // meta is also passed in, but not used
  1403 + return setData( data, val, mSource );
  1404 + };
  1405 + }
  1406 + else
  1407 + {
  1408 + /* Array or flat object mapping */
  1409 + return function (data, val) { // meta is also passed in, but not used
  1410 + data[mSource] = val;
  1411 + };
  1412 + }
  1413 + }
  1414 +
  1415 +
  1416 + /**
  1417 + * Return an array with the full table data
  1418 + * @param {object} oSettings dataTables settings object
  1419 + * @returns array {array} aData Master data array
  1420 + * @memberof DataTable#oApi
  1421 + */
  1422 + function _fnGetDataMaster ( settings )
  1423 + {
  1424 + return _pluck( settings.aoData, '_aData' );
  1425 + }
  1426 +
  1427 +
  1428 + /**
  1429 + * Nuke the table
  1430 + * @param {object} oSettings dataTables settings object
  1431 + * @memberof DataTable#oApi
  1432 + */
  1433 + function _fnClearTable( settings )
  1434 + {
  1435 + settings.aoData.length = 0;
  1436 + settings.aiDisplayMaster.length = 0;
  1437 + settings.aiDisplay.length = 0;
  1438 + }
  1439 +
  1440 +
  1441 + /**
  1442 + * Take an array of integers (index array) and remove a target integer (value - not
  1443 + * the key!)
  1444 + * @param {array} a Index array to target
  1445 + * @param {int} iTarget value to find
  1446 + * @memberof DataTable#oApi
  1447 + */
  1448 + function _fnDeleteIndex( a, iTarget, splice )
  1449 + {
  1450 + var iTargetIndex = -1;
  1451 +
  1452 + for ( var i=0, iLen=a.length ; i<iLen ; i++ )
  1453 + {
  1454 + if ( a[i] == iTarget )
  1455 + {
  1456 + iTargetIndex = i;
  1457 + }
  1458 + else if ( a[i] > iTarget )
  1459 + {
  1460 + a[i]--;
  1461 + }
  1462 + }
  1463 +
  1464 + if ( iTargetIndex != -1 && splice === undefined )
  1465 + {
  1466 + a.splice( iTargetIndex, 1 );
  1467 + }
  1468 + }
  1469 +
  1470 +
  1471 + /**
  1472 + * Mark cached data as invalid such that a re-read of the data will occur when
  1473 + * the cached data is next requested. Also update from the data source object.
  1474 + *
  1475 + * @param {object} settings DataTables settings object
  1476 + * @param {int} rowIdx Row index to invalidate
  1477 + * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
  1478 + * or 'data'
  1479 + * @param {int} [colIdx] Column index to invalidate. If undefined the whole
  1480 + * row will be invalidated
  1481 + * @memberof DataTable#oApi
  1482 + *
  1483 + * @todo For the modularisation of v1.11 this will need to become a callback, so
  1484 + * the sort and filter methods can subscribe to it. That will required
  1485 + * initialisation options for sorting, which is why it is not already baked in
  1486 + */
  1487 + function _fnInvalidate( settings, rowIdx, src, colIdx )
  1488 + {
  1489 + var row = settings.aoData[ rowIdx ];
  1490 + var i, ien;
  1491 + var cellWrite = function ( cell, col ) {
  1492 + // This is very frustrating, but in IE if you just write directly
  1493 + // to innerHTML, and elements that are overwritten are GC'ed,
  1494 + // even if there is a reference to them elsewhere
  1495 + while ( cell.childNodes.length ) {
  1496 + cell.removeChild( cell.firstChild );
  1497 + }
  1498 +
  1499 + cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
  1500 + };
  1501 +
  1502 + // Are we reading last data from DOM or the data object?
  1503 + if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
  1504 + // Read the data from the DOM
  1505 + row._aData = _fnGetRowElements(
  1506 + settings, row, colIdx, colIdx === undefined ? undefined : row._aData
  1507 + )
  1508 + .data;
  1509 + }
  1510 + else {
  1511 + // Reading from data object, update the DOM
  1512 + var cells = row.anCells;
  1513 +
  1514 + if ( cells ) {
  1515 + if ( colIdx !== undefined ) {
  1516 + cellWrite( cells[colIdx], colIdx );
  1517 + }
  1518 + else {
  1519 + for ( i=0, ien=cells.length ; i<ien ; i++ ) {
  1520 + cellWrite( cells[i], i );
  1521 + }
  1522 + }
  1523 + }
  1524 + }
  1525 +
  1526 + // For both row and cell invalidation, the cached data for sorting and
  1527 + // filtering is nulled out
  1528 + row._aSortData = null;
  1529 + row._aFilterData = null;
  1530 +
  1531 + // Invalidate the type for a specific column (if given) or all columns since
  1532 + // the data might have changed
  1533 + var cols = settings.aoColumns;
  1534 + if ( colIdx !== undefined ) {
  1535 + cols[ colIdx ].sType = null;
  1536 + }
  1537 + else {
  1538 + for ( i=0, ien=cols.length ; i<ien ; i++ ) {
  1539 + cols[i].sType = null;
  1540 + }
  1541 +
  1542 + // Update DataTables special `DT_*` attributes for the row
  1543 + _fnRowAttributes( row );
  1544 + }
  1545 + }
  1546 +
  1547 +
  1548 + /**
  1549 + * Build a data source object from an HTML row, reading the contents of the
  1550 + * cells that are in the row.
  1551 + *
  1552 + * @param {object} settings DataTables settings object
  1553 + * @param {node|object} TR element from which to read data or existing row
  1554 + * object from which to re-read the data from the cells
  1555 + * @param {int} [colIdx] Optional column index
  1556 + * @param {array|object} [d] Data source object. If `colIdx` is given then this
  1557 + * parameter should also be given and will be used to write the data into.
  1558 + * Only the column in question will be written
  1559 + * @returns {object} Object with two parameters: `data` the data read, in
  1560 + * document order, and `cells` and array of nodes (they can be useful to the
  1561 + * caller, so rather than needing a second traversal to get them, just return
  1562 + * them from here).
  1563 + * @memberof DataTable#oApi
  1564 + */
  1565 + function _fnGetRowElements( settings, row, colIdx, d )
  1566 + {
  1567 + var
  1568 + tds = [],
  1569 + td = row.firstChild,
  1570 + name, col, o, i=0, contents,
  1571 + columns = settings.aoColumns,
  1572 + objectRead = settings._rowReadObject;
  1573 +
  1574 + // Allow the data object to be passed in, or construct
  1575 + d = d || objectRead ? {} : [];
  1576 +
  1577 + var attr = function ( str, td ) {
  1578 + if ( typeof str === 'string' ) {
  1579 + var idx = str.indexOf('@');
  1580 +
  1581 + if ( idx !== -1 ) {
  1582 + var attr = str.substring( idx+1 );
  1583 + var setter = _fnSetObjectDataFn( str );
  1584 + setter( d, td.getAttribute( attr ) );
  1585 + }
  1586 + }
  1587 + };
  1588 +
  1589 + // Read data from a cell and store into the data object
  1590 + var cellProcess = function ( cell ) {
  1591 + if ( colIdx === undefined || colIdx === i ) {
  1592 + col = columns[i];
  1593 + contents = $.trim(cell.innerHTML);
  1594 +
  1595 + if ( col && col._bAttrSrc ) {
  1596 + var setter = _fnSetObjectDataFn( col.mData._ );
  1597 + setter( d, contents );
  1598 +
  1599 + attr( col.mData.sort, cell );
  1600 + attr( col.mData.type, cell );
  1601 + attr( col.mData.filter, cell );
  1602 + }
  1603 + else {
  1604 + // Depending on the `data` option for the columns the data can
  1605 + // be read to either an object or an array.
  1606 + if ( objectRead ) {
  1607 + if ( ! col._setter ) {
  1608 + // Cache the setter function
  1609 + col._setter = _fnSetObjectDataFn( col.mData );
  1610 + }
  1611 + col._setter( d, contents );
  1612 + }
  1613 + else {
  1614 + d[i] = contents;
  1615 + }
  1616 + }
  1617 + }
  1618 +
  1619 + i++;
  1620 + };
  1621 +
  1622 + if ( td ) {
  1623 + // `tr` element was passed in
  1624 + while ( td ) {
  1625 + name = td.nodeName.toUpperCase();
  1626 +
  1627 + if ( name == "TD" || name == "TH" ) {
  1628 + cellProcess( td );
  1629 + tds.push( td );
  1630 + }
  1631 +
  1632 + td = td.nextSibling;
  1633 + }
  1634 + }
  1635 + else {
  1636 + // Existing row object passed in
  1637 + tds = row.anCells;
  1638 +
  1639 + for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
  1640 + cellProcess( tds[j] );
  1641 + }
  1642 + }
  1643 +
  1644 + return {
  1645 + data: d,
  1646 + cells: tds
  1647 + };
  1648 + }
  1649 + /**
  1650 + * Create a new TR element (and it's TD children) for a row
  1651 + * @param {object} oSettings dataTables settings object
  1652 + * @param {int} iRow Row to consider
  1653 + * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
  1654 + * DataTables will create a row automatically
  1655 + * @param {array} [anTds] Array of TD|TH elements for the row - must be given
  1656 + * if nTr is.
  1657 + * @memberof DataTable#oApi
  1658 + */
  1659 + function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
  1660 + {
  1661 + var
  1662 + row = oSettings.aoData[iRow],
  1663 + rowData = row._aData,
  1664 + cells = [],
  1665 + nTr, nTd, oCol,
  1666 + i, iLen;
  1667 +
  1668 + if ( row.nTr === null )
  1669 + {
  1670 + nTr = nTrIn || document.createElement('tr');
  1671 +
  1672 + row.nTr = nTr;
  1673 + row.anCells = cells;
  1674 +
  1675 + /* Use a private property on the node to allow reserve mapping from the node
  1676 + * to the aoData array for fast look up
  1677 + */
  1678 + nTr._DT_RowIndex = iRow;
  1679 +
  1680 + /* Special parameters can be given by the data source to be used on the row */
  1681 + _fnRowAttributes( row );
  1682 +
  1683 + /* Process each column */
  1684 + for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
  1685 + {
  1686 + oCol = oSettings.aoColumns[i];
  1687 +
  1688 + nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
  1689 + cells.push( nTd );
  1690 +
  1691 + // Need to create the HTML if new, or if a rendering function is defined
  1692 + if ( !nTrIn || oCol.mRender || oCol.mData !== i )
  1693 + {
  1694 + nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
  1695 + }
  1696 +
  1697 + /* Add user defined class */
  1698 + if ( oCol.sClass )
  1699 + {
  1700 + nTd.className += ' '+oCol.sClass;
  1701 + }
  1702 +
  1703 + // Visibility - add or remove as required
  1704 + if ( oCol.bVisible && ! nTrIn )
  1705 + {
  1706 + nTr.appendChild( nTd );
  1707 + }
  1708 + else if ( ! oCol.bVisible && nTrIn )
  1709 + {
  1710 + nTd.parentNode.removeChild( nTd );
  1711 + }
  1712 +
  1713 + if ( oCol.fnCreatedCell )
  1714 + {
  1715 + oCol.fnCreatedCell.call( oSettings.oInstance,
  1716 + nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
  1717 + );
  1718 + }
  1719 + }
  1720 +
  1721 + _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
  1722 + }
  1723 +
  1724 + // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
  1725 + // and deployed
  1726 + row.nTr.setAttribute( 'role', 'row' );
  1727 + }
  1728 +
  1729 +
  1730 + /**
  1731 + * Add attributes to a row based on the special `DT_*` parameters in a data
  1732 + * source object.
  1733 + * @param {object} DataTables row object for the row to be modified
  1734 + * @memberof DataTable#oApi
  1735 + */
  1736 + function _fnRowAttributes( row )
  1737 + {
  1738 + var tr = row.nTr;
  1739 + var data = row._aData;
  1740 +
  1741 + if ( tr ) {
  1742 + if ( data.DT_RowId ) {
  1743 + tr.id = data.DT_RowId;
  1744 + }
  1745 +
  1746 + if ( data.DT_RowClass ) {
  1747 + // Remove any classes added by DT_RowClass before
  1748 + var a = data.DT_RowClass.split(' ');
  1749 + row.__rowc = row.__rowc ?
  1750 + _unique( row.__rowc.concat( a ) ) :
  1751 + a;
  1752 +
  1753 + $(tr)
  1754 + .removeClass( row.__rowc.join(' ') )
  1755 + .addClass( data.DT_RowClass );
  1756 + }
  1757 +
  1758 + if ( data.DT_RowAttr ) {
  1759 + $(tr).attr( data.DT_RowAttr );
  1760 + }
  1761 +
  1762 + if ( data.DT_RowData ) {
  1763 + $(tr).data( data.DT_RowData );
  1764 + }
  1765 + }
  1766 + }
  1767 +
  1768 +
  1769 + /**
  1770 + * Create the HTML header for the table
  1771 + * @param {object} oSettings dataTables settings object
  1772 + * @memberof DataTable#oApi
  1773 + */
  1774 + function _fnBuildHead( oSettings )
  1775 + {
  1776 + var i, ien, cell, row, column;
  1777 + var thead = oSettings.nTHead;
  1778 + var tfoot = oSettings.nTFoot;
  1779 + var createHeader = $('th, td', thead).length === 0;
  1780 + var classes = oSettings.oClasses;
  1781 + var columns = oSettings.aoColumns;
  1782 +
  1783 + if ( createHeader ) {
  1784 + row = $('<tr/>').appendTo( thead );
  1785 + }
  1786 +
  1787 + for ( i=0, ien=columns.length ; i<ien ; i++ ) {
  1788 + column = columns[i];
  1789 + cell = $( column.nTh ).addClass( column.sClass );
  1790 +
  1791 + if ( createHeader ) {
  1792 + cell.appendTo( row );
  1793 + }
  1794 +
  1795 + // 1.11 move into sorting
  1796 + if ( oSettings.oFeatures.bSort ) {
  1797 + cell.addClass( column.sSortingClass );
  1798 +
  1799 + if ( column.bSortable !== false ) {
  1800 + cell
  1801 + .attr( 'tabindex', oSettings.iTabIndex )
  1802 + .attr( 'aria-controls', oSettings.sTableId );
  1803 +
  1804 + _fnSortAttachListener( oSettings, column.nTh, i );
  1805 + }
  1806 + }
  1807 +
  1808 + if ( column.sTitle != cell.html() ) {
  1809 + cell.html( column.sTitle );
  1810 + }
  1811 +
  1812 + _fnRenderer( oSettings, 'header' )(
  1813 + oSettings, cell, column, classes
  1814 + );
  1815 + }
  1816 +
  1817 + if ( createHeader ) {
  1818 + _fnDetectHeader( oSettings.aoHeader, thead );
  1819 + }
  1820 +
  1821 + /* ARIA role for the rows */
  1822 + $(thead).find('>tr').attr('role', 'row');
  1823 +
  1824 + /* Deal with the footer - add classes if required */
  1825 + $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
  1826 + $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
  1827 +
  1828 + // Cache the footer cells. Note that we only take the cells from the first
  1829 + // row in the footer. If there is more than one row the user wants to
  1830 + // interact with, they need to use the table().foot() method. Note also this
  1831 + // allows cells to be used for multiple columns using colspan
  1832 + if ( tfoot !== null ) {
  1833 + var cells = oSettings.aoFooter[0];
  1834 +
  1835 + for ( i=0, ien=cells.length ; i<ien ; i++ ) {
  1836 + column = columns[i];
  1837 + column.nTf = cells[i].cell;
  1838 +
  1839 + if ( column.sClass ) {
  1840 + $(column.nTf).addClass( column.sClass );
  1841 + }
  1842 + }
  1843 + }
  1844 + }
  1845 +
  1846 +
  1847 + /**
  1848 + * Draw the header (or footer) element based on the column visibility states. The
  1849 + * methodology here is to use the layout array from _fnDetectHeader, modified for
  1850 + * the instantaneous column visibility, to construct the new layout. The grid is
  1851 + * traversed over cell at a time in a rows x columns grid fashion, although each
  1852 + * cell insert can cover multiple elements in the grid - which is tracks using the
  1853 + * aApplied array. Cell inserts in the grid will only occur where there isn't
  1854 + * already a cell in that position.
  1855 + * @param {object} oSettings dataTables settings object
  1856 + * @param array {objects} aoSource Layout array from _fnDetectHeader
  1857 + * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
  1858 + * @memberof DataTable#oApi
  1859 + */
  1860 + function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
  1861 + {
  1862 + var i, iLen, j, jLen, k, kLen, n, nLocalTr;
  1863 + var aoLocal = [];
  1864 + var aApplied = [];
  1865 + var iColumns = oSettings.aoColumns.length;
  1866 + var iRowspan, iColspan;
  1867 +
  1868 + if ( ! aoSource )
  1869 + {
  1870 + return;
  1871 + }
  1872 +
  1873 + if ( bIncludeHidden === undefined )
  1874 + {
  1875 + bIncludeHidden = false;
  1876 + }
  1877 +
  1878 + /* Make a copy of the master layout array, but without the visible columns in it */
  1879 + for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
  1880 + {
  1881 + aoLocal[i] = aoSource[i].slice();
  1882 + aoLocal[i].nTr = aoSource[i].nTr;
  1883 +
  1884 + /* Remove any columns which are currently hidden */
  1885 + for ( j=iColumns-1 ; j>=0 ; j-- )
  1886 + {
  1887 + if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
  1888 + {
  1889 + aoLocal[i].splice( j, 1 );
  1890 + }
  1891 + }
  1892 +
  1893 + /* Prep the applied array - it needs an element for each row */
  1894 + aApplied.push( [] );
  1895 + }
  1896 +
  1897 + for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
  1898 + {
  1899 + nLocalTr = aoLocal[i].nTr;
  1900 +
  1901 + /* All cells are going to be replaced, so empty out the row */
  1902 + if ( nLocalTr )
  1903 + {
  1904 + while( (n = nLocalTr.firstChild) )
  1905 + {
  1906 + nLocalTr.removeChild( n );
  1907 + }
  1908 + }
  1909 +
  1910 + for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
  1911 + {
  1912 + iRowspan = 1;
  1913 + iColspan = 1;
  1914 +
  1915 + /* Check to see if there is already a cell (row/colspan) covering our target
  1916 + * insert point. If there is, then there is nothing to do.
  1917 + */
  1918 + if ( aApplied[i][j] === undefined )
  1919 + {
  1920 + nLocalTr.appendChild( aoLocal[i][j].cell );
  1921 + aApplied[i][j] = 1;
  1922 +
  1923 + /* Expand the cell to cover as many rows as needed */
  1924 + while ( aoLocal[i+iRowspan] !== undefined &&
  1925 + aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
  1926 + {
  1927 + aApplied[i+iRowspan][j] = 1;
  1928 + iRowspan++;
  1929 + }
  1930 +
  1931 + /* Expand the cell to cover as many columns as needed */
  1932 + while ( aoLocal[i][j+iColspan] !== undefined &&
  1933 + aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
  1934 + {
  1935 + /* Must update the applied array over the rows for the columns */
  1936 + for ( k=0 ; k<iRowspan ; k++ )
  1937 + {
  1938 + aApplied[i+k][j+iColspan] = 1;
  1939 + }
  1940 + iColspan++;
  1941 + }
  1942 +
  1943 + /* Do the actual expansion in the DOM */
  1944 + $(aoLocal[i][j].cell)
  1945 + .attr('rowspan', iRowspan)
  1946 + .attr('colspan', iColspan);
  1947 + }
  1948 + }
  1949 + }
  1950 + }
  1951 +
  1952 +
  1953 + /**
  1954 + * Insert the required TR nodes into the table for display
  1955 + * @param {object} oSettings dataTables settings object
  1956 + * @memberof DataTable#oApi
  1957 + */
  1958 + function _fnDraw( oSettings )
  1959 + {
  1960 + /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
  1961 + var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
  1962 + if ( $.inArray( false, aPreDraw ) !== -1 )
  1963 + {
  1964 + _fnProcessingDisplay( oSettings, false );
  1965 + return;
  1966 + }
  1967 +
  1968 + var i, iLen, n;
  1969 + var anRows = [];
  1970 + var iRowCount = 0;
  1971 + var asStripeClasses = oSettings.asStripeClasses;
  1972 + var iStripes = asStripeClasses.length;
  1973 + var iOpenRows = oSettings.aoOpenRows.length;
  1974 + var oLang = oSettings.oLanguage;
  1975 + var iInitDisplayStart = oSettings.iInitDisplayStart;
  1976 + var bServerSide = _fnDataSource( oSettings ) == 'ssp';
  1977 + var aiDisplay = oSettings.aiDisplay;
  1978 +
  1979 + oSettings.bDrawing = true;
  1980 +
  1981 + /* Check and see if we have an initial draw position from state saving */
  1982 + if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
  1983 + {
  1984 + oSettings._iDisplayStart = bServerSide ?
  1985 + iInitDisplayStart :
  1986 + iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
  1987 + 0 :
  1988 + iInitDisplayStart;
  1989 +
  1990 + oSettings.iInitDisplayStart = -1;
  1991 + }
  1992 +
  1993 + var iDisplayStart = oSettings._iDisplayStart;
  1994 + var iDisplayEnd = oSettings.fnDisplayEnd();
  1995 +
  1996 + /* Server-side processing draw intercept */
  1997 + if ( oSettings.bDeferLoading )
  1998 + {
  1999 + oSettings.bDeferLoading = false;
  2000 + oSettings.iDraw++;
  2001 + _fnProcessingDisplay( oSettings, false );
  2002 + }
  2003 + else if ( !bServerSide )
  2004 + {
  2005 + oSettings.iDraw++;
  2006 + }
  2007 + else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
  2008 + {
  2009 + return;
  2010 + }
  2011 +
  2012 + if ( aiDisplay.length !== 0 )
  2013 + {
  2014 + var iStart = bServerSide ? 0 : iDisplayStart;
  2015 + var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
  2016 +
  2017 + for ( var j=iStart ; j<iEnd ; j++ )
  2018 + {
  2019 + var iDataIndex = aiDisplay[j];
  2020 + var aoData = oSettings.aoData[ iDataIndex ];
  2021 + if ( aoData.nTr === null )
  2022 + {
  2023 + _fnCreateTr( oSettings, iDataIndex );
  2024 + }
  2025 +
  2026 + var nRow = aoData.nTr;
  2027 +
  2028 + /* Remove the old striping classes and then add the new one */
  2029 + if ( iStripes !== 0 )
  2030 + {
  2031 + var sStripe = asStripeClasses[ iRowCount % iStripes ];
  2032 + if ( aoData._sRowStripe != sStripe )
  2033 + {
  2034 + $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
  2035 + aoData._sRowStripe = sStripe;
  2036 + }
  2037 + }
  2038 +
  2039 + // Row callback functions - might want to manipulate the row
  2040 + // iRowCount and j are not currently documented. Are they at all
  2041 + // useful?
  2042 + _fnCallbackFire( oSettings, 'aoRowCallback', null,
  2043 + [nRow, aoData._aData, iRowCount, j] );
  2044 +
  2045 + anRows.push( nRow );
  2046 + iRowCount++;
  2047 + }
  2048 + }
  2049 + else
  2050 + {
  2051 + /* Table is empty - create a row with an empty message in it */
  2052 + var sZero = oLang.sZeroRecords;
  2053 + if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )
  2054 + {
  2055 + sZero = oLang.sLoadingRecords;
  2056 + }
  2057 + else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
  2058 + {
  2059 + sZero = oLang.sEmptyTable;
  2060 + }
  2061 +
  2062 + anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
  2063 + .append( $('<td />', {
  2064 + 'valign': 'top',
  2065 + 'colSpan': _fnVisbleColumns( oSettings ),
  2066 + 'class': oSettings.oClasses.sRowEmpty
  2067 + } ).html( sZero ) )[0];
  2068 + }
  2069 +
  2070 + /* Header and footer callbacks */
  2071 + _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
  2072 + _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
  2073 +
  2074 + _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
  2075 + _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
  2076 +
  2077 + var body = $(oSettings.nTBody);
  2078 +
  2079 + body.children().detach();
  2080 + body.append( $(anRows) );
  2081 +
  2082 + /* Call all required callback functions for the end of a draw */
  2083 + _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
  2084 +
  2085 + /* Draw is complete, sorting and filtering must be as well */
  2086 + oSettings.bSorted = false;
  2087 + oSettings.bFiltered = false;
  2088 + oSettings.bDrawing = false;
  2089 + }
  2090 +
  2091 +
  2092 + /**
  2093 + * Redraw the table - taking account of the various features which are enabled
  2094 + * @param {object} oSettings dataTables settings object
  2095 + * @param {boolean} [holdPosition] Keep the current paging position. By default
  2096 + * the paging is reset to the first page
  2097 + * @memberof DataTable#oApi
  2098 + */
  2099 + function _fnReDraw( settings, holdPosition )
  2100 + {
  2101 + var
  2102 + features = settings.oFeatures,
  2103 + sort = features.bSort,
  2104 + filter = features.bFilter;
  2105 +
  2106 + if ( sort ) {
  2107 + _fnSort( settings );
  2108 + }
  2109 +
  2110 + if ( filter ) {
  2111 + _fnFilterComplete( settings, settings.oPreviousSearch );
  2112 + }
  2113 + else {
  2114 + // No filtering, so we want to just use the display master
  2115 + settings.aiDisplay = settings.aiDisplayMaster.slice();
  2116 + }
  2117 +
  2118 + if ( holdPosition !== true ) {
  2119 + settings._iDisplayStart = 0;
  2120 + }
  2121 +
  2122 + // Let any modules know about the draw hold position state (used by
  2123 + // scrolling internally)
  2124 + settings._drawHold = holdPosition;
  2125 +
  2126 + _fnDraw( settings );
  2127 +
  2128 + settings._drawHold = false;
  2129 + }
  2130 +
  2131 +
  2132 + /**
  2133 + * Add the options to the page HTML for the table
  2134 + * @param {object} oSettings dataTables settings object
  2135 + * @memberof DataTable#oApi
  2136 + */
  2137 + function _fnAddOptionsHtml ( oSettings )
  2138 + {
  2139 + var classes = oSettings.oClasses;
  2140 + var table = $(oSettings.nTable);
  2141 + var holding = $('<div/>').insertBefore( table ); // Holding element for speed
  2142 + var features = oSettings.oFeatures;
  2143 +
  2144 + // All DataTables are wrapped in a div
  2145 + var insert = $('<div/>', {
  2146 + id: oSettings.sTableId+'_wrapper',
  2147 + 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
  2148 + } );
  2149 +
  2150 + oSettings.nHolding = holding[0];
  2151 + oSettings.nTableWrapper = insert[0];
  2152 + oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
  2153 +
  2154 + /* Loop over the user set positioning and place the elements as needed */
  2155 + var aDom = oSettings.sDom.split('');
  2156 + var featureNode, cOption, nNewNode, cNext, sAttr, j;
  2157 + for ( var i=0 ; i<aDom.length ; i++ )
  2158 + {
  2159 + featureNode = null;
  2160 + cOption = aDom[i];
  2161 +
  2162 + if ( cOption == '<' )
  2163 + {
  2164 + /* New container div */
  2165 + nNewNode = $('<div/>')[0];
  2166 +
  2167 + /* Check to see if we should append an id and/or a class name to the container */
  2168 + cNext = aDom[i+1];
  2169 + if ( cNext == "'" || cNext == '"' )
  2170 + {
  2171 + sAttr = "";
  2172 + j = 2;
  2173 + while ( aDom[i+j] != cNext )
  2174 + {
  2175 + sAttr += aDom[i+j];
  2176 + j++;
  2177 + }
  2178 +
  2179 + /* Replace jQuery UI constants @todo depreciated */
  2180 + if ( sAttr == "H" )
  2181 + {
  2182 + sAttr = classes.sJUIHeader;
  2183 + }
  2184 + else if ( sAttr == "F" )
  2185 + {
  2186 + sAttr = classes.sJUIFooter;
  2187 + }
  2188 +
  2189 + /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
  2190 + * breaks the string into parts and applies them as needed
  2191 + */
  2192 + if ( sAttr.indexOf('.') != -1 )
  2193 + {
  2194 + var aSplit = sAttr.split('.');
  2195 + nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
  2196 + nNewNode.className = aSplit[1];
  2197 + }
  2198 + else if ( sAttr.charAt(0) == "#" )
  2199 + {
  2200 + nNewNode.id = sAttr.substr(1, sAttr.length-1);
  2201 + }
  2202 + else
  2203 + {
  2204 + nNewNode.className = sAttr;
  2205 + }
  2206 +
  2207 + i += j; /* Move along the position array */
  2208 + }
  2209 +
  2210 + insert.append( nNewNode );
  2211 + insert = $(nNewNode);
  2212 + }
  2213 + else if ( cOption == '>' )
  2214 + {
  2215 + /* End container div */
  2216 + insert = insert.parent();
  2217 + }
  2218 + // @todo Move options into their own plugins?
  2219 + else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
  2220 + {
  2221 + /* Length */
  2222 + featureNode = _fnFeatureHtmlLength( oSettings );
  2223 + }
  2224 + else if ( cOption == 'f' && features.bFilter )
  2225 + {
  2226 + /* Filter */
  2227 + featureNode = _fnFeatureHtmlFilter( oSettings );
  2228 + }
  2229 + else if ( cOption == 'r' && features.bProcessing )
  2230 + {
  2231 + /* pRocessing */
  2232 + featureNode = _fnFeatureHtmlProcessing( oSettings );
  2233 + }
  2234 + else if ( cOption == 't' )
  2235 + {
  2236 + /* Table */
  2237 + featureNode = _fnFeatureHtmlTable( oSettings );
  2238 + }
  2239 + else if ( cOption == 'i' && features.bInfo )
  2240 + {
  2241 + /* Info */
  2242 + featureNode = _fnFeatureHtmlInfo( oSettings );
  2243 + }
  2244 + else if ( cOption == 'p' && features.bPaginate )
  2245 + {
  2246 + /* Pagination */
  2247 + featureNode = _fnFeatureHtmlPaginate( oSettings );
  2248 + }
  2249 + else if ( DataTable.ext.feature.length !== 0 )
  2250 + {
  2251 + /* Plug-in features */
  2252 + var aoFeatures = DataTable.ext.feature;
  2253 + for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
  2254 + {
  2255 + if ( cOption == aoFeatures[k].cFeature )
  2256 + {
  2257 + featureNode = aoFeatures[k].fnInit( oSettings );
  2258 + break;
  2259 + }
  2260 + }
  2261 + }
  2262 +
  2263 + /* Add to the 2D features array */
  2264 + if ( featureNode )
  2265 + {
  2266 + var aanFeatures = oSettings.aanFeatures;
  2267 +
  2268 + if ( ! aanFeatures[cOption] )
  2269 + {
  2270 + aanFeatures[cOption] = [];
  2271 + }
  2272 +
  2273 + aanFeatures[cOption].push( featureNode );
  2274 + insert.append( featureNode );
  2275 + }
  2276 + }
  2277 +
  2278 + /* Built our DOM structure - replace the holding div with what we want */
  2279 + holding.replaceWith( insert );
  2280 + }
  2281 +
  2282 +
  2283 + /**
  2284 + * Use the DOM source to create up an array of header cells. The idea here is to
  2285 + * create a layout grid (array) of rows x columns, which contains a reference
  2286 + * to the cell that that point in the grid (regardless of col/rowspan), such that
  2287 + * any column / row could be removed and the new grid constructed
  2288 + * @param array {object} aLayout Array to store the calculated layout in
  2289 + * @param {node} nThead The header/footer element for the table
  2290 + * @memberof DataTable#oApi
  2291 + */
  2292 + function _fnDetectHeader ( aLayout, nThead )
  2293 + {
  2294 + var nTrs = $(nThead).children('tr');
  2295 + var nTr, nCell;
  2296 + var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
  2297 + var bUnique;
  2298 + var fnShiftCol = function ( a, i, j ) {
  2299 + var k = a[i];
  2300 + while ( k[j] ) {
  2301 + j++;
  2302 + }
  2303 + return j;
  2304 + };
  2305 +
  2306 + aLayout.splice( 0, aLayout.length );
  2307 +
  2308 + /* We know how many rows there are in the layout - so prep it */
  2309 + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  2310 + {
  2311 + aLayout.push( [] );
  2312 + }
  2313 +
  2314 + /* Calculate a layout array */
  2315 + for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
  2316 + {
  2317 + nTr = nTrs[i];
  2318 + iColumn = 0;
  2319 +
  2320 + /* For every cell in the row... */
  2321 + nCell = nTr.firstChild;
  2322 + while ( nCell ) {
  2323 + if ( nCell.nodeName.toUpperCase() == "TD" ||
  2324 + nCell.nodeName.toUpperCase() == "TH" )
  2325 + {
  2326 + /* Get the col and rowspan attributes from the DOM and sanitise them */
  2327 + iColspan = nCell.getAttribute('colspan') * 1;
  2328 + iRowspan = nCell.getAttribute('rowspan') * 1;
  2329 + iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
  2330 + iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
  2331 +
  2332 + /* There might be colspan cells already in this row, so shift our target
  2333 + * accordingly
  2334 + */
  2335 + iColShifted = fnShiftCol( aLayout, i, iColumn );
  2336 +
  2337 + /* Cache calculation for unique columns */
  2338 + bUnique = iColspan === 1 ? true : false;
  2339 +
  2340 + /* If there is col / rowspan, copy the information into the layout grid */
  2341 + for ( l=0 ; l<iColspan ; l++ )
  2342 + {
  2343 + for ( k=0 ; k<iRowspan ; k++ )
  2344 + {
  2345 + aLayout[i+k][iColShifted+l] = {
  2346 + "cell": nCell,
  2347 + "unique": bUnique
  2348 + };
  2349 + aLayout[i+k].nTr = nTr;
  2350 + }
  2351 + }
  2352 + }
  2353 + nCell = nCell.nextSibling;
  2354 + }
  2355 + }
  2356 + }
  2357 +
  2358 +
  2359 + /**
  2360 + * Get an array of unique th elements, one for each column
  2361 + * @param {object} oSettings dataTables settings object
  2362 + * @param {node} nHeader automatically detect the layout from this node - optional
  2363 + * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
  2364 + * @returns array {node} aReturn list of unique th's
  2365 + * @memberof DataTable#oApi
  2366 + */
  2367 + function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
  2368 + {
  2369 + var aReturn = [];
  2370 + if ( !aLayout )
  2371 + {
  2372 + aLayout = oSettings.aoHeader;
  2373 + if ( nHeader )
  2374 + {
  2375 + aLayout = [];
  2376 + _fnDetectHeader( aLayout, nHeader );
  2377 + }
  2378 + }
  2379 +
  2380 + for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
  2381 + {
  2382 + for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
  2383 + {
  2384 + if ( aLayout[i][j].unique &&
  2385 + (!aReturn[j] || !oSettings.bSortCellsTop) )
  2386 + {
  2387 + aReturn[j] = aLayout[i][j].cell;
  2388 + }
  2389 + }
  2390 + }
  2391 +
  2392 + return aReturn;
  2393 + }
  2394 +
  2395 + /**
  2396 + * Create an Ajax call based on the table's settings, taking into account that
  2397 + * parameters can have multiple forms, and backwards compatibility.
  2398 + *
  2399 + * @param {object} oSettings dataTables settings object
  2400 + * @param {array} data Data to send to the server, required by
  2401 + * DataTables - may be augmented by developer callbacks
  2402 + * @param {function} fn Callback function to run when data is obtained
  2403 + */
  2404 + function _fnBuildAjax( oSettings, data, fn )
  2405 + {
  2406 + // Compatibility with 1.9-, allow fnServerData and event to manipulate
  2407 + _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
  2408 +
  2409 + // Convert to object based for 1.10+ if using the old array scheme which can
  2410 + // come from server-side processing or serverParams
  2411 + if ( data && $.isArray(data) ) {
  2412 + var tmp = {};
  2413 + var rbracket = /(.*?)\[\]$/;
  2414 +
  2415 + $.each( data, function (key, val) {
  2416 + var match = val.name.match(rbracket);
  2417 +
  2418 + if ( match ) {
  2419 + // Support for arrays
  2420 + var name = match[0];
  2421 +
  2422 + if ( ! tmp[ name ] ) {
  2423 + tmp[ name ] = [];
  2424 + }
  2425 + tmp[ name ].push( val.value );
  2426 + }
  2427 + else {
  2428 + tmp[val.name] = val.value;
  2429 + }
  2430 + } );
  2431 + data = tmp;
  2432 + }
  2433 +
  2434 + var ajaxData;
  2435 + var ajax = oSettings.ajax;
  2436 + var instance = oSettings.oInstance;
  2437 + var callback = function ( json ) {
  2438 + _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
  2439 + fn( json );
  2440 + };
  2441 +
  2442 + if ( $.isPlainObject( ajax ) && ajax.data )
  2443 + {
  2444 + ajaxData = ajax.data;
  2445 +
  2446 + var newData = $.isFunction( ajaxData ) ?
  2447 + ajaxData( data, oSettings ) : // fn can manipulate data or return
  2448 + ajaxData; // an object object or array to merge
  2449 +
  2450 + // If the function returned something, use that alone
  2451 + data = $.isFunction( ajaxData ) && newData ?
  2452 + newData :
  2453 + $.extend( true, data, newData );
  2454 +
  2455 + // Remove the data property as we've resolved it already and don't want
  2456 + // jQuery to do it again (it is restored at the end of the function)
  2457 + delete ajax.data;
  2458 + }
  2459 +
  2460 + var baseAjax = {
  2461 + "data": data,
  2462 + "success": function (json) {
  2463 + var error = json.error || json.sError;
  2464 + if ( error ) {
  2465 + _fnLog( oSettings, 0, error );
  2466 + }
  2467 +
  2468 + oSettings.json = json;
  2469 + callback( json );
  2470 + },
  2471 + "dataType": "json",
  2472 + "cache": false,
  2473 + "type": oSettings.sServerMethod,
  2474 + "error": function (xhr, error, thrown) {
  2475 + var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
  2476 +
  2477 + if ( $.inArray( true, ret ) === -1 ) {
  2478 + if ( error == "parsererror" ) {
  2479 + _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
  2480 + }
  2481 + else if ( xhr.readyState === 4 ) {
  2482 + _fnLog( oSettings, 0, 'Ajax error', 7 );
  2483 + }
  2484 + }
  2485 +
  2486 + _fnProcessingDisplay( oSettings, false );
  2487 + }
  2488 + };
  2489 +
  2490 + // Store the data submitted for the API
  2491 + oSettings.oAjaxData = data;
  2492 +
  2493 + // Allow plug-ins and external processes to modify the data
  2494 + _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
  2495 +
  2496 + if ( oSettings.fnServerData )
  2497 + {
  2498 + // DataTables 1.9- compatibility
  2499 + oSettings.fnServerData.call( instance,
  2500 + oSettings.sAjaxSource,
  2501 + $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
  2502 + return { name: key, value: val };
  2503 + } ),
  2504 + callback,
  2505 + oSettings
  2506 + );
  2507 + }
  2508 + else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
  2509 + {
  2510 + // DataTables 1.9- compatibility
  2511 + oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
  2512 + url: ajax || oSettings.sAjaxSource
  2513 + } ) );
  2514 + }
  2515 + else if ( $.isFunction( ajax ) )
  2516 + {
  2517 + // Is a function - let the caller define what needs to be done
  2518 + oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
  2519 + }
  2520 + else
  2521 + {
  2522 + // Object to extend the base settings
  2523 + oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
  2524 +
  2525 + // Restore for next time around
  2526 + ajax.data = ajaxData;
  2527 + }
  2528 + }
  2529 +
  2530 +
  2531 + /**
  2532 + * Update the table using an Ajax call
  2533 + * @param {object} settings dataTables settings object
  2534 + * @returns {boolean} Block the table drawing or not
  2535 + * @memberof DataTable#oApi
  2536 + */
  2537 + function _fnAjaxUpdate( settings )
  2538 + {
  2539 + if ( settings.bAjaxDataGet ) {
  2540 + settings.iDraw++;
  2541 + _fnProcessingDisplay( settings, true );
  2542 +
  2543 + _fnBuildAjax(
  2544 + settings,
  2545 + _fnAjaxParameters( settings ),
  2546 + function(json) {
  2547 + _fnAjaxUpdateDraw( settings, json );
  2548 + }
  2549 + );
  2550 +
  2551 + return false;
  2552 + }
  2553 + return true;
  2554 + }
  2555 +
  2556 +
  2557 + /**
  2558 + * Build up the parameters in an object needed for a server-side processing
  2559 + * request. Note that this is basically done twice, is different ways - a modern
  2560 + * method which is used by default in DataTables 1.10 which uses objects and
  2561 + * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
  2562 + * the sAjaxSource option is used in the initialisation, or the legacyAjax
  2563 + * option is set.
  2564 + * @param {object} oSettings dataTables settings object
  2565 + * @returns {bool} block the table drawing or not
  2566 + * @memberof DataTable#oApi
  2567 + */
  2568 + function _fnAjaxParameters( settings )
  2569 + {
  2570 + var
  2571 + columns = settings.aoColumns,
  2572 + columnCount = columns.length,
  2573 + features = settings.oFeatures,
  2574 + preSearch = settings.oPreviousSearch,
  2575 + preColSearch = settings.aoPreSearchCols,
  2576 + i, data = [], dataProp, column, columnSearch,
  2577 + sort = _fnSortFlatten( settings ),
  2578 + displayStart = settings._iDisplayStart,
  2579 + displayLength = features.bPaginate !== false ?
  2580 + settings._iDisplayLength :
  2581 + -1;
  2582 +
  2583 + var param = function ( name, value ) {
  2584 + data.push( { 'name': name, 'value': value } );
  2585 + };
  2586 +
  2587 + // DataTables 1.9- compatible method
  2588 + param( 'sEcho', settings.iDraw );
  2589 + param( 'iColumns', columnCount );
  2590 + param( 'sColumns', _pluck( columns, 'sName' ).join(',') );
  2591 + param( 'iDisplayStart', displayStart );
  2592 + param( 'iDisplayLength', displayLength );
  2593 +
  2594 + // DataTables 1.10+ method
  2595 + var d = {
  2596 + draw: settings.iDraw,
  2597 + columns: [],
  2598 + order: [],
  2599 + start: displayStart,
  2600 + length: displayLength,
  2601 + search: {
  2602 + value: preSearch.sSearch,
  2603 + regex: preSearch.bRegex
  2604 + }
  2605 + };
  2606 +
  2607 + for ( i=0 ; i<columnCount ; i++ ) {
  2608 + column = columns[i];
  2609 + columnSearch = preColSearch[i];
  2610 + dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
  2611 +
  2612 + d.columns.push( {
  2613 + data: dataProp,
  2614 + name: column.sName,
  2615 + searchable: column.bSearchable,
  2616 + orderable: column.bSortable,
  2617 + search: {
  2618 + value: columnSearch.sSearch,
  2619 + regex: columnSearch.bRegex
  2620 + }
  2621 + } );
  2622 +
  2623 + param( "mDataProp_"+i, dataProp );
  2624 +
  2625 + if ( features.bFilter ) {
  2626 + param( 'sSearch_'+i, columnSearch.sSearch );
  2627 + param( 'bRegex_'+i, columnSearch.bRegex );
  2628 + param( 'bSearchable_'+i, column.bSearchable );
  2629 + }
  2630 +
  2631 + if ( features.bSort ) {
  2632 + param( 'bSortable_'+i, column.bSortable );
  2633 + }
  2634 + }
  2635 +
  2636 + if ( features.bFilter ) {
  2637 + param( 'sSearch', preSearch.sSearch );
  2638 + param( 'bRegex', preSearch.bRegex );
  2639 + }
  2640 +
  2641 + if ( features.bSort ) {
  2642 + $.each( sort, function ( i, val ) {
  2643 + d.order.push( { column: val.col, dir: val.dir } );
  2644 +
  2645 + param( 'iSortCol_'+i, val.col );
  2646 + param( 'sSortDir_'+i, val.dir );
  2647 + } );
  2648 +
  2649 + param( 'iSortingCols', sort.length );
  2650 + }
  2651 +
  2652 + // If the legacy.ajax parameter is null, then we automatically decide which
  2653 + // form to use, based on sAjaxSource
  2654 + var legacy = DataTable.ext.legacy.ajax;
  2655 + if ( legacy === null ) {
  2656 + return settings.sAjaxSource ? data : d;
  2657 + }
  2658 +
  2659 + // Otherwise, if legacy has been specified then we use that to decide on the
  2660 + // form
  2661 + return legacy ? data : d;
  2662 + }
  2663 +
  2664 +
  2665 + /**
  2666 + * Data the data from the server (nuking the old) and redraw the table
  2667 + * @param {object} oSettings dataTables settings object
  2668 + * @param {object} json json data return from the server.
  2669 + * @param {string} json.sEcho Tracking flag for DataTables to match requests
  2670 + * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
  2671 + * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
  2672 + * @param {array} json.aaData The data to display on this page
  2673 + * @param {string} [json.sColumns] Column ordering (sName, comma separated)
  2674 + * @memberof DataTable#oApi
  2675 + */
  2676 + function _fnAjaxUpdateDraw ( settings, json )
  2677 + {
  2678 + // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
  2679 + // Support both
  2680 + var compat = function ( old, modern ) {
  2681 + return json[old] !== undefined ? json[old] : json[modern];
  2682 + };
  2683 +
  2684 + var data = _fnAjaxDataSrc( settings, json );
  2685 + var draw = compat( 'sEcho', 'draw' );
  2686 + var recordsTotal = compat( 'iTotalRecords', 'totalElements' );
  2687 + var recordsFiltered = compat( 'iTotalDisplayRecords', 'totalElements' );
  2688 +
  2689 + if ( draw ) {
  2690 + // Protect against out of sequence returns
  2691 + if ( draw*1 < settings.iDraw ) {
  2692 + return;
  2693 + }
  2694 + settings.iDraw = draw * 1;
  2695 + }
  2696 +
  2697 + _fnClearTable( settings );
  2698 + settings._iRecordsTotal = parseInt(recordsTotal, 10);
  2699 + settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
  2700 +
  2701 + for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  2702 + _fnAddData( settings, data[i] );
  2703 + }
  2704 + settings.aiDisplay = settings.aiDisplayMaster.slice();
  2705 +
  2706 + settings.bAjaxDataGet = false;
  2707 + _fnDraw( settings );
  2708 +
  2709 + if ( ! settings._bInitComplete ) {
  2710 + _fnInitComplete( settings, json );
  2711 + }
  2712 +
  2713 + settings.bAjaxDataGet = true;
  2714 + _fnProcessingDisplay( settings, false );
  2715 + }
  2716 +
  2717 +
  2718 + /**
  2719 + * Get the data from the JSON data source to use for drawing a table. Using
  2720 + * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
  2721 + * source object, or from a processing function.
  2722 + * @param {object} oSettings dataTables settings object
  2723 + * @param {object} json Data source object / array from the server
  2724 + * @return {array} Array of data to use
  2725 + */
  2726 + function _fnAjaxDataSrc ( oSettings, json )
  2727 + {
  2728 + var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
  2729 + oSettings.ajax.dataSrc :
  2730 + oSettings.sAjaxDataProp; // Compatibility with 1.9-.
  2731 +
  2732 + // Compatibility with 1.9-. In order to read from aaData, check if the
  2733 + // default has been changed, if not, check for aaData
  2734 + if ( dataSrc === 'data' ) {
  2735 + return json.aaData || json[dataSrc];
  2736 + }
  2737 +
  2738 + return dataSrc !== "" ?
  2739 + _fnGetObjectDataFn( dataSrc )( json ) :
  2740 + json;
  2741 + }
  2742 +
  2743 + /**
  2744 + * Generate the node required for filtering text
  2745 + * @returns {node} Filter control element
  2746 + * @param {object} oSettings dataTables settings object
  2747 + * @memberof DataTable#oApi
  2748 + */
  2749 + function _fnFeatureHtmlFilter ( settings )
  2750 + {
  2751 + var classes = settings.oClasses;
  2752 + var tableId = settings.sTableId;
  2753 + var language = settings.oLanguage;
  2754 + var previousSearch = settings.oPreviousSearch;
  2755 + var features = settings.aanFeatures;
  2756 + var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
  2757 +
  2758 + var str = language.sSearch;
  2759 + str = str.match(/_INPUT_/) ?
  2760 + str.replace('_INPUT_', input) :
  2761 + str+input;
  2762 +
  2763 + var filter = $('<div/>', {
  2764 + 'id': ! features.f ? tableId+'_filter' : null,
  2765 + 'class': classes.sFilter
  2766 + } )
  2767 + .append( $('<label/>' ).append( str ) );
  2768 +
  2769 + var searchFn = function() {
  2770 + /* Update all other filter input elements for the new display */
  2771 + var n = features.f;
  2772 + var val = !this.value ? "" : this.value; // mental IE8 fix :-(
  2773 +
  2774 + /* Now do the filter */
  2775 + if ( val != previousSearch.sSearch ) {
  2776 + _fnFilterComplete( settings, {
  2777 + "sSearch": val,
  2778 + "bRegex": previousSearch.bRegex,
  2779 + "bSmart": previousSearch.bSmart ,
  2780 + "bCaseInsensitive": previousSearch.bCaseInsensitive
  2781 + } );
  2782 +
  2783 + // Need to redraw, without resorting
  2784 + settings._iDisplayStart = 0;
  2785 + _fnDraw( settings );
  2786 + }
  2787 + };
  2788 +
  2789 + var searchDelay = settings.searchDelay !== null ?
  2790 + settings.searchDelay :
  2791 + _fnDataSource( settings ) === 'ssp' ?
  2792 + 400 :
  2793 + 0;
  2794 +
  2795 + var jqFilter = $('input', filter)
  2796 + .val( previousSearch.sSearch )
  2797 + .attr( 'placeholder', language.sSearchPlaceholder )
  2798 + .bind(
  2799 + 'keyup.DT search.DT input.DT paste.DT cut.DT',
  2800 + searchDelay ?
  2801 + _fnThrottle( searchFn, searchDelay ) :
  2802 + searchFn
  2803 + )
  2804 + .bind( 'keypress.DT', function(e) {
  2805 + /* Prevent form submission */
  2806 + if ( e.keyCode == 13 ) {
  2807 + return false;
  2808 + }
  2809 + } )
  2810 + .attr('aria-controls', tableId);
  2811 +
  2812 + // Update the input elements whenever the table is filtered
  2813 + $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
  2814 + if ( settings === s ) {
  2815 + // IE9 throws an 'unknown error' if document.activeElement is used
  2816 + // inside an iframe or frame...
  2817 + try {
  2818 + if ( jqFilter[0] !== document.activeElement ) {
  2819 + jqFilter.val( previousSearch.sSearch );
  2820 + }
  2821 + }
  2822 + catch ( e ) {}
  2823 + }
  2824 + } );
  2825 +
  2826 + return filter[0];
  2827 + }
  2828 +
  2829 +
  2830 + /**
  2831 + * Filter the table using both the global filter and column based filtering
  2832 + * @param {object} oSettings dataTables settings object
  2833 + * @param {object} oSearch search information
  2834 + * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
  2835 + * @memberof DataTable#oApi
  2836 + */
  2837 + function _fnFilterComplete ( oSettings, oInput, iForce )
  2838 + {
  2839 + var oPrevSearch = oSettings.oPreviousSearch;
  2840 + var aoPrevSearch = oSettings.aoPreSearchCols;
  2841 + var fnSaveFilter = function ( oFilter ) {
  2842 + /* Save the filtering values */
  2843 + oPrevSearch.sSearch = oFilter.sSearch;
  2844 + oPrevSearch.bRegex = oFilter.bRegex;
  2845 + oPrevSearch.bSmart = oFilter.bSmart;
  2846 + oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
  2847 + };
  2848 + var fnRegex = function ( o ) {
  2849 + // Backwards compatibility with the bEscapeRegex option
  2850 + return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
  2851 + };
  2852 +
  2853 + // Resolve any column types that are unknown due to addition or invalidation
  2854 + // @todo As per sort - can this be moved into an event handler?
  2855 + _fnColumnTypes( oSettings );
  2856 +
  2857 + /* In server-side processing all filtering is done by the server, so no point hanging around here */
  2858 + if ( _fnDataSource( oSettings ) != 'ssp' )
  2859 + {
  2860 + /* Global filter */
  2861 + _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
  2862 + fnSaveFilter( oInput );
  2863 +
  2864 + /* Now do the individual column filter */
  2865 + for ( var i=0 ; i<aoPrevSearch.length ; i++ )
  2866 + {
  2867 + _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
  2868 + aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
  2869 + }
  2870 +
  2871 + /* Custom filtering */
  2872 + _fnFilterCustom( oSettings );
  2873 + }
  2874 + else
  2875 + {
  2876 + fnSaveFilter( oInput );
  2877 + }
  2878 +
  2879 + /* Tell the draw function we have been filtering */
  2880 + oSettings.bFiltered = true;
  2881 + _fnCallbackFire( oSettings, null, 'search', [oSettings] );
  2882 + }
  2883 +
  2884 +
  2885 + /**
  2886 + * Apply custom filtering functions
  2887 + * @param {object} oSettings dataTables settings object
  2888 + * @memberof DataTable#oApi
  2889 + */
  2890 + function _fnFilterCustom( settings )
  2891 + {
  2892 + var filters = DataTable.ext.search;
  2893 + var displayRows = settings.aiDisplay;
  2894 + var row, rowIdx;
  2895 +
  2896 + for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
  2897 + var rows = [];
  2898 +
  2899 + // Loop over each row and see if it should be included
  2900 + for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
  2901 + rowIdx = displayRows[ j ];
  2902 + row = settings.aoData[ rowIdx ];
  2903 +
  2904 + if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
  2905 + rows.push( rowIdx );
  2906 + }
  2907 + }
  2908 +
  2909 + // So the array reference doesn't break set the results into the
  2910 + // existing array
  2911 + displayRows.length = 0;
  2912 + displayRows.push.apply( displayRows, rows );
  2913 + }
  2914 + }
  2915 +
  2916 +
  2917 + /**
  2918 + * Filter the table on a per-column basis
  2919 + * @param {object} oSettings dataTables settings object
  2920 + * @param {string} sInput string to filter on
  2921 + * @param {int} iColumn column to filter
  2922 + * @param {bool} bRegex treat search string as a regular expression or not
  2923 + * @param {bool} bSmart use smart filtering or not
  2924 + * @param {bool} bCaseInsensitive Do case insenstive matching or not
  2925 + * @memberof DataTable#oApi
  2926 + */
  2927 + function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
  2928 + {
  2929 + if ( searchStr === '' ) {
  2930 + return;
  2931 + }
  2932 +
  2933 + var data;
  2934 + var display = settings.aiDisplay;
  2935 + var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
  2936 +
  2937 + for ( var i=display.length-1 ; i>=0 ; i-- ) {
  2938 + data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
  2939 +
  2940 + if ( ! rpSearch.test( data ) ) {
  2941 + display.splice( i, 1 );
  2942 + }
  2943 + }
  2944 + }
  2945 +
  2946 +
  2947 + /**
  2948 + * Filter the data table based on user input and draw the table
  2949 + * @param {object} settings dataTables settings object
  2950 + * @param {string} input string to filter on
  2951 + * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
  2952 + * @param {bool} regex treat as a regular expression or not
  2953 + * @param {bool} smart perform smart filtering or not
  2954 + * @param {bool} caseInsensitive Do case insenstive matching or not
  2955 + * @memberof DataTable#oApi
  2956 + */
  2957 + function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
  2958 + {
  2959 + var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
  2960 + var prevSearch = settings.oPreviousSearch.sSearch;
  2961 + var displayMaster = settings.aiDisplayMaster;
  2962 + var display, invalidated, i;
  2963 +
  2964 + // Need to take account of custom filtering functions - always filter
  2965 + if ( DataTable.ext.search.length !== 0 ) {
  2966 + force = true;
  2967 + }
  2968 +
  2969 + // Check if any of the rows were invalidated
  2970 + invalidated = _fnFilterData( settings );
  2971 +
  2972 + // If the input is blank - we just want the full data set
  2973 + if ( input.length <= 0 ) {
  2974 + settings.aiDisplay = displayMaster.slice();
  2975 + }
  2976 + else {
  2977 + // New search - start from the master array
  2978 + if ( invalidated ||
  2979 + force ||
  2980 + prevSearch.length > input.length ||
  2981 + input.indexOf(prevSearch) !== 0 ||
  2982 + settings.bSorted // On resort, the display master needs to be
  2983 + // re-filtered since indexes will have changed
  2984 + ) {
  2985 + settings.aiDisplay = displayMaster.slice();
  2986 + }
  2987 +
  2988 + // Search the display array
  2989 + display = settings.aiDisplay;
  2990 +
  2991 + for ( i=display.length-1 ; i>=0 ; i-- ) {
  2992 + if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
  2993 + display.splice( i, 1 );
  2994 + }
  2995 + }
  2996 + }
  2997 + }
  2998 +
  2999 +
  3000 + /**
  3001 + * Build a regular expression object suitable for searching a table
  3002 + * @param {string} sSearch string to search for
  3003 + * @param {bool} bRegex treat as a regular expression or not
  3004 + * @param {bool} bSmart perform smart filtering or not
  3005 + * @param {bool} bCaseInsensitive Do case insensitive matching or not
  3006 + * @returns {RegExp} constructed object
  3007 + * @memberof DataTable#oApi
  3008 + */
  3009 + function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
  3010 + {
  3011 + search = regex ?
  3012 + search :
  3013 + _fnEscapeRegex( search );
  3014 +
  3015 + if ( smart ) {
  3016 + /* For smart filtering we want to allow the search to work regardless of
  3017 + * word order. We also want double quoted text to be preserved, so word
  3018 + * order is important - a la google. So this is what we want to
  3019 + * generate:
  3020 + *
  3021 + * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
  3022 + */
  3023 + var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
  3024 + if ( word.charAt(0) === '"' ) {
  3025 + var m = word.match( /^"(.*)"$/ );
  3026 + word = m ? m[1] : word;
  3027 + }
  3028 +
  3029 + return word.replace('"', '');
  3030 + } );
  3031 +
  3032 + search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
  3033 + }
  3034 +
  3035 + return new RegExp( search, caseInsensitive ? 'i' : '' );
  3036 + }
  3037 +
  3038 +
  3039 + /**
  3040 + * Escape a string such that it can be used in a regular expression
  3041 + * @param {string} sVal string to escape
  3042 + * @returns {string} escaped string
  3043 + * @memberof DataTable#oApi
  3044 + */
  3045 + function _fnEscapeRegex ( sVal )
  3046 + {
  3047 + return sVal.replace( _re_escape_regex, '\\$1' );
  3048 + }
  3049 +
  3050 +
  3051 +
  3052 + var __filter_div = $('<div>')[0];
  3053 + var __filter_div_textContent = __filter_div.textContent !== undefined;
  3054 +
  3055 + // Update the filtering data for each row if needed (by invalidation or first run)
  3056 + function _fnFilterData ( settings )
  3057 + {
  3058 + var columns = settings.aoColumns;
  3059 + var column;
  3060 + var i, j, ien, jen, filterData, cellData, row;
  3061 + var fomatters = DataTable.ext.type.search;
  3062 + var wasInvalidated = false;
  3063 +
  3064 + for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  3065 + row = settings.aoData[i];
  3066 +
  3067 + if ( ! row._aFilterData ) {
  3068 + filterData = [];
  3069 +
  3070 + for ( j=0, jen=columns.length ; j<jen ; j++ ) {
  3071 + column = columns[j];
  3072 +
  3073 + if ( column.bSearchable ) {
  3074 + cellData = _fnGetCellData( settings, i, j, 'filter' );
  3075 +
  3076 + if ( fomatters[ column.sType ] ) {
  3077 + cellData = fomatters[ column.sType ]( cellData );
  3078 + }
  3079 +
  3080 + // Search in DataTables 1.10 is string based. In 1.11 this
  3081 + // should be altered to also allow strict type checking.
  3082 + if ( cellData === null ) {
  3083 + cellData = '';
  3084 + }
  3085 +
  3086 + if ( typeof cellData !== 'string' && cellData.toString ) {
  3087 + cellData = cellData.toString();
  3088 + }
  3089 + }
  3090 + else {
  3091 + cellData = '';
  3092 + }
  3093 +
  3094 + // If it looks like there is an HTML entity in the string,
  3095 + // attempt to decode it so sorting works as expected. Note that
  3096 + // we could use a single line of jQuery to do this, but the DOM
  3097 + // method used here is much faster http://jsperf.com/html-decode
  3098 + if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
  3099 + __filter_div.innerHTML = cellData;
  3100 + cellData = __filter_div_textContent ?
  3101 + __filter_div.textContent :
  3102 + __filter_div.innerText;
  3103 + }
  3104 +
  3105 + if ( cellData.replace ) {
  3106 + cellData = cellData.replace(/[\r\n]/g, '');
  3107 + }
  3108 +
  3109 + filterData.push( cellData );
  3110 + }
  3111 +
  3112 + row._aFilterData = filterData;
  3113 + row._sFilterRow = filterData.join(' ');
  3114 + wasInvalidated = true;
  3115 + }
  3116 + }
  3117 +
  3118 + return wasInvalidated;
  3119 + }
  3120 +
  3121 +
  3122 + /**
  3123 + * Convert from the internal Hungarian notation to camelCase for external
  3124 + * interaction
  3125 + * @param {object} obj Object to convert
  3126 + * @returns {object} Inverted object
  3127 + * @memberof DataTable#oApi
  3128 + */
  3129 + function _fnSearchToCamel ( obj )
  3130 + {
  3131 + return {
  3132 + search: obj.sSearch,
  3133 + smart: obj.bSmart,
  3134 + regex: obj.bRegex,
  3135 + caseInsensitive: obj.bCaseInsensitive
  3136 + };
  3137 + }
  3138 +
  3139 +
  3140 +
  3141 + /**
  3142 + * Convert from camelCase notation to the internal Hungarian. We could use the
  3143 + * Hungarian convert function here, but this is cleaner
  3144 + * @param {object} obj Object to convert
  3145 + * @returns {object} Inverted object
  3146 + * @memberof DataTable#oApi
  3147 + */
  3148 + function _fnSearchToHung ( obj )
  3149 + {
  3150 + return {
  3151 + sSearch: obj.search,
  3152 + bSmart: obj.smart,
  3153 + bRegex: obj.regex,
  3154 + bCaseInsensitive: obj.caseInsensitive
  3155 + };
  3156 + }
  3157 +
  3158 + /**
  3159 + * Generate the node required for the info display
  3160 + * @param {object} oSettings dataTables settings object
  3161 + * @returns {node} Information element
  3162 + * @memberof DataTable#oApi
  3163 + */
  3164 + function _fnFeatureHtmlInfo ( settings )
  3165 + {
  3166 + var
  3167 + tid = settings.sTableId,
  3168 + nodes = settings.aanFeatures.i,
  3169 + n = $('<div/>', {
  3170 + 'class': settings.oClasses.sInfo,
  3171 + 'id': ! nodes ? tid+'_info' : null
  3172 + } );
  3173 +
  3174 + if ( ! nodes ) {
  3175 + // Update display on each draw
  3176 + settings.aoDrawCallback.push( {
  3177 + "fn": _fnUpdateInfo,
  3178 + "sName": "information"
  3179 + } );
  3180 +
  3181 + n
  3182 + .attr( 'role', 'status' )
  3183 + .attr( 'aria-live', 'polite' );
  3184 +
  3185 + // Table is described by our info div
  3186 + $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
  3187 + }
  3188 +
  3189 + return n[0];
  3190 + }
  3191 +
  3192 +
  3193 + /**
  3194 + * Update the information elements in the display
  3195 + * @param {object} settings dataTables settings object
  3196 + * @memberof DataTable#oApi
  3197 + */
  3198 + function _fnUpdateInfo ( settings )
  3199 + {
  3200 + /* Show information about the table */
  3201 + var nodes = settings.aanFeatures.i;
  3202 + if ( nodes.length === 0 ) {
  3203 + return;
  3204 + }
  3205 +
  3206 + var
  3207 + lang = settings.oLanguage,
  3208 + start = settings._iDisplayStart+1,
  3209 + end = settings.fnDisplayEnd(),
  3210 + max = settings.fnRecordsTotal(),
  3211 + total = settings.fnRecordsDisplay(),
  3212 + out = total ?
  3213 + lang.sInfo :
  3214 + lang.sInfoEmpty;
  3215 +
  3216 + if ( total !== max ) {
  3217 + /* Record set after filtering */
  3218 + out += ' ' + lang.sInfoFiltered;
  3219 + }
  3220 +
  3221 + // Convert the macros
  3222 + out += lang.sInfoPostFix;
  3223 + out = _fnInfoMacros( settings, out );
  3224 +
  3225 + var callback = lang.fnInfoCallback;
  3226 + if ( callback !== null ) {
  3227 + out = callback.call( settings.oInstance,
  3228 + settings, start, end, max, total, out
  3229 + );
  3230 + }
  3231 +
  3232 + $(nodes).html( out );
  3233 + }
  3234 +
  3235 +
  3236 + function _fnInfoMacros ( settings, str )
  3237 + {
  3238 + // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
  3239 + // internally
  3240 + var
  3241 + formatter = settings.fnFormatNumber,
  3242 + start = settings._iDisplayStart+1,
  3243 + len = settings._iDisplayLength,
  3244 + vis = settings.fnRecordsDisplay(),
  3245 + all = len === -1;
  3246 +
  3247 + return str.
  3248 + replace(/_START_/g, formatter.call( settings, start ) ).
  3249 + replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).
  3250 + replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).
  3251 + replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
  3252 + replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
  3253 + replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
  3254 + }
  3255 +
  3256 +
  3257 +
  3258 + /**
  3259 + * Draw the table for the first time, adding all required features
  3260 + * @param {object} settings dataTables settings object
  3261 + * @memberof DataTable#oApi
  3262 + */
  3263 + function _fnInitialise ( settings )
  3264 + {
  3265 + var i, iLen, iAjaxStart=settings.iInitDisplayStart;
  3266 + var columns = settings.aoColumns, column;
  3267 + var features = settings.oFeatures;
  3268 +
  3269 + /* Ensure that the table data is fully initialised */
  3270 + if ( ! settings.bInitialised ) {
  3271 + setTimeout( function(){ _fnInitialise( settings ); }, 200 );
  3272 + return;
  3273 + }
  3274 +
  3275 + /* Show the display HTML options */
  3276 + _fnAddOptionsHtml( settings );
  3277 +
  3278 + /* Build and draw the header / footer for the table */
  3279 + _fnBuildHead( settings );
  3280 + _fnDrawHead( settings, settings.aoHeader );
  3281 + _fnDrawHead( settings, settings.aoFooter );
  3282 +
  3283 + /* Okay to show that something is going on now */
  3284 + _fnProcessingDisplay( settings, true );
  3285 +
  3286 + /* Calculate sizes for columns */
  3287 + if ( features.bAutoWidth ) {
  3288 + _fnCalculateColumnWidths( settings );
  3289 + }
  3290 +
  3291 + for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
  3292 + column = columns[i];
  3293 +
  3294 + if ( column.sWidth ) {
  3295 + column.nTh.style.width = _fnStringToCss( column.sWidth );
  3296 + }
  3297 + }
  3298 +
  3299 + // If there is default sorting required - let's do it. The sort function
  3300 + // will do the drawing for us. Otherwise we draw the table regardless of the
  3301 + // Ajax source - this allows the table to look initialised for Ajax sourcing
  3302 + // data (show 'loading' message possibly)
  3303 + _fnReDraw( settings );
  3304 +
  3305 + // Server-side processing init complete is done by _fnAjaxUpdateDraw
  3306 + var dataSrc = _fnDataSource( settings );
  3307 + if ( dataSrc != 'ssp' ) {
  3308 + // if there is an ajax source load the data
  3309 + if ( dataSrc == 'ajax' ) {
  3310 + _fnBuildAjax( settings, [], function(json) {
  3311 + var aData = _fnAjaxDataSrc( settings, json );
  3312 +
  3313 + // Got the data - add it to the table
  3314 + for ( i=0 ; i<aData.length ; i++ ) {
  3315 + _fnAddData( settings, aData[i] );
  3316 + }
  3317 +
  3318 + // Reset the init display for cookie saving. We've already done
  3319 + // a filter, and therefore cleared it before. So we need to make
  3320 + // it appear 'fresh'
  3321 + settings.iInitDisplayStart = iAjaxStart;
  3322 +
  3323 + _fnReDraw( settings );
  3324 +
  3325 + _fnProcessingDisplay( settings, false );
  3326 + _fnInitComplete( settings, json );
  3327 + }, settings );
  3328 + }
  3329 + else {
  3330 + _fnProcessingDisplay( settings, false );
  3331 + _fnInitComplete( settings );
  3332 + }
  3333 + }
  3334 + }
  3335 +
  3336 +
  3337 + /**
  3338 + * Draw the table for the first time, adding all required features
  3339 + * @param {object} oSettings dataTables settings object
  3340 + * @param {object} [json] JSON from the server that completed the table, if using Ajax source
  3341 + * with client-side processing (optional)
  3342 + * @memberof DataTable#oApi
  3343 + */
  3344 + function _fnInitComplete ( settings, json )
  3345 + {
  3346 + settings._bInitComplete = true;
  3347 +
  3348 + // On an Ajax load we now have data and therefore want to apply the column
  3349 + // sizing
  3350 + if ( json ) {
  3351 + _fnAdjustColumnSizing( settings );
  3352 + }
  3353 +
  3354 + _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
  3355 + }
  3356 +
  3357 +
  3358 + function _fnLengthChange ( settings, val )
  3359 + {
  3360 + var len = parseInt( val, 10 );
  3361 + settings._iDisplayLength = len;
  3362 +
  3363 + _fnLengthOverflow( settings );
  3364 +
  3365 + // Fire length change event
  3366 + _fnCallbackFire( settings, null, 'length', [settings, len] );
  3367 + }
  3368 +
  3369 +
  3370 + /**
  3371 + * Generate the node required for user display length changing
  3372 + * @param {object} settings dataTables settings object
  3373 + * @returns {node} Display length feature node
  3374 + * @memberof DataTable#oApi
  3375 + */
  3376 + function _fnFeatureHtmlLength ( settings )
  3377 + {
  3378 + var
  3379 + classes = settings.oClasses,
  3380 + tableId = settings.sTableId,
  3381 + menu = settings.aLengthMenu,
  3382 + d2 = $.isArray( menu[0] ),
  3383 + lengths = d2 ? menu[0] : menu,
  3384 + language = d2 ? menu[1] : menu;
  3385 +
  3386 + var select = $('<select/>', {
  3387 + 'name': tableId+'_length',
  3388 + 'aria-controls': tableId,
  3389 + 'class': classes.sLengthSelect
  3390 + } );
  3391 +
  3392 + for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
  3393 + select[0][ i ] = new Option( language[i], lengths[i] );
  3394 + }
  3395 +
  3396 + var div = $('<div><label/></div>').addClass( classes.sLength );
  3397 + if ( ! settings.aanFeatures.l ) {
  3398 + div[0].id = tableId+'_length';
  3399 + }
  3400 +
  3401 + div.children().append(
  3402 + settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
  3403 + );
  3404 +
  3405 + // Can't use `select` variable as user might provide their own and the
  3406 + // reference is broken by the use of outerHTML
  3407 + $('select', div)
  3408 + .val( settings._iDisplayLength )
  3409 + .bind( 'change.DT', function(e) {
  3410 + _fnLengthChange( settings, $(this).val() );
  3411 + _fnDraw( settings );
  3412 + } );
  3413 +
  3414 + // Update node value whenever anything changes the table's length
  3415 + $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
  3416 + if ( settings === s ) {
  3417 + $('select', div).val( len );
  3418 + }
  3419 + } );
  3420 +
  3421 + return div[0];
  3422 + }
  3423 +
  3424 +
  3425 +
  3426 + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  3427 + * Note that most of the paging logic is done in
  3428 + * DataTable.ext.pager
  3429 + */
  3430 +
  3431 + /**
  3432 + * Generate the node required for default pagination
  3433 + * @param {object} oSettings dataTables settings object
  3434 + * @returns {node} Pagination feature node
  3435 + * @memberof DataTable#oApi
  3436 + */
  3437 + function _fnFeatureHtmlPaginate ( settings )
  3438 + {
  3439 + var
  3440 + type = settings.sPaginationType,
  3441 + plugin = DataTable.ext.pager[ type ],
  3442 + modern = typeof plugin === 'function',
  3443 + redraw = function( settings ) {
  3444 + _fnDraw( settings );
  3445 + },
  3446 + node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
  3447 + features = settings.aanFeatures;
  3448 +
  3449 + if ( ! modern ) {
  3450 + plugin.fnInit( settings, node, redraw );
  3451 + }
  3452 +
  3453 + /* Add a draw callback for the pagination on first instance, to update the paging display */
  3454 + if ( ! features.p )
  3455 + {
  3456 + node.id = settings.sTableId+'_paginate';
  3457 +
  3458 + settings.aoDrawCallback.push( {
  3459 + "fn": function( settings ) {
  3460 + if ( modern ) {
  3461 + var
  3462 + start = settings._iDisplayStart,
  3463 + len = settings._iDisplayLength,
  3464 + visRecords = settings.fnRecordsDisplay(),
  3465 + all = len === -1,
  3466 + page = all ? 0 : Math.ceil( start / len ),
  3467 + pages = all ? 1 : Math.ceil( visRecords / len ),
  3468 + buttons = plugin(page, pages),
  3469 + i, ien;
  3470 +
  3471 + for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
  3472 + _fnRenderer( settings, 'pageButton' )(
  3473 + settings, features.p[i], i, buttons, page, pages
  3474 + );
  3475 + }
  3476 + }
  3477 + else {
  3478 + plugin.fnUpdate( settings, redraw );
  3479 + }
  3480 + },
  3481 + "sName": "pagination"
  3482 + } );
  3483 + }
  3484 +
  3485 + return node;
  3486 + }
  3487 +
  3488 +
  3489 + /**
  3490 + * Alter the display settings to change the page
  3491 + * @param {object} settings DataTables settings object
  3492 + * @param {string|int} action Paging action to take: "first", "previous",
  3493 + * "next" or "last" or page number to jump to (integer)
  3494 + * @param [bool] redraw Automatically draw the update or not
  3495 + * @returns {bool} true page has changed, false - no change
  3496 + * @memberof DataTable#oApi
  3497 + */
  3498 + function _fnPageChange ( settings, action, redraw )
  3499 + {
  3500 + var
  3501 + start = settings._iDisplayStart,
  3502 + len = settings._iDisplayLength,
  3503 + records = settings.fnRecordsDisplay();
  3504 +
  3505 + if ( records === 0 || len === -1 )
  3506 + {
  3507 + start = 0;
  3508 + }
  3509 + else if ( typeof action === "number" )
  3510 + {
  3511 + start = action * len;
  3512 +
  3513 + if ( start > records )
  3514 + {
  3515 + start = 0;
  3516 + }
  3517 + }
  3518 + else if ( action == "first" )
  3519 + {
  3520 + start = 0;
  3521 + }
  3522 + else if ( action == "previous" )
  3523 + {
  3524 + start = len >= 0 ?
  3525 + start - len :
  3526 + 0;
  3527 +
  3528 + if ( start < 0 )
  3529 + {
  3530 + start = 0;
  3531 + }
  3532 + }
  3533 + else if ( action == "next" )
  3534 + {
  3535 + if ( start + len < records )
  3536 + {
  3537 + start += len;
  3538 + }
  3539 + }
  3540 + else if ( action == "last" )
  3541 + {
  3542 + start = Math.floor( (records-1) / len) * len;
  3543 + }
  3544 + else
  3545 + {
  3546 + _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
  3547 + }
  3548 +
  3549 + var changed = settings._iDisplayStart !== start;
  3550 + settings._iDisplayStart = start;
  3551 +
  3552 + if ( changed ) {
  3553 + _fnCallbackFire( settings, null, 'page', [settings] );
  3554 +
  3555 + if ( redraw ) {
  3556 + _fnDraw( settings );
  3557 + }
  3558 + }
  3559 +
  3560 + return changed;
  3561 + }
  3562 +
  3563 +
  3564 +
  3565 + /**
  3566 + * Generate the node required for the processing node
  3567 + * @param {object} settings dataTables settings object
  3568 + * @returns {node} Processing element
  3569 + * @memberof DataTable#oApi
  3570 + */
  3571 + function _fnFeatureHtmlProcessing ( settings )
  3572 + {
  3573 + return $('<div/>', {
  3574 + 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
  3575 + 'class': settings.oClasses.sProcessing
  3576 + } )
  3577 + .html( settings.oLanguage.sProcessing )
  3578 + .insertBefore( settings.nTable )[0];
  3579 + }
  3580 +
  3581 +
  3582 + /**
  3583 + * Display or hide the processing indicator
  3584 + * @param {object} settings dataTables settings object
  3585 + * @param {bool} show Show the processing indicator (true) or not (false)
  3586 + * @memberof DataTable#oApi
  3587 + */
  3588 + function _fnProcessingDisplay ( settings, show )
  3589 + {
  3590 + if ( settings.oFeatures.bProcessing ) {
  3591 + $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
  3592 + }
  3593 +
  3594 + _fnCallbackFire( settings, null, 'processing', [settings, show] );
  3595 + }
  3596 +
  3597 + /**
  3598 + * Add any control elements for the table - specifically scrolling
  3599 + * @param {object} settings dataTables settings object
  3600 + * @returns {node} Node to add to the DOM
  3601 + * @memberof DataTable#oApi
  3602 + */
  3603 + function _fnFeatureHtmlTable ( settings )
  3604 + {
  3605 + var table = $(settings.nTable);
  3606 +
  3607 + // Add the ARIA grid role to the table
  3608 + table.attr( 'role', 'grid' );
  3609 +
  3610 + // Scrolling from here on in
  3611 + var scroll = settings.oScroll;
  3612 +
  3613 + if ( scroll.sX === '' && scroll.sY === '' ) {
  3614 + return settings.nTable;
  3615 + }
  3616 +
  3617 + var scrollX = scroll.sX;
  3618 + var scrollY = scroll.sY;
  3619 + var classes = settings.oClasses;
  3620 + var caption = table.children('caption');
  3621 + var captionSide = caption.length ? caption[0]._captionSide : null;
  3622 + var headerClone = $( table[0].cloneNode(false) );
  3623 + var footerClone = $( table[0].cloneNode(false) );
  3624 + var footer = table.children('tfoot');
  3625 + var _div = '<div/>';
  3626 + var size = function ( s ) {
  3627 + return !s ? null : _fnStringToCss( s );
  3628 + };
  3629 +
  3630 + // This is fairly messy, but with x scrolling enabled, if the table has a
  3631 + // width attribute, regardless of any width applied using the column width
  3632 + // options, the browser will shrink or grow the table as needed to fit into
  3633 + // that 100%. That would make the width options useless. So we remove it.
  3634 + // This is okay, under the assumption that width:100% is applied to the
  3635 + // table in CSS (it is in the default stylesheet) which will set the table
  3636 + // width as appropriate (the attribute and css behave differently...)
  3637 + if ( scroll.sX && table.attr('width') === '100%' ) {
  3638 + table.removeAttr('width');
  3639 + }
  3640 +
  3641 + if ( ! footer.length ) {
  3642 + footer = null;
  3643 + }
  3644 +
  3645 + /*
  3646 + * The HTML structure that we want to generate in this function is:
  3647 + * div - scroller
  3648 + * div - scroll head
  3649 + * div - scroll head inner
  3650 + * table - scroll head table
  3651 + * thead - thead
  3652 + * div - scroll body
  3653 + * table - table (master table)
  3654 + * thead - thead clone for sizing
  3655 + * tbody - tbody
  3656 + * div - scroll foot
  3657 + * div - scroll foot inner
  3658 + * table - scroll foot table
  3659 + * tfoot - tfoot
  3660 + */
  3661 + var scroller = $( _div, { 'class': classes.sScrollWrapper } )
  3662 + .append(
  3663 + $(_div, { 'class': classes.sScrollHead } )
  3664 + .css( {
  3665 + overflow: 'hidden',
  3666 + position: 'relative',
  3667 + border: 0,
  3668 + width: scrollX ? size(scrollX) : '100%'
  3669 + } )
  3670 + .append(
  3671 + $(_div, { 'class': classes.sScrollHeadInner } )
  3672 + .css( {
  3673 + 'box-sizing': 'content-box',
  3674 + width: scroll.sXInner || '100%'
  3675 + } )
  3676 + .append(
  3677 + headerClone
  3678 + .removeAttr('id')
  3679 + .css( 'margin-left', 0 )
  3680 + .append( captionSide === 'top' ? caption : null )
  3681 + .append(
  3682 + table.children('thead')
  3683 + )
  3684 + )
  3685 + )
  3686 + )
  3687 + .append(
  3688 + $(_div, { 'class': classes.sScrollBody } )
  3689 + .css( {
  3690 + overflow: 'auto',
  3691 + height: size( scrollY ),
  3692 + width: size( scrollX )
  3693 + } )
  3694 + .append( table )
  3695 + );
  3696 +
  3697 + if ( footer ) {
  3698 + scroller.append(
  3699 + $(_div, { 'class': classes.sScrollFoot } )
  3700 + .css( {
  3701 + overflow: 'hidden',
  3702 + border: 0,
  3703 + width: scrollX ? size(scrollX) : '100%'
  3704 + } )
  3705 + .append(
  3706 + $(_div, { 'class': classes.sScrollFootInner } )
  3707 + .append(
  3708 + footerClone
  3709 + .removeAttr('id')
  3710 + .css( 'margin-left', 0 )
  3711 + .append( captionSide === 'bottom' ? caption : null )
  3712 + .append(
  3713 + table.children('tfoot')
  3714 + )
  3715 + )
  3716 + )
  3717 + );
  3718 + }
  3719 +
  3720 + var children = scroller.children();
  3721 + var scrollHead = children[0];
  3722 + var scrollBody = children[1];
  3723 + var scrollFoot = footer ? children[2] : null;
  3724 +
  3725 + // When the body is scrolled, then we also want to scroll the headers
  3726 + if ( scrollX ) {
  3727 + $(scrollBody).on( 'scroll.DT', function (e) {
  3728 + var scrollLeft = this.scrollLeft;
  3729 +
  3730 + scrollHead.scrollLeft = scrollLeft;
  3731 +
  3732 + if ( footer ) {
  3733 + scrollFoot.scrollLeft = scrollLeft;
  3734 + }
  3735 + } );
  3736 + }
  3737 +
  3738 + settings.nScrollHead = scrollHead;
  3739 + settings.nScrollBody = scrollBody;
  3740 + settings.nScrollFoot = scrollFoot;
  3741 +
  3742 + // On redraw - align columns
  3743 + settings.aoDrawCallback.push( {
  3744 + "fn": _fnScrollDraw,
  3745 + "sName": "scrolling"
  3746 + } );
  3747 +
  3748 + return scroller[0];
  3749 + }
  3750 +
  3751 +
  3752 +
  3753 + /**
  3754 + * Update the header, footer and body tables for resizing - i.e. column
  3755 + * alignment.
  3756 + *
  3757 + * Welcome to the most horrible function DataTables. The process that this
  3758 + * function follows is basically:
  3759 + * 1. Re-create the table inside the scrolling div
  3760 + * 2. Take live measurements from the DOM
  3761 + * 3. Apply the measurements to align the columns
  3762 + * 4. Clean up
  3763 + *
  3764 + * @param {object} settings dataTables settings object
  3765 + * @memberof DataTable#oApi
  3766 + */
  3767 + function _fnScrollDraw ( settings )
  3768 + {
  3769 + // Given that this is such a monster function, a lot of variables are use
  3770 + // to try and keep the minimised size as small as possible
  3771 + var
  3772 + scroll = settings.oScroll,
  3773 + scrollX = scroll.sX,
  3774 + scrollXInner = scroll.sXInner,
  3775 + scrollY = scroll.sY,
  3776 + barWidth = scroll.iBarWidth,
  3777 + divHeader = $(settings.nScrollHead),
  3778 + divHeaderStyle = divHeader[0].style,
  3779 + divHeaderInner = divHeader.children('div'),
  3780 + divHeaderInnerStyle = divHeaderInner[0].style,
  3781 + divHeaderTable = divHeaderInner.children('table'),
  3782 + divBodyEl = settings.nScrollBody,
  3783 + divBody = $(divBodyEl),
  3784 + divBodyStyle = divBodyEl.style,
  3785 + divFooter = $(settings.nScrollFoot),
  3786 + divFooterInner = divFooter.children('div'),
  3787 + divFooterTable = divFooterInner.children('table'),
  3788 + header = $(settings.nTHead),
  3789 + table = $(settings.nTable),
  3790 + tableEl = table[0],
  3791 + tableStyle = tableEl.style,
  3792 + footer = settings.nTFoot ? $(settings.nTFoot) : null,
  3793 + browser = settings.oBrowser,
  3794 + ie67 = browser.bScrollOversize,
  3795 + headerTrgEls, footerTrgEls,
  3796 + headerSrcEls, footerSrcEls,
  3797 + headerCopy, footerCopy,
  3798 + headerWidths=[], footerWidths=[],
  3799 + headerContent=[],
  3800 + idx, correction, sanityWidth,
  3801 + zeroOut = function(nSizer) {
  3802 + var style = nSizer.style;
  3803 + style.paddingTop = "0";
  3804 + style.paddingBottom = "0";
  3805 + style.borderTopWidth = "0";
  3806 + style.borderBottomWidth = "0";
  3807 + style.height = 0;
  3808 + };
  3809 +
  3810 + /*
  3811 + * 1. Re-create the table inside the scrolling div
  3812 + */
  3813 +
  3814 + // Remove the old minimised thead and tfoot elements in the inner table
  3815 + table.children('thead, tfoot').remove();
  3816 +
  3817 + // Clone the current header and footer elements and then place it into the inner table
  3818 + headerCopy = header.clone().prependTo( table );
  3819 + headerTrgEls = header.find('tr'); // original header is in its own table
  3820 + headerSrcEls = headerCopy.find('tr');
  3821 + headerCopy.find('th, td').removeAttr('tabindex');
  3822 +
  3823 + if ( footer ) {
  3824 + footerCopy = footer.clone().prependTo( table );
  3825 + footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
  3826 + footerSrcEls = footerCopy.find('tr');
  3827 + }
  3828 +
  3829 +
  3830 + /*
  3831 + * 2. Take live measurements from the DOM - do not alter the DOM itself!
  3832 + */
  3833 +
  3834 + // Remove old sizing and apply the calculated column widths
  3835 + // Get the unique column headers in the newly created (cloned) header. We want to apply the
  3836 + // calculated sizes to this header
  3837 + if ( ! scrollX )
  3838 + {
  3839 + divBodyStyle.width = '100%';
  3840 + divHeader[0].style.width = '100%';
  3841 + }
  3842 +
  3843 + $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
  3844 + idx = _fnVisibleToColumnIndex( settings, i );
  3845 + el.style.width = settings.aoColumns[idx].sWidth;
  3846 + } );
  3847 +
  3848 + if ( footer ) {
  3849 + _fnApplyToChildren( function(n) {
  3850 + n.style.width = "";
  3851 + }, footerSrcEls );
  3852 + }
  3853 +
  3854 + // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
  3855 + // will end up forcing the scrollbar to appear, making our measurements wrong for when we
  3856 + // then hide it (end of this function), so add the header height to the body scroller.
  3857 + if ( scroll.bCollapse && scrollY !== "" ) {
  3858 + divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
  3859 + }
  3860 +
  3861 + // Size the table as a whole
  3862 + sanityWidth = table.outerWidth();
  3863 + if ( scrollX === "" ) {
  3864 + // No x scrolling
  3865 + tableStyle.width = "100%";
  3866 +
  3867 + // IE7 will make the width of the table when 100% include the scrollbar
  3868 + // - which is shouldn't. When there is a scrollbar we need to take this
  3869 + // into account.
  3870 + if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
  3871 + divBody.css('overflow-y') == "scroll")
  3872 + ) {
  3873 + tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
  3874 + }
  3875 + }
  3876 + else
  3877 + {
  3878 + // x scrolling
  3879 + if ( scrollXInner !== "" ) {
  3880 + // x scroll inner has been given - use it
  3881 + tableStyle.width = _fnStringToCss(scrollXInner);
  3882 + }
  3883 + else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
  3884 + // There is y-scrolling - try to take account of the y scroll bar
  3885 + tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
  3886 + if ( table.outerWidth() > sanityWidth-barWidth ) {
  3887 + // Not possible to take account of it
  3888 + tableStyle.width = _fnStringToCss( sanityWidth );
  3889 + }
  3890 + }
  3891 + else {
  3892 + // When all else fails
  3893 + tableStyle.width = _fnStringToCss( sanityWidth );
  3894 + }
  3895 + }
  3896 +
  3897 + // Recalculate the sanity width - now that we've applied the required width,
  3898 + // before it was a temporary variable. This is required because the column
  3899 + // width calculation is done before this table DOM is created.
  3900 + sanityWidth = table.outerWidth();
  3901 +
  3902 + // Hidden header should have zero height, so remove padding and borders. Then
  3903 + // set the width based on the real headers
  3904 +
  3905 + // Apply all styles in one pass
  3906 + _fnApplyToChildren( zeroOut, headerSrcEls );
  3907 +
  3908 + // Read all widths in next pass
  3909 + _fnApplyToChildren( function(nSizer) {
  3910 + headerContent.push( nSizer.innerHTML );
  3911 + headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
  3912 + }, headerSrcEls );
  3913 +
  3914 + // Apply all widths in final pass
  3915 + _fnApplyToChildren( function(nToSize, i) {
  3916 + nToSize.style.width = headerWidths[i];
  3917 + }, headerTrgEls );
  3918 +
  3919 + $(headerSrcEls).height(0);
  3920 +
  3921 + /* Same again with the footer if we have one */
  3922 + if ( footer )
  3923 + {
  3924 + _fnApplyToChildren( zeroOut, footerSrcEls );
  3925 +
  3926 + _fnApplyToChildren( function(nSizer) {
  3927 + footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
  3928 + }, footerSrcEls );
  3929 +
  3930 + _fnApplyToChildren( function(nToSize, i) {
  3931 + nToSize.style.width = footerWidths[i];
  3932 + }, footerTrgEls );
  3933 +
  3934 + $(footerSrcEls).height(0);
  3935 + }
  3936 +
  3937 +
  3938 + /*
  3939 + * 3. Apply the measurements
  3940 + */
  3941 +
  3942 + // "Hide" the header and footer that we used for the sizing. We need to keep
  3943 + // the content of the cell so that the width applied to the header and body
  3944 + // both match, but we want to hide it completely. We want to also fix their
  3945 + // width to what they currently are
  3946 + _fnApplyToChildren( function(nSizer, i) {
  3947 + nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
  3948 + nSizer.style.width = headerWidths[i];
  3949 + }, headerSrcEls );
  3950 +
  3951 + if ( footer )
  3952 + {
  3953 + _fnApplyToChildren( function(nSizer, i) {
  3954 + nSizer.innerHTML = "";
  3955 + nSizer.style.width = footerWidths[i];
  3956 + }, footerSrcEls );
  3957 + }
  3958 +
  3959 + // Sanity check that the table is of a sensible width. If not then we are going to get
  3960 + // misalignment - try to prevent this by not allowing the table to shrink below its min width
  3961 + if ( table.outerWidth() < sanityWidth )
  3962 + {
  3963 + // The min width depends upon if we have a vertical scrollbar visible or not */
  3964 + correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
  3965 + divBody.css('overflow-y') == "scroll")) ?
  3966 + sanityWidth+barWidth :
  3967 + sanityWidth;
  3968 +
  3969 + // IE6/7 are a law unto themselves...
  3970 + if ( ie67 && (divBodyEl.scrollHeight >
  3971 + divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
  3972 + ) {
  3973 + tableStyle.width = _fnStringToCss( correction-barWidth );
  3974 + }
  3975 +
  3976 + // And give the user a warning that we've stopped the table getting too small
  3977 + if ( scrollX === "" || scrollXInner !== "" ) {
  3978 + _fnLog( settings, 1, 'Possible column misalignment', 6 );
  3979 + }
  3980 + }
  3981 + else
  3982 + {
  3983 + correction = '100%';
  3984 + }
  3985 +
  3986 + // Apply to the container elements
  3987 + divBodyStyle.width = _fnStringToCss( correction );
  3988 + divHeaderStyle.width = _fnStringToCss( correction );
  3989 +
  3990 + if ( footer ) {
  3991 + settings.nScrollFoot.style.width = _fnStringToCss( correction );
  3992 + }
  3993 +
  3994 +
  3995 + /*
  3996 + * 4. Clean up
  3997 + */
  3998 + if ( ! scrollY ) {
  3999 + /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
  4000 + * the scrollbar height from the visible display, rather than adding it on. We need to
  4001 + * set the height in order to sort this. Don't want to do it in any other browsers.
  4002 + */
  4003 + if ( ie67 ) {
  4004 + divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
  4005 + }
  4006 + }
  4007 +
  4008 + if ( scrollY && scroll.bCollapse ) {
  4009 + divBodyStyle.height = _fnStringToCss( scrollY );
  4010 +
  4011 + var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
  4012 + barWidth :
  4013 + 0;
  4014 +
  4015 + if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
  4016 + divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
  4017 + }
  4018 + }
  4019 +
  4020 + /* Finally set the width's of the header and footer tables */
  4021 + var iOuterWidth = table.outerWidth();
  4022 + divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
  4023 + divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
  4024 +
  4025 + // Figure out if there are scrollbar present - if so then we need a the header and footer to
  4026 + // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
  4027 + var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
  4028 + var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
  4029 + divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
  4030 +
  4031 + if ( footer ) {
  4032 + divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
  4033 + divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
  4034 + divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
  4035 + }
  4036 +
  4037 + /* Adjust the position of the header in case we loose the y-scrollbar */
  4038 + divBody.scroll();
  4039 +
  4040 + // If sorting or filtering has occurred, jump the scrolling back to the top
  4041 + // only if we aren't holding the position
  4042 + if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
  4043 + divBodyEl.scrollTop = 0;
  4044 + }
  4045 + }
  4046 +
  4047 +
  4048 +
  4049 + /**
  4050 + * Apply a given function to the display child nodes of an element array (typically
  4051 + * TD children of TR rows
  4052 + * @param {function} fn Method to apply to the objects
  4053 + * @param array {nodes} an1 List of elements to look through for display children
  4054 + * @param array {nodes} an2 Another list (identical structure to the first) - optional
  4055 + * @memberof DataTable#oApi
  4056 + */
  4057 + function _fnApplyToChildren( fn, an1, an2 )
  4058 + {
  4059 + var index=0, i=0, iLen=an1.length;
  4060 + var nNode1, nNode2;
  4061 +
  4062 + while ( i < iLen ) {
  4063 + nNode1 = an1[i].firstChild;
  4064 + nNode2 = an2 ? an2[i].firstChild : null;
  4065 +
  4066 + while ( nNode1 ) {
  4067 + if ( nNode1.nodeType === 1 ) {
  4068 + if ( an2 ) {
  4069 + fn( nNode1, nNode2, index );
  4070 + }
  4071 + else {
  4072 + fn( nNode1, index );
  4073 + }
  4074 +
  4075 + index++;
  4076 + }
  4077 +
  4078 + nNode1 = nNode1.nextSibling;
  4079 + nNode2 = an2 ? nNode2.nextSibling : null;
  4080 + }
  4081 +
  4082 + i++;
  4083 + }
  4084 + }
  4085 +
  4086 +
  4087 +
  4088 + var __re_html_remove = /<.*?>/g;
  4089 +
  4090 +
  4091 + /**
  4092 + * Calculate the width of columns for the table
  4093 + * @param {object} oSettings dataTables settings object
  4094 + * @memberof DataTable#oApi
  4095 + */
  4096 + function _fnCalculateColumnWidths ( oSettings )
  4097 + {
  4098 + var
  4099 + table = oSettings.nTable,
  4100 + columns = oSettings.aoColumns,
  4101 + scroll = oSettings.oScroll,
  4102 + scrollY = scroll.sY,
  4103 + scrollX = scroll.sX,
  4104 + scrollXInner = scroll.sXInner,
  4105 + columnCount = columns.length,
  4106 + visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
  4107 + headerCells = $('th', oSettings.nTHead),
  4108 + tableWidthAttr = table.getAttribute('width'), // from DOM element
  4109 + tableContainer = table.parentNode,
  4110 + userInputs = false,
  4111 + i, column, columnIdx, width, outerWidth;
  4112 +
  4113 + var styleWidth = table.style.width;
  4114 + if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
  4115 + tableWidthAttr = styleWidth;
  4116 + }
  4117 +
  4118 + /* Convert any user input sizes into pixel sizes */
  4119 + for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4120 + column = columns[ visibleColumns[i] ];
  4121 +
  4122 + if ( column.sWidth !== null ) {
  4123 + column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
  4124 +
  4125 + userInputs = true;
  4126 + }
  4127 + }
  4128 +
  4129 + /* If the number of columns in the DOM equals the number that we have to
  4130 + * process in DataTables, then we can use the offsets that are created by
  4131 + * the web- browser. No custom sizes can be set in order for this to happen,
  4132 + * nor scrolling used
  4133 + */
  4134 + if ( ! userInputs && ! scrollX && ! scrollY &&
  4135 + columnCount == _fnVisbleColumns( oSettings ) &&
  4136 + columnCount == headerCells.length
  4137 + ) {
  4138 + for ( i=0 ; i<columnCount ; i++ ) {
  4139 + columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
  4140 + }
  4141 + }
  4142 + else
  4143 + {
  4144 + // Otherwise construct a single row, worst case, table with the widest
  4145 + // node in the data, assign any user defined widths, then insert it into
  4146 + // the DOM and allow the browser to do all the hard work of calculating
  4147 + // table widths
  4148 + var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
  4149 + .css( 'visibility', 'hidden' )
  4150 + .removeAttr( 'id' );
  4151 +
  4152 + // Clean up the table body
  4153 + tmpTable.find('tbody tr').remove();
  4154 + var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
  4155 +
  4156 + // Remove any assigned widths from the footer (from scrolling)
  4157 + tmpTable.find('tfoot th, tfoot td').css('width', '');
  4158 +
  4159 + // Apply custom sizing to the cloned header
  4160 + headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
  4161 +
  4162 + for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4163 + column = columns[ visibleColumns[i] ];
  4164 +
  4165 + headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
  4166 + _fnStringToCss( column.sWidthOrig ) :
  4167 + '';
  4168 + }
  4169 +
  4170 + // Find the widest cell for each column and put it into the table
  4171 + if ( oSettings.aoData.length ) {
  4172 + for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4173 + columnIdx = visibleColumns[i];
  4174 + column = columns[ columnIdx ];
  4175 +
  4176 + $( _fnGetWidestNode( oSettings, columnIdx ) )
  4177 + .clone( false )
  4178 + .append( column.sContentPadding )
  4179 + .appendTo( tr );
  4180 + }
  4181 + }
  4182 +
  4183 + // Table has been built, attach to the document so we can work with it
  4184 + tmpTable.appendTo( tableContainer );
  4185 +
  4186 + // When scrolling (X or Y) we want to set the width of the table as
  4187 + // appropriate. However, when not scrolling leave the table width as it
  4188 + // is. This results in slightly different, but I think correct behaviour
  4189 + if ( scrollX && scrollXInner ) {
  4190 + tmpTable.width( scrollXInner );
  4191 + }
  4192 + else if ( scrollX ) {
  4193 + tmpTable.css( 'width', 'auto' );
  4194 +
  4195 + if ( tmpTable.width() < tableContainer.offsetWidth ) {
  4196 + tmpTable.width( tableContainer.offsetWidth );
  4197 + }
  4198 + }
  4199 + else if ( scrollY ) {
  4200 + tmpTable.width( tableContainer.offsetWidth );
  4201 + }
  4202 + else if ( tableWidthAttr ) {
  4203 + tmpTable.width( tableWidthAttr );
  4204 + }
  4205 +
  4206 + // Take into account the y scrollbar
  4207 + _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
  4208 +
  4209 + // Browsers need a bit of a hand when a width is assigned to any columns
  4210 + // when x-scrolling as they tend to collapse the table to the min-width,
  4211 + // even if we sent the column widths. So we need to keep track of what
  4212 + // the table width should be by summing the user given values, and the
  4213 + // automatic values
  4214 + if ( scrollX )
  4215 + {
  4216 + var total = 0;
  4217 +
  4218 + for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4219 + column = columns[ visibleColumns[i] ];
  4220 + outerWidth = $(headerCells[i]).outerWidth();
  4221 +
  4222 + total += column.sWidthOrig === null ?
  4223 + outerWidth :
  4224 + parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
  4225 + }
  4226 +
  4227 + tmpTable.width( _fnStringToCss( total ) );
  4228 + table.style.width = _fnStringToCss( total );
  4229 + }
  4230 +
  4231 + // Get the width of each column in the constructed table
  4232 + for ( i=0 ; i<visibleColumns.length ; i++ ) {
  4233 + column = columns[ visibleColumns[i] ];
  4234 + width = $(headerCells[i]).width();
  4235 +
  4236 + if ( width ) {
  4237 + column.sWidth = _fnStringToCss( width );
  4238 + }
  4239 + }
  4240 +
  4241 + table.style.width = _fnStringToCss( tmpTable.css('width') );
  4242 +
  4243 + // Finished with the table - ditch it
  4244 + tmpTable.remove();
  4245 + }
  4246 +
  4247 + // If there is a width attr, we want to attach an event listener which
  4248 + // allows the table sizing to automatically adjust when the window is
  4249 + // resized. Use the width attr rather than CSS, since we can't know if the
  4250 + // CSS is a relative value or absolute - DOM read is always px.
  4251 + if ( tableWidthAttr ) {
  4252 + table.style.width = _fnStringToCss( tableWidthAttr );
  4253 + }
  4254 +
  4255 + if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
  4256 + var bindResize = function () {
  4257 + $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
  4258 + _fnAdjustColumnSizing( oSettings );
  4259 + } ) );
  4260 + };
  4261 +
  4262 + // IE6/7 will crash if we bind a resize event handler on page load.
  4263 + // To be removed in 1.11 which drops IE6/7 support
  4264 + if ( oSettings.oBrowser.bScrollOversize ) {
  4265 + setTimeout( bindResize, 1000 );
  4266 + }
  4267 + else {
  4268 + bindResize();
  4269 + }
  4270 +
  4271 + oSettings._reszEvt = true;
  4272 + }
  4273 + }
  4274 +
  4275 +
  4276 + /**
  4277 + * Throttle the calls to a function. Arguments and context are maintained for
  4278 + * the throttled function
  4279 + * @param {function} fn Function to be called
  4280 + * @param {int} [freq=200] call frequency in mS
  4281 + * @returns {function} wrapped function
  4282 + * @memberof DataTable#oApi
  4283 + */
  4284 + function _fnThrottle( fn, freq ) {
  4285 + var
  4286 + frequency = freq !== undefined ? freq : 200,
  4287 + last,
  4288 + timer;
  4289 +
  4290 + return function () {
  4291 + var
  4292 + that = this,
  4293 + now = +new Date(),
  4294 + args = arguments;
  4295 +
  4296 + if ( last && now < last + frequency ) {
  4297 + clearTimeout( timer );
  4298 +
  4299 + timer = setTimeout( function () {
  4300 + last = undefined;
  4301 + fn.apply( that, args );
  4302 + }, frequency );
  4303 + }
  4304 + else {
  4305 + last = now;
  4306 + fn.apply( that, args );
  4307 + }
  4308 + };
  4309 + }
  4310 +
  4311 +
  4312 + /**
  4313 + * Convert a CSS unit width to pixels (e.g. 2em)
  4314 + * @param {string} width width to be converted
  4315 + * @param {node} parent parent to get the with for (required for relative widths) - optional
  4316 + * @returns {int} width in pixels
  4317 + * @memberof DataTable#oApi
  4318 + */
  4319 + function _fnConvertToWidth ( width, parent )
  4320 + {
  4321 + if ( ! width ) {
  4322 + return 0;
  4323 + }
  4324 +
  4325 + var n = $('<div/>')
  4326 + .css( 'width', _fnStringToCss( width ) )
  4327 + .appendTo( parent || document.body );
  4328 +
  4329 + var val = n[0].offsetWidth;
  4330 + n.remove();
  4331 +
  4332 + return val;
  4333 + }
  4334 +
  4335 +
  4336 + /**
  4337 + * Adjust a table's width to take account of vertical scroll bar
  4338 + * @param {object} oSettings dataTables settings object
  4339 + * @param {node} n table node
  4340 + * @memberof DataTable#oApi
  4341 + */
  4342 +
  4343 + function _fnScrollingWidthAdjust ( settings, n )
  4344 + {
  4345 + var scroll = settings.oScroll;
  4346 +
  4347 + if ( scroll.sX || scroll.sY ) {
  4348 + // When y-scrolling only, we want to remove the width of the scroll bar
  4349 + // so the table + scroll bar will fit into the area available, otherwise
  4350 + // we fix the table at its current size with no adjustment
  4351 + var correction = ! scroll.sX ? scroll.iBarWidth : 0;
  4352 + n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
  4353 + }
  4354 + }
  4355 +
  4356 +
  4357 + /**
  4358 + * Get the widest node
  4359 + * @param {object} settings dataTables settings object
  4360 + * @param {int} colIdx column of interest
  4361 + * @returns {node} widest table node
  4362 + * @memberof DataTable#oApi
  4363 + */
  4364 + function _fnGetWidestNode( settings, colIdx )
  4365 + {
  4366 + var idx = _fnGetMaxLenString( settings, colIdx );
  4367 + if ( idx < 0 ) {
  4368 + return null;
  4369 + }
  4370 +
  4371 + var data = settings.aoData[ idx ];
  4372 + return ! data.nTr ? // Might not have been created when deferred rendering
  4373 + $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
  4374 + data.anCells[ colIdx ];
  4375 + }
  4376 +
  4377 +
  4378 + /**
  4379 + * Get the maximum strlen for each data column
  4380 + * @param {object} settings dataTables settings object
  4381 + * @param {int} colIdx column of interest
  4382 + * @returns {string} max string length for each column
  4383 + * @memberof DataTable#oApi
  4384 + */
  4385 + function _fnGetMaxLenString( settings, colIdx )
  4386 + {
  4387 + var s, max=-1, maxIdx = -1;
  4388 +
  4389 + for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  4390 + s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
  4391 + s = s.replace( __re_html_remove, '' );
  4392 +
  4393 + if ( s.length > max ) {
  4394 + max = s.length;
  4395 + maxIdx = i;
  4396 + }
  4397 + }
  4398 +
  4399 + return maxIdx;
  4400 + }
  4401 +
  4402 +
  4403 + /**
  4404 + * Append a CSS unit (only if required) to a string
  4405 + * @param {string} value to css-ify
  4406 + * @returns {string} value with css unit
  4407 + * @memberof DataTable#oApi
  4408 + */
  4409 + function _fnStringToCss( s )
  4410 + {
  4411 + if ( s === null ) {
  4412 + return '0px';
  4413 + }
  4414 +
  4415 + if ( typeof s == 'number' ) {
  4416 + return s < 0 ?
  4417 + '0px' :
  4418 + s+'px';
  4419 + }
  4420 +
  4421 + // Check it has a unit character already
  4422 + return s.match(/\d$/) ?
  4423 + s+'px' :
  4424 + s;
  4425 + }
  4426 +
  4427 +
  4428 + /**
  4429 + * Get the width of a scroll bar in this browser being used
  4430 + * @returns {int} width in pixels
  4431 + * @memberof DataTable#oApi
  4432 + */
  4433 + function _fnScrollBarWidth ()
  4434 + {
  4435 + // On first run a static variable is set, since this is only needed once.
  4436 + // Subsequent runs will just use the previously calculated value
  4437 + var width = DataTable.__scrollbarWidth;
  4438 +
  4439 + if ( width === undefined ) {
  4440 + var sizer = $('<p/>').css( {
  4441 + position: 'absolute',
  4442 + top: 0,
  4443 + left: 0,
  4444 + width: '100%',
  4445 + height: 150,
  4446 + padding: 0,
  4447 + overflow: 'scroll',
  4448 + visibility: 'hidden'
  4449 + } )
  4450 + .appendTo('body');
  4451 +
  4452 + width = sizer[0].offsetWidth - sizer[0].clientWidth;
  4453 + DataTable.__scrollbarWidth = width;
  4454 +
  4455 + sizer.remove();
  4456 + }
  4457 +
  4458 + return width;
  4459 + }
  4460 +
  4461 +
  4462 +
  4463 + function _fnSortFlatten ( settings )
  4464 + {
  4465 + var
  4466 + i, iLen, k, kLen,
  4467 + aSort = [],
  4468 + aiOrig = [],
  4469 + aoColumns = settings.aoColumns,
  4470 + aDataSort, iCol, sType, srcCol,
  4471 + fixed = settings.aaSortingFixed,
  4472 + fixedObj = $.isPlainObject( fixed ),
  4473 + nestedSort = [],
  4474 + add = function ( a ) {
  4475 + if ( a.length && ! $.isArray( a[0] ) ) {
  4476 + // 1D array
  4477 + nestedSort.push( a );
  4478 + }
  4479 + else {
  4480 + // 2D array
  4481 + nestedSort.push.apply( nestedSort, a );
  4482 + }
  4483 + };
  4484 +
  4485 + // Build the sort array, with pre-fix and post-fix options if they have been
  4486 + // specified
  4487 + if ( $.isArray( fixed ) ) {
  4488 + add( fixed );
  4489 + }
  4490 +
  4491 + if ( fixedObj && fixed.pre ) {
  4492 + add( fixed.pre );
  4493 + }
  4494 +
  4495 + add( settings.aaSorting );
  4496 +
  4497 + if (fixedObj && fixed.post ) {
  4498 + add( fixed.post );
  4499 + }
  4500 +
  4501 + for ( i=0 ; i<nestedSort.length ; i++ )
  4502 + {
  4503 + srcCol = nestedSort[i][0];
  4504 + aDataSort = aoColumns[ srcCol ].aDataSort;
  4505 +
  4506 + for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
  4507 + {
  4508 + iCol = aDataSort[k];
  4509 + sType = aoColumns[ iCol ].sType || 'string';
  4510 +
  4511 + if ( nestedSort[i]._idx === undefined ) {
  4512 + nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
  4513 + }
  4514 +
  4515 + aSort.push( {
  4516 + src: srcCol,
  4517 + col: iCol,
  4518 + dir: nestedSort[i][1],
  4519 + index: nestedSort[i]._idx,
  4520 + type: sType,
  4521 + formatter: DataTable.ext.type.order[ sType+"-pre" ]
  4522 + } );
  4523 + }
  4524 + }
  4525 +
  4526 + return aSort;
  4527 + }
  4528 +
  4529 + /**
  4530 + * Change the order of the table
  4531 + * @param {object} oSettings dataTables settings object
  4532 + * @memberof DataTable#oApi
  4533 + * @todo This really needs split up!
  4534 + */
  4535 + function _fnSort ( oSettings )
  4536 + {
  4537 + var
  4538 + i, ien, iLen, j, jLen, k, kLen,
  4539 + sDataType, nTh,
  4540 + aiOrig = [],
  4541 + oExtSort = DataTable.ext.type.order,
  4542 + aoData = oSettings.aoData,
  4543 + aoColumns = oSettings.aoColumns,
  4544 + aDataSort, data, iCol, sType, oSort,
  4545 + formatters = 0,
  4546 + sortCol,
  4547 + displayMaster = oSettings.aiDisplayMaster,
  4548 + aSort;
  4549 +
  4550 + // Resolve any column types that are unknown due to addition or invalidation
  4551 + // @todo Can this be moved into a 'data-ready' handler which is called when
  4552 + // data is going to be used in the table?
  4553 + _fnColumnTypes( oSettings );
  4554 +
  4555 + aSort = _fnSortFlatten( oSettings );
  4556 +
  4557 + for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
  4558 + sortCol = aSort[i];
  4559 +
  4560 + // Track if we can use the fast sort algorithm
  4561 + if ( sortCol.formatter ) {
  4562 + formatters++;
  4563 + }
  4564 +
  4565 + // Load the data needed for the sort, for each cell
  4566 + _fnSortData( oSettings, sortCol.col );
  4567 + }
  4568 +
  4569 + /* No sorting required if server-side or no sorting array */
  4570 + if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
  4571 + {
  4572 + // Create a value - key array of the current row positions such that we can use their
  4573 + // current position during the sort, if values match, in order to perform stable sorting
  4574 + for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
  4575 + aiOrig[ displayMaster[i] ] = i;
  4576 + }
  4577 +
  4578 + /* Do the sort - here we want multi-column sorting based on a given data source (column)
  4579 + * and sorting function (from oSort) in a certain direction. It's reasonably complex to
  4580 + * follow on it's own, but this is what we want (example two column sorting):
  4581 + * fnLocalSorting = function(a,b){
  4582 + * var iTest;
  4583 + * iTest = oSort['string-asc']('data11', 'data12');
  4584 + * if (iTest !== 0)
  4585 + * return iTest;
  4586 + * iTest = oSort['numeric-desc']('data21', 'data22');
  4587 + * if (iTest !== 0)
  4588 + * return iTest;
  4589 + * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
  4590 + * }
  4591 + * Basically we have a test for each sorting column, if the data in that column is equal,
  4592 + * test the next column. If all columns match, then we use a numeric sort on the row
  4593 + * positions in the original data array to provide a stable sort.
  4594 + *
  4595 + * Note - I know it seems excessive to have two sorting methods, but the first is around
  4596 + * 15% faster, so the second is only maintained for backwards compatibility with sorting
  4597 + * methods which do not have a pre-sort formatting function.
  4598 + */
  4599 + if ( formatters === aSort.length ) {
  4600 + // All sort types have formatting functions
  4601 + displayMaster.sort( function ( a, b ) {
  4602 + var
  4603 + x, y, k, test, sort,
  4604 + len=aSort.length,
  4605 + dataA = aoData[a]._aSortData,
  4606 + dataB = aoData[b]._aSortData;
  4607 +
  4608 + for ( k=0 ; k<len ; k++ ) {
  4609 + sort = aSort[k];
  4610 +
  4611 + x = dataA[ sort.col ];
  4612 + y = dataB[ sort.col ];
  4613 +
  4614 + test = x<y ? -1 : x>y ? 1 : 0;
  4615 + if ( test !== 0 ) {
  4616 + return sort.dir === 'asc' ? test : -test;
  4617 + }
  4618 + }
  4619 +
  4620 + x = aiOrig[a];
  4621 + y = aiOrig[b];
  4622 + return x<y ? -1 : x>y ? 1 : 0;
  4623 + } );
  4624 + }
  4625 + else {
  4626 + // Depreciated - remove in 1.11 (providing a plug-in option)
  4627 + // Not all sort types have formatting methods, so we have to call their sorting
  4628 + // methods.
  4629 + displayMaster.sort( function ( a, b ) {
  4630 + var
  4631 + x, y, k, l, test, sort, fn,
  4632 + len=aSort.length,
  4633 + dataA = aoData[a]._aSortData,
  4634 + dataB = aoData[b]._aSortData;
  4635 +
  4636 + for ( k=0 ; k<len ; k++ ) {
  4637 + sort = aSort[k];
  4638 +
  4639 + x = dataA[ sort.col ];
  4640 + y = dataB[ sort.col ];
  4641 +
  4642 + fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
  4643 + test = fn( x, y );
  4644 + if ( test !== 0 ) {
  4645 + return test;
  4646 + }
  4647 + }
  4648 +
  4649 + x = aiOrig[a];
  4650 + y = aiOrig[b];
  4651 + return x<y ? -1 : x>y ? 1 : 0;
  4652 + } );
  4653 + }
  4654 + }
  4655 +
  4656 + /* Tell the draw function that we have sorted the data */
  4657 + oSettings.bSorted = true;
  4658 + }
  4659 +
  4660 +
  4661 + function _fnSortAria ( settings )
  4662 + {
  4663 + var label;
  4664 + var nextSort;
  4665 + var columns = settings.aoColumns;
  4666 + var aSort = _fnSortFlatten( settings );
  4667 + var oAria = settings.oLanguage.oAria;
  4668 +
  4669 + // ARIA attributes - need to loop all columns, to update all (removing old
  4670 + // attributes as needed)
  4671 + for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
  4672 + {
  4673 + var col = columns[i];
  4674 + var asSorting = col.asSorting;
  4675 + var sTitle = col.sTitle.replace( /<.*?>/g, "" );
  4676 + var th = col.nTh;
  4677 +
  4678 + // IE7 is throwing an error when setting these properties with jQuery's
  4679 + // attr() and removeAttr() methods...
  4680 + th.removeAttribute('aria-sort');
  4681 +
  4682 + /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
  4683 + if ( col.bSortable ) {
  4684 + if ( aSort.length > 0 && aSort[0].col == i ) {
  4685 + th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
  4686 + nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
  4687 + }
  4688 + else {
  4689 + nextSort = asSorting[0];
  4690 + }
  4691 +
  4692 + label = sTitle + ( nextSort === "asc" ?
  4693 + oAria.sSortAscending :
  4694 + oAria.sSortDescending
  4695 + );
  4696 + }
  4697 + else {
  4698 + label = sTitle;
  4699 + }
  4700 +
  4701 + th.setAttribute('aria-label', label);
  4702 + }
  4703 + }
  4704 +
  4705 +
  4706 + /**
  4707 + * Function to run on user sort request
  4708 + * @param {object} settings dataTables settings object
  4709 + * @param {node} attachTo node to attach the handler to
  4710 + * @param {int} colIdx column sorting index
  4711 + * @param {boolean} [append=false] Append the requested sort to the existing
  4712 + * sort if true (i.e. multi-column sort)
  4713 + * @param {function} [callback] callback function
  4714 + * @memberof DataTable#oApi
  4715 + */
  4716 + function _fnSortListener ( settings, colIdx, append, callback )
  4717 + {
  4718 + var col = settings.aoColumns[ colIdx ];
  4719 + var sorting = settings.aaSorting;
  4720 + var asSorting = col.asSorting;
  4721 + var nextSortIdx;
  4722 + var next = function ( a, overflow ) {
  4723 + var idx = a._idx;
  4724 + if ( idx === undefined ) {
  4725 + idx = $.inArray( a[1], asSorting );
  4726 + }
  4727 +
  4728 + return idx+1 < asSorting.length ?
  4729 + idx+1 :
  4730 + overflow ?
  4731 + null :
  4732 + 0;
  4733 + };
  4734 +
  4735 + // Convert to 2D array if needed
  4736 + if ( typeof sorting[0] === 'number' ) {
  4737 + sorting = settings.aaSorting = [ sorting ];
  4738 + }
  4739 +
  4740 + // If appending the sort then we are multi-column sorting
  4741 + if ( append && settings.oFeatures.bSortMulti ) {
  4742 + // Are we already doing some kind of sort on this column?
  4743 + var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
  4744 +
  4745 + if ( sortIdx !== -1 ) {
  4746 + // Yes, modify the sort
  4747 + nextSortIdx = next( sorting[sortIdx], true );
  4748 +
  4749 + if ( nextSortIdx === null && sorting.length === 1 ) {
  4750 + nextSortIdx = 0; // can't remove sorting completely
  4751 + }
  4752 +
  4753 + if ( nextSortIdx === null ) {
  4754 + sorting.splice( sortIdx, 1 );
  4755 + }
  4756 + else {
  4757 + sorting[sortIdx][1] = asSorting[ nextSortIdx ];
  4758 + sorting[sortIdx]._idx = nextSortIdx;
  4759 + }
  4760 + }
  4761 + else {
  4762 + // No sort on this column yet
  4763 + sorting.push( [ colIdx, asSorting[0], 0 ] );
  4764 + sorting[sorting.length-1]._idx = 0;
  4765 + }
  4766 + }
  4767 + else if ( sorting.length && sorting[0][0] == colIdx ) {
  4768 + // Single column - already sorting on this column, modify the sort
  4769 + nextSortIdx = next( sorting[0] );
  4770 +
  4771 + sorting.length = 1;
  4772 + sorting[0][1] = asSorting[ nextSortIdx ];
  4773 + sorting[0]._idx = nextSortIdx;
  4774 + }
  4775 + else {
  4776 + // Single column - sort only on this column
  4777 + sorting.length = 0;
  4778 + sorting.push( [ colIdx, asSorting[0] ] );
  4779 + sorting[0]._idx = 0;
  4780 + }
  4781 +
  4782 + // Run the sort by calling a full redraw
  4783 + _fnReDraw( settings );
  4784 +
  4785 + // callback used for async user interaction
  4786 + if ( typeof callback == 'function' ) {
  4787 + callback( settings );
  4788 + }
  4789 + }
  4790 +
  4791 +
  4792 + /**
  4793 + * Attach a sort handler (click) to a node
  4794 + * @param {object} settings dataTables settings object
  4795 + * @param {node} attachTo node to attach the handler to
  4796 + * @param {int} colIdx column sorting index
  4797 + * @param {function} [callback] callback function
  4798 + * @memberof DataTable#oApi
  4799 + */
  4800 + function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
  4801 + {
  4802 + var col = settings.aoColumns[ colIdx ];
  4803 +
  4804 + _fnBindAction( attachTo, {}, function (e) {
  4805 + /* If the column is not sortable - don't to anything */
  4806 + if ( col.bSortable === false ) {
  4807 + return;
  4808 + }
  4809 +
  4810 + // If processing is enabled use a timeout to allow the processing
  4811 + // display to be shown - otherwise to it synchronously
  4812 + if ( settings.oFeatures.bProcessing ) {
  4813 + _fnProcessingDisplay( settings, true );
  4814 +
  4815 + setTimeout( function() {
  4816 + _fnSortListener( settings, colIdx, e.shiftKey, callback );
  4817 +
  4818 + // In server-side processing, the draw callback will remove the
  4819 + // processing display
  4820 + if ( _fnDataSource( settings ) !== 'ssp' ) {
  4821 + _fnProcessingDisplay( settings, false );
  4822 + }
  4823 + }, 0 );
  4824 + }
  4825 + else {
  4826 + _fnSortListener( settings, colIdx, e.shiftKey, callback );
  4827 + }
  4828 + } );
  4829 + }
  4830 +
  4831 +
  4832 + /**
  4833 + * Set the sorting classes on table's body, Note: it is safe to call this function
  4834 + * when bSort and bSortClasses are false
  4835 + * @param {object} oSettings dataTables settings object
  4836 + * @memberof DataTable#oApi
  4837 + */
  4838 + function _fnSortingClasses( settings )
  4839 + {
  4840 + var oldSort = settings.aLastSort;
  4841 + var sortClass = settings.oClasses.sSortColumn;
  4842 + var sort = _fnSortFlatten( settings );
  4843 + var features = settings.oFeatures;
  4844 + var i, ien, colIdx;
  4845 +
  4846 + if ( features.bSort && features.bSortClasses ) {
  4847 + // Remove old sorting classes
  4848 + for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
  4849 + colIdx = oldSort[i].src;
  4850 +
  4851 + // Remove column sorting
  4852 + $( _pluck( settings.aoData, 'anCells', colIdx ) )
  4853 + .removeClass( sortClass + (i<2 ? i+1 : 3) );
  4854 + }
  4855 +
  4856 + // Add new column sorting
  4857 + for ( i=0, ien=sort.length ; i<ien ; i++ ) {
  4858 + colIdx = sort[i].src;
  4859 +
  4860 + $( _pluck( settings.aoData, 'anCells', colIdx ) )
  4861 + .addClass( sortClass + (i<2 ? i+1 : 3) );
  4862 + }
  4863 + }
  4864 +
  4865 + settings.aLastSort = sort;
  4866 + }
  4867 +
  4868 +
  4869 + // Get the data to sort a column, be it from cache, fresh (populating the
  4870 + // cache), or from a sort formatter
  4871 + function _fnSortData( settings, idx )
  4872 + {
  4873 + // Custom sorting function - provided by the sort data type
  4874 + var column = settings.aoColumns[ idx ];
  4875 + var customSort = DataTable.ext.order[ column.sSortDataType ];
  4876 + var customData;
  4877 +
  4878 + if ( customSort ) {
  4879 + customData = customSort.call( settings.oInstance, settings, idx,
  4880 + _fnColumnIndexToVisible( settings, idx )
  4881 + );
  4882 + }
  4883 +
  4884 + // Use / populate cache
  4885 + var row, cellData;
  4886 + var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
  4887 +
  4888 + for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  4889 + row = settings.aoData[i];
  4890 +
  4891 + if ( ! row._aSortData ) {
  4892 + row._aSortData = [];
  4893 + }
  4894 +
  4895 + if ( ! row._aSortData[idx] || customSort ) {
  4896 + cellData = customSort ?
  4897 + customData[i] : // If there was a custom sort function, use data from there
  4898 + _fnGetCellData( settings, i, idx, 'sort' );
  4899 +
  4900 + row._aSortData[ idx ] = formatter ?
  4901 + formatter( cellData ) :
  4902 + cellData;
  4903 + }
  4904 + }
  4905 + }
  4906 +
  4907 +
  4908 +
  4909 + /**
  4910 + * Save the state of a table
  4911 + * @param {object} oSettings dataTables settings object
  4912 + * @memberof DataTable#oApi
  4913 + */
  4914 + function _fnSaveState ( settings )
  4915 + {
  4916 + if ( !settings.oFeatures.bStateSave || settings.bDestroying )
  4917 + {
  4918 + return;
  4919 + }
  4920 +
  4921 + /* Store the interesting variables */
  4922 + var state = {
  4923 + time: +new Date(),
  4924 + start: settings._iDisplayStart,
  4925 + length: settings._iDisplayLength,
  4926 + order: $.extend( true, [], settings.aaSorting ),
  4927 + search: _fnSearchToCamel( settings.oPreviousSearch ),
  4928 + columns: $.map( settings.aoColumns, function ( col, i ) {
  4929 + return {
  4930 + visible: col.bVisible,
  4931 + search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
  4932 + };
  4933 + } )
  4934 + };
  4935 +
  4936 + _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
  4937 +
  4938 + settings.oSavedState = state;
  4939 + settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
  4940 + }
  4941 +
  4942 +
  4943 + /**
  4944 + * Attempt to load a saved table state
  4945 + * @param {object} oSettings dataTables settings object
  4946 + * @param {object} oInit DataTables init object so we can override settings
  4947 + * @memberof DataTable#oApi
  4948 + */
  4949 + function _fnLoadState ( settings, oInit )
  4950 + {
  4951 + var i, ien;
  4952 + var columns = settings.aoColumns;
  4953 +
  4954 + if ( ! settings.oFeatures.bStateSave ) {
  4955 + return;
  4956 + }
  4957 +
  4958 + var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
  4959 + if ( ! state || ! state.time ) {
  4960 + return;
  4961 + }
  4962 +
  4963 + /* Allow custom and plug-in manipulation functions to alter the saved data set and
  4964 + * cancelling of loading by returning false
  4965 + */
  4966 + var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
  4967 + if ( $.inArray( false, abStateLoad ) !== -1 ) {
  4968 + return;
  4969 + }
  4970 +
  4971 + /* Reject old data */
  4972 + var duration = settings.iStateDuration;
  4973 + if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
  4974 + return;
  4975 + }
  4976 +
  4977 + // Number of columns have changed - all bets are off, no restore of settings
  4978 + if ( columns.length !== state.columns.length ) {
  4979 + return;
  4980 + }
  4981 +
  4982 + // Store the saved state so it might be accessed at any time
  4983 + settings.oLoadedState = $.extend( true, {}, state );
  4984 +
  4985 + // Restore key features - todo - for 1.11 this needs to be done by
  4986 + // subscribed events
  4987 + if ( state.start !== undefined ) {
  4988 + settings._iDisplayStart = state.start;
  4989 + settings.iInitDisplayStart = state.start;
  4990 + }
  4991 + if ( state.length !== undefined ) {
  4992 + settings._iDisplayLength = state.length;
  4993 + }
  4994 +
  4995 + // Order
  4996 + if ( state.order !== undefined ) {
  4997 + settings.aaSorting = [];
  4998 + $.each( state.order, function ( i, col ) {
  4999 + settings.aaSorting.push( col[0] >= columns.length ?
  5000 + [ 0, col[1] ] :
  5001 + col
  5002 + );
  5003 + } );
  5004 + }
  5005 +
  5006 + // Search
  5007 + if ( state.search !== undefined ) {
  5008 + $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
  5009 + }
  5010 +
  5011 + // Columns
  5012 + for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
  5013 + var col = state.columns[i];
  5014 +
  5015 + // Visibility
  5016 + if ( col.visible !== undefined ) {
  5017 + columns[i].bVisible = col.visible;
  5018 + }
  5019 +
  5020 + // Search
  5021 + if ( col.search !== undefined ) {
  5022 + $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
  5023 + }
  5024 + }
  5025 +
  5026 + _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
  5027 + }
  5028 +
  5029 +
  5030 + /**
  5031 + * Return the settings object for a particular table
  5032 + * @param {node} table table we are using as a dataTable
  5033 + * @returns {object} Settings object - or null if not found
  5034 + * @memberof DataTable#oApi
  5035 + */
  5036 + function _fnSettingsFromNode ( table )
  5037 + {
  5038 + var settings = DataTable.settings;
  5039 + var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
  5040 +
  5041 + return idx !== -1 ?
  5042 + settings[ idx ] :
  5043 + null;
  5044 + }
  5045 +
  5046 +
  5047 + /**
  5048 + * Log an error message
  5049 + * @param {object} settings dataTables settings object
  5050 + * @param {int} level log error messages, or display them to the user
  5051 + * @param {string} msg error message
  5052 + * @param {int} tn Technical note id to get more information about the error.
  5053 + * @memberof DataTable#oApi
  5054 + */
  5055 + function _fnLog( settings, level, msg, tn )
  5056 + {
  5057 + msg = 'DataTables warning: '+
  5058 + (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
  5059 +
  5060 + if ( tn ) {
  5061 + msg += '. For more information about this error, please see '+
  5062 + 'http://datatables.net/tn/'+tn;
  5063 + }
  5064 +
  5065 + if ( ! level ) {
  5066 + // Backwards compatibility pre 1.10
  5067 + var ext = DataTable.ext;
  5068 + var type = ext.sErrMode || ext.errMode;
  5069 +
  5070 + _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
  5071 +
  5072 + if ( type == 'alert' ) {
  5073 + alert( msg );
  5074 + }
  5075 + else if ( type == 'throw' ) {
  5076 + throw new Error(msg);
  5077 + }
  5078 + else if ( typeof type == 'function' ) {
  5079 + type( settings, tn, msg );
  5080 + }
  5081 + }
  5082 + else if ( window.console && console.log ) {
  5083 + console.log( msg );
  5084 + }
  5085 + }
  5086 +
  5087 +
  5088 + /**
  5089 + * See if a property is defined on one object, if so assign it to the other object
  5090 + * @param {object} ret target object
  5091 + * @param {object} src source object
  5092 + * @param {string} name property
  5093 + * @param {string} [mappedName] name to map too - optional, name used if not given
  5094 + * @memberof DataTable#oApi
  5095 + */
  5096 + function _fnMap( ret, src, name, mappedName )
  5097 + {
  5098 + if ( $.isArray( name ) ) {
  5099 + $.each( name, function (i, val) {
  5100 + if ( $.isArray( val ) ) {
  5101 + _fnMap( ret, src, val[0], val[1] );
  5102 + }
  5103 + else {
  5104 + _fnMap( ret, src, val );
  5105 + }
  5106 + } );
  5107 +
  5108 + return;
  5109 + }
  5110 +
  5111 + if ( mappedName === undefined ) {
  5112 + mappedName = name;
  5113 + }
  5114 +
  5115 + if ( src[name] !== undefined ) {
  5116 + ret[mappedName] = src[name];
  5117 + }
  5118 + }
  5119 +
  5120 +
  5121 + /**
  5122 + * Extend objects - very similar to jQuery.extend, but deep copy objects, and
  5123 + * shallow copy arrays. The reason we need to do this, is that we don't want to
  5124 + * deep copy array init values (such as aaSorting) since the dev wouldn't be
  5125 + * able to override them, but we do want to deep copy arrays.
  5126 + * @param {object} out Object to extend
  5127 + * @param {object} extender Object from which the properties will be applied to
  5128 + * out
  5129 + * @param {boolean} breakRefs If true, then arrays will be sliced to take an
  5130 + * independent copy with the exception of the `data` or `aaData` parameters
  5131 + * if they are present. This is so you can pass in a collection to
  5132 + * DataTables and have that used as your data source without breaking the
  5133 + * references
  5134 + * @returns {object} out Reference, just for convenience - out === the return.
  5135 + * @memberof DataTable#oApi
  5136 + * @todo This doesn't take account of arrays inside the deep copied objects.
  5137 + */
  5138 + function _fnExtend( out, extender, breakRefs )
  5139 + {
  5140 + var val;
  5141 +
  5142 + for ( var prop in extender ) {
  5143 + if ( extender.hasOwnProperty(prop) ) {
  5144 + val = extender[prop];
  5145 +
  5146 + if ( $.isPlainObject( val ) ) {
  5147 + if ( ! $.isPlainObject( out[prop] ) ) {
  5148 + out[prop] = {};
  5149 + }
  5150 + $.extend( true, out[prop], val );
  5151 + }
  5152 + else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
  5153 + out[prop] = val.slice();
  5154 + }
  5155 + else {
  5156 + out[prop] = val;
  5157 + }
  5158 + }
  5159 + }
  5160 +
  5161 + return out;
  5162 + }
  5163 +
  5164 +
  5165 + /**
  5166 + * Bind an event handers to allow a click or return key to activate the callback.
  5167 + * This is good for accessibility since a return on the keyboard will have the
  5168 + * same effect as a click, if the element has focus.
  5169 + * @param {element} n Element to bind the action to
  5170 + * @param {object} oData Data object to pass to the triggered function
  5171 + * @param {function} fn Callback function for when the event is triggered
  5172 + * @memberof DataTable#oApi
  5173 + */
  5174 + function _fnBindAction( n, oData, fn )
  5175 + {
  5176 + $(n)
  5177 + .bind( 'click.DT', oData, function (e) {
  5178 + n.blur(); // Remove focus outline for mouse users
  5179 + fn(e);
  5180 + } )
  5181 + .bind( 'keypress.DT', oData, function (e){
  5182 + if ( e.which === 13 ) {
  5183 + e.preventDefault();
  5184 + fn(e);
  5185 + }
  5186 + } )
  5187 + .bind( 'selectstart.DT', function () {
  5188 + /* Take the brutal approach to cancelling text selection */
  5189 + return false;
  5190 + } );
  5191 + }
  5192 +
  5193 +
  5194 + /**
  5195 + * Register a callback function. Easily allows a callback function to be added to
  5196 + * an array store of callback functions that can then all be called together.
  5197 + * @param {object} oSettings dataTables settings object
  5198 + * @param {string} sStore Name of the array storage for the callbacks in oSettings
  5199 + * @param {function} fn Function to be called back
  5200 + * @param {string} sName Identifying name for the callback (i.e. a label)
  5201 + * @memberof DataTable#oApi
  5202 + */
  5203 + function _fnCallbackReg( oSettings, sStore, fn, sName )
  5204 + {
  5205 + if ( fn )
  5206 + {
  5207 + oSettings[sStore].push( {
  5208 + "fn": fn,
  5209 + "sName": sName
  5210 + } );
  5211 + }
  5212 + }
  5213 +
  5214 +
  5215 + /**
  5216 + * Fire callback functions and trigger events. Note that the loop over the
  5217 + * callback array store is done backwards! Further note that you do not want to
  5218 + * fire off triggers in time sensitive applications (for example cell creation)
  5219 + * as its slow.
  5220 + * @param {object} settings dataTables settings object
  5221 + * @param {string} callbackArr Name of the array storage for the callbacks in
  5222 + * oSettings
  5223 + * @param {string} eventName Name of the jQuery custom event to trigger. If
  5224 + * null no trigger is fired
  5225 + * @param {array} args Array of arguments to pass to the callback function /
  5226 + * trigger
  5227 + * @memberof DataTable#oApi
  5228 + */
  5229 + function _fnCallbackFire( settings, callbackArr, eventName, args )
  5230 + {
  5231 + var ret = [];
  5232 +
  5233 + if ( callbackArr ) {
  5234 + ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
  5235 + return val.fn.apply( settings.oInstance, args );
  5236 + } );
  5237 + }
  5238 +
  5239 + if ( eventName !== null ) {
  5240 + var e = $.Event( eventName+'.dt' );
  5241 +
  5242 + $(settings.nTable).trigger( e, args );
  5243 +
  5244 + ret.push( e.result );
  5245 + }
  5246 +
  5247 + return ret;
  5248 + }
  5249 +
  5250 +
  5251 + function _fnLengthOverflow ( settings )
  5252 + {
  5253 + var
  5254 + start = settings._iDisplayStart,
  5255 + end = settings.fnDisplayEnd(),
  5256 + len = settings._iDisplayLength;
  5257 +
  5258 + /* If we have space to show extra rows (backing up from the end point - then do so */
  5259 + if ( start >= end )
  5260 + {
  5261 + start = end - len;
  5262 + }
  5263 +
  5264 + // Keep the start record on the current page
  5265 + start -= (start % len);
  5266 +
  5267 + if ( len === -1 || start < 0 )
  5268 + {
  5269 + start = 0;
  5270 + }
  5271 +
  5272 + settings._iDisplayStart = start;
  5273 + }
  5274 +
  5275 +
  5276 + function _fnRenderer( settings, type )
  5277 + {
  5278 + var renderer = settings.renderer;
  5279 + var host = DataTable.ext.renderer[type];
  5280 +
  5281 + if ( $.isPlainObject( renderer ) && renderer[type] ) {
  5282 + // Specific renderer for this type. If available use it, otherwise use
  5283 + // the default.
  5284 + return host[renderer[type]] || host._;
  5285 + }
  5286 + else if ( typeof renderer === 'string' ) {
  5287 + // Common renderer - if there is one available for this type use it,
  5288 + // otherwise use the default
  5289 + return host[renderer] || host._;
  5290 + }
  5291 +
  5292 + // Use the default
  5293 + return host._;
  5294 + }
  5295 +
  5296 +
  5297 + /**
  5298 + * Detect the data source being used for the table. Used to simplify the code
  5299 + * a little (ajax) and to make it compress a little smaller.
  5300 + *
  5301 + * @param {object} settings dataTables settings object
  5302 + * @returns {string} Data source
  5303 + * @memberof DataTable#oApi
  5304 + */
  5305 + function _fnDataSource ( settings )
  5306 + {
  5307 + if ( settings.oFeatures.bServerSide ) {
  5308 + return 'ssp';
  5309 + }
  5310 + else if ( settings.ajax || settings.sAjaxSource ) {
  5311 + return 'ajax';
  5312 + }
  5313 + return 'dom';
  5314 + }
  5315 +
  5316 +
  5317 + DataTable = function( options )
  5318 + {
  5319 + /**
  5320 + * Perform a jQuery selector action on the table's TR elements (from the tbody) and
  5321 + * return the resulting jQuery object.
  5322 + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  5323 + * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  5324 + * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
  5325 + * criterion ("applied") or all TR elements (i.e. no filter).
  5326 + * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
  5327 + * Can be either 'current', whereby the current sorting of the table is used, or
  5328 + * 'original' whereby the original order the data was read into the table is used.
  5329 + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  5330 + * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  5331 + * 'current' and filter is 'applied', regardless of what they might be given as.
  5332 + * @returns {object} jQuery object, filtered by the given selector.
  5333 + * @dtopt API
  5334 + * @deprecated Since v1.10
  5335 + *
  5336 + * @example
  5337 + * $(document).ready(function() {
  5338 + * var oTable = $('#example').dataTable();
  5339 + *
  5340 + * // Highlight every second row
  5341 + * oTable.$('tr:odd').css('backgroundColor', 'blue');
  5342 + * } );
  5343 + *
  5344 + * @example
  5345 + * $(document).ready(function() {
  5346 + * var oTable = $('#example').dataTable();
  5347 + *
  5348 + * // Filter to rows with 'Webkit' in them, add a background colour and then
  5349 + * // remove the filter, thus highlighting the 'Webkit' rows only.
  5350 + * oTable.fnFilter('Webkit');
  5351 + * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
  5352 + * oTable.fnFilter('');
  5353 + * } );
  5354 + */
  5355 + this.$ = function ( sSelector, oOpts )
  5356 + {
  5357 + return this.api(true).$( sSelector, oOpts );
  5358 + };
  5359 +
  5360 +
  5361 + /**
  5362 + * Almost identical to $ in operation, but in this case returns the data for the matched
  5363 + * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
  5364 + * rather than any descendants, so the data can be obtained for the row/cell. If matching
  5365 + * rows are found, the data returned is the original data array/object that was used to
  5366 + * create the row (or a generated array if from a DOM source).
  5367 + *
  5368 + * This method is often useful in-combination with $ where both functions are given the
  5369 + * same parameters and the array indexes will match identically.
  5370 + * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
  5371 + * @param {object} [oOpts] Optional parameters for modifying the rows to be included
  5372 + * @param {string} [oOpts.filter=none] Select elements that meet the current filter
  5373 + * criterion ("applied") or all elements (i.e. no filter).
  5374 + * @param {string} [oOpts.order=current] Order of the data in the processed array.
  5375 + * Can be either 'current', whereby the current sorting of the table is used, or
  5376 + * 'original' whereby the original order the data was read into the table is used.
  5377 + * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
  5378 + * ("current") or not ("all"). If 'current' is given, then order is assumed to be
  5379 + * 'current' and filter is 'applied', regardless of what they might be given as.
  5380 + * @returns {array} Data for the matched elements. If any elements, as a result of the
  5381 + * selector, were not TR, TD or TH elements in the DataTable, they will have a null
  5382 + * entry in the array.
  5383 + * @dtopt API
  5384 + * @deprecated Since v1.10
  5385 + *
  5386 + * @example
  5387 + * $(document).ready(function() {
  5388 + * var oTable = $('#example').dataTable();
  5389 + *
  5390 + * // Get the data from the first row in the table
  5391 + * var data = oTable._('tr:first');
  5392 + *
  5393 + * // Do something useful with the data
  5394 + * alert( "First cell is: "+data[0] );
  5395 + * } );
  5396 + *
  5397 + * @example
  5398 + * $(document).ready(function() {
  5399 + * var oTable = $('#example').dataTable();
  5400 + *
  5401 + * // Filter to 'Webkit' and get all data for
  5402 + * oTable.fnFilter('Webkit');
  5403 + * var data = oTable._('tr', {"search": "applied"});
  5404 + *
  5405 + * // Do something with the data
  5406 + * alert( data.length+" rows matched the search" );
  5407 + * } );
  5408 + */
  5409 + this._ = function ( sSelector, oOpts )
  5410 + {
  5411 + return this.api(true).rows( sSelector, oOpts ).data();
  5412 + };
  5413 +
  5414 +
  5415 + /**
  5416 + * Create a DataTables Api instance, with the currently selected tables for
  5417 + * the Api's context.
  5418 + * @param {boolean} [traditional=false] Set the API instance's context to be
  5419 + * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
  5420 + * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
  5421 + * or if all tables captured in the jQuery object should be used.
  5422 + * @return {DataTables.Api}
  5423 + */
  5424 + this.api = function ( traditional )
  5425 + {
  5426 + return traditional ?
  5427 + new _Api(
  5428 + _fnSettingsFromNode( this[ _ext.iApiIndex ] )
  5429 + ) :
  5430 + new _Api( this );
  5431 + };
  5432 +
  5433 +
  5434 + /**
  5435 + * Add a single new row or multiple rows of data to the table. Please note
  5436 + * that this is suitable for client-side processing only - if you are using
  5437 + * server-side processing (i.e. "bServerSide": true), then to add data, you
  5438 + * must add it to the data source, i.e. the server-side, through an Ajax call.
  5439 + * @param {array|object} data The data to be added to the table. This can be:
  5440 + * <ul>
  5441 + * <li>1D array of data - add a single row with the data provided</li>
  5442 + * <li>2D array of arrays - add multiple rows in a single call</li>
  5443 + * <li>object - data object when using <i>mData</i></li>
  5444 + * <li>array of objects - multiple data objects when using <i>mData</i></li>
  5445 + * </ul>
  5446 + * @param {bool} [redraw=true] redraw the table or not
  5447 + * @returns {array} An array of integers, representing the list of indexes in
  5448 + * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
  5449 + * the table.
  5450 + * @dtopt API
  5451 + * @deprecated Since v1.10
  5452 + *
  5453 + * @example
  5454 + * // Global var for counter
  5455 + * var giCount = 2;
  5456 + *
  5457 + * $(document).ready(function() {
  5458 + * $('#example').dataTable();
  5459 + * } );
  5460 + *
  5461 + * function fnClickAddRow() {
  5462 + * $('#example').dataTable().fnAddData( [
  5463 + * giCount+".1",
  5464 + * giCount+".2",
  5465 + * giCount+".3",
  5466 + * giCount+".4" ]
  5467 + * );
  5468 + *
  5469 + * giCount++;
  5470 + * }
  5471 + */
  5472 + this.fnAddData = function( data, redraw )
  5473 + {
  5474 + var api = this.api( true );
  5475 +
  5476 + /* Check if we want to add multiple rows or not */
  5477 + var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
  5478 + api.rows.add( data ) :
  5479 + api.row.add( data );
  5480 +
  5481 + if ( redraw === undefined || redraw ) {
  5482 + api.draw();
  5483 + }
  5484 +
  5485 + return rows.flatten().toArray();
  5486 + };
  5487 +
  5488 +
  5489 + /**
  5490 + * This function will make DataTables recalculate the column sizes, based on the data
  5491 + * contained in the table and the sizes applied to the columns (in the DOM, CSS or
  5492 + * through the sWidth parameter). This can be useful when the width of the table's
  5493 + * parent element changes (for example a window resize).
  5494 + * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
  5495 + * @dtopt API
  5496 + * @deprecated Since v1.10
  5497 + *
  5498 + * @example
  5499 + * $(document).ready(function() {
  5500 + * var oTable = $('#example').dataTable( {
  5501 + * "sScrollY": "200px",
  5502 + * "bPaginate": false
  5503 + * } );
  5504 + *
  5505 + * $(window).bind('resize', function () {
  5506 + * oTable.fnAdjustColumnSizing();
  5507 + * } );
  5508 + * } );
  5509 + */
  5510 + this.fnAdjustColumnSizing = function ( bRedraw )
  5511 + {
  5512 + var api = this.api( true ).columns.adjust();
  5513 + var settings = api.settings()[0];
  5514 + var scroll = settings.oScroll;
  5515 +
  5516 + if ( bRedraw === undefined || bRedraw ) {
  5517 + api.draw( false );
  5518 + }
  5519 + else if ( scroll.sX !== "" || scroll.sY !== "" ) {
  5520 + /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
  5521 + _fnScrollDraw( settings );
  5522 + }
  5523 + };
  5524 +
  5525 +
  5526 + /**
  5527 + * Quickly and simply clear a table
  5528 + * @param {bool} [bRedraw=true] redraw the table or not
  5529 + * @dtopt API
  5530 + * @deprecated Since v1.10
  5531 + *
  5532 + * @example
  5533 + * $(document).ready(function() {
  5534 + * var oTable = $('#example').dataTable();
  5535 + *
  5536 + * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
  5537 + * oTable.fnClearTable();
  5538 + * } );
  5539 + */
  5540 + this.fnClearTable = function( bRedraw )
  5541 + {
  5542 + var api = this.api( true ).clear();
  5543 +
  5544 + if ( bRedraw === undefined || bRedraw ) {
  5545 + api.draw();
  5546 + }
  5547 + };
  5548 +
  5549 +
  5550 + /**
  5551 + * The exact opposite of 'opening' a row, this function will close any rows which
  5552 + * are currently 'open'.
  5553 + * @param {node} nTr the table row to 'close'
  5554 + * @returns {int} 0 on success, or 1 if failed (can't find the row)
  5555 + * @dtopt API
  5556 + * @deprecated Since v1.10
  5557 + *
  5558 + * @example
  5559 + * $(document).ready(function() {
  5560 + * var oTable;
  5561 + *
  5562 + * // 'open' an information row when a row is clicked on
  5563 + * $('#example tbody tr').click( function () {
  5564 + * if ( oTable.fnIsOpen(this) ) {
  5565 + * oTable.fnClose( this );
  5566 + * } else {
  5567 + * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  5568 + * }
  5569 + * } );
  5570 + *
  5571 + * oTable = $('#example').dataTable();
  5572 + * } );
  5573 + */
  5574 + this.fnClose = function( nTr )
  5575 + {
  5576 + this.api( true ).row( nTr ).child.hide();
  5577 + };
  5578 +
  5579 +
  5580 + /**
  5581 + * Remove a row for the table
  5582 + * @param {mixed} target The index of the row from aoData to be deleted, or
  5583 + * the TR element you want to delete
  5584 + * @param {function|null} [callBack] Callback function
  5585 + * @param {bool} [redraw=true] Redraw the table or not
  5586 + * @returns {array} The row that was deleted
  5587 + * @dtopt API
  5588 + * @deprecated Since v1.10
  5589 + *
  5590 + * @example
  5591 + * $(document).ready(function() {
  5592 + * var oTable = $('#example').dataTable();
  5593 + *
  5594 + * // Immediately remove the first row
  5595 + * oTable.fnDeleteRow( 0 );
  5596 + * } );
  5597 + */
  5598 + this.fnDeleteRow = function( target, callback, redraw )
  5599 + {
  5600 + var api = this.api( true );
  5601 + var rows = api.rows( target );
  5602 + var settings = rows.settings()[0];
  5603 + var data = settings.aoData[ rows[0][0] ];
  5604 +
  5605 + rows.remove();
  5606 +
  5607 + if ( callback ) {
  5608 + callback.call( this, settings, data );
  5609 + }
  5610 +
  5611 + if ( redraw === undefined || redraw ) {
  5612 + api.draw();
  5613 + }
  5614 +
  5615 + return data;
  5616 + };
  5617 +
  5618 +
  5619 + /**
  5620 + * Restore the table to it's original state in the DOM by removing all of DataTables
  5621 + * enhancements, alterations to the DOM structure of the table and event listeners.
  5622 + * @param {boolean} [remove=false] Completely remove the table from the DOM
  5623 + * @dtopt API
  5624 + * @deprecated Since v1.10
  5625 + *
  5626 + * @example
  5627 + * $(document).ready(function() {
  5628 + * // This example is fairly pointless in reality, but shows how fnDestroy can be used
  5629 + * var oTable = $('#example').dataTable();
  5630 + * oTable.fnDestroy();
  5631 + * } );
  5632 + */
  5633 + this.fnDestroy = function ( remove )
  5634 + {
  5635 + this.api( true ).destroy( remove );
  5636 + };
  5637 +
  5638 +
  5639 + /**
  5640 + * Redraw the table
  5641 + * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
  5642 + * @dtopt API
  5643 + * @deprecated Since v1.10
  5644 + *
  5645 + * @example
  5646 + * $(document).ready(function() {
  5647 + * var oTable = $('#example').dataTable();
  5648 + *
  5649 + * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
  5650 + * oTable.fnDraw();
  5651 + * } );
  5652 + */
  5653 + this.fnDraw = function( complete )
  5654 + {
  5655 + // Note that this isn't an exact match to the old call to _fnDraw - it takes
  5656 + // into account the new data, but can hold position.
  5657 + this.api( true ).draw( complete );
  5658 + };
  5659 +
  5660 +
  5661 + /**
  5662 + * Filter the input based on data
  5663 + * @param {string} sInput String to filter the table on
  5664 + * @param {int|null} [iColumn] Column to limit filtering to
  5665 + * @param {bool} [bRegex=false] Treat as regular expression or not
  5666 + * @param {bool} [bSmart=true] Perform smart filtering or not
  5667 + * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
  5668 + * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
  5669 + * @dtopt API
  5670 + * @deprecated Since v1.10
  5671 + *
  5672 + * @example
  5673 + * $(document).ready(function() {
  5674 + * var oTable = $('#example').dataTable();
  5675 + *
  5676 + * // Sometime later - filter...
  5677 + * oTable.fnFilter( 'test string' );
  5678 + * } );
  5679 + */
  5680 + this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
  5681 + {
  5682 + var api = this.api( true );
  5683 +
  5684 + if ( iColumn === null || iColumn === undefined ) {
  5685 + api.search( sInput, bRegex, bSmart, bCaseInsensitive );
  5686 + }
  5687 + else {
  5688 + api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
  5689 + }
  5690 +
  5691 + api.draw();
  5692 + };
  5693 +
  5694 +
  5695 + /**
  5696 + * Get the data for the whole table, an individual row or an individual cell based on the
  5697 + * provided parameters.
  5698 + * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
  5699 + * a TR node then the data source for the whole row will be returned. If given as a
  5700 + * TD/TH cell node then iCol will be automatically calculated and the data for the
  5701 + * cell returned. If given as an integer, then this is treated as the aoData internal
  5702 + * data index for the row (see fnGetPosition) and the data for that row used.
  5703 + * @param {int} [col] Optional column index that you want the data of.
  5704 + * @returns {array|object|string} If mRow is undefined, then the data for all rows is
  5705 + * returned. If mRow is defined, just data for that row, and is iCol is
  5706 + * defined, only data for the designated cell is returned.
  5707 + * @dtopt API
  5708 + * @deprecated Since v1.10
  5709 + *
  5710 + * @example
  5711 + * // Row data
  5712 + * $(document).ready(function() {
  5713 + * oTable = $('#example').dataTable();
  5714 + *
  5715 + * oTable.$('tr').click( function () {
  5716 + * var data = oTable.fnGetData( this );
  5717 + * // ... do something with the array / object of data for the row
  5718 + * } );
  5719 + * } );
  5720 + *
  5721 + * @example
  5722 + * // Individual cell data
  5723 + * $(document).ready(function() {
  5724 + * oTable = $('#example').dataTable();
  5725 + *
  5726 + * oTable.$('td').click( function () {
  5727 + * var sData = oTable.fnGetData( this );
  5728 + * alert( 'The cell clicked on had the value of '+sData );
  5729 + * } );
  5730 + * } );
  5731 + */
  5732 + this.fnGetData = function( src, col )
  5733 + {
  5734 + var api = this.api( true );
  5735 +
  5736 + if ( src !== undefined ) {
  5737 + var type = src.nodeName ? src.nodeName.toLowerCase() : '';
  5738 +
  5739 + return col !== undefined || type == 'td' || type == 'th' ?
  5740 + api.cell( src, col ).data() :
  5741 + api.row( src ).data() || null;
  5742 + }
  5743 +
  5744 + return api.data().toArray();
  5745 + };
  5746 +
  5747 +
  5748 + /**
  5749 + * Get an array of the TR nodes that are used in the table's body. Note that you will
  5750 + * typically want to use the '$' API method in preference to this as it is more
  5751 + * flexible.
  5752 + * @param {int} [iRow] Optional row index for the TR element you want
  5753 + * @returns {array|node} If iRow is undefined, returns an array of all TR elements
  5754 + * in the table's body, or iRow is defined, just the TR element requested.
  5755 + * @dtopt API
  5756 + * @deprecated Since v1.10
  5757 + *
  5758 + * @example
  5759 + * $(document).ready(function() {
  5760 + * var oTable = $('#example').dataTable();
  5761 + *
  5762 + * // Get the nodes from the table
  5763 + * var nNodes = oTable.fnGetNodes( );
  5764 + * } );
  5765 + */
  5766 + this.fnGetNodes = function( iRow )
  5767 + {
  5768 + var api = this.api( true );
  5769 +
  5770 + return iRow !== undefined ?
  5771 + api.row( iRow ).node() :
  5772 + api.rows().nodes().flatten().toArray();
  5773 + };
  5774 +
  5775 +
  5776 + /**
  5777 + * Get the array indexes of a particular cell from it's DOM element
  5778 + * and column index including hidden columns
  5779 + * @param {node} node this can either be a TR, TD or TH in the table's body
  5780 + * @returns {int} If nNode is given as a TR, then a single index is returned, or
  5781 + * if given as a cell, an array of [row index, column index (visible),
  5782 + * column index (all)] is given.
  5783 + * @dtopt API
  5784 + * @deprecated Since v1.10
  5785 + *
  5786 + * @example
  5787 + * $(document).ready(function() {
  5788 + * $('#example tbody td').click( function () {
  5789 + * // Get the position of the current data from the node
  5790 + * var aPos = oTable.fnGetPosition( this );
  5791 + *
  5792 + * // Get the data array for this row
  5793 + * var aData = oTable.fnGetData( aPos[0] );
  5794 + *
  5795 + * // Update the data array and return the value
  5796 + * aData[ aPos[1] ] = 'clicked';
  5797 + * this.innerHTML = 'clicked';
  5798 + * } );
  5799 + *
  5800 + * // Init DataTables
  5801 + * oTable = $('#example').dataTable();
  5802 + * } );
  5803 + */
  5804 + this.fnGetPosition = function( node )
  5805 + {
  5806 + var api = this.api( true );
  5807 + var nodeName = node.nodeName.toUpperCase();
  5808 +
  5809 + if ( nodeName == 'TR' ) {
  5810 + return api.row( node ).index();
  5811 + }
  5812 + else if ( nodeName == 'TD' || nodeName == 'TH' ) {
  5813 + var cell = api.cell( node ).index();
  5814 +
  5815 + return [
  5816 + cell.row,
  5817 + cell.columnVisible,
  5818 + cell.column
  5819 + ];
  5820 + }
  5821 + return null;
  5822 + };
  5823 +
  5824 +
  5825 + /**
  5826 + * Check to see if a row is 'open' or not.
  5827 + * @param {node} nTr the table row to check
  5828 + * @returns {boolean} true if the row is currently open, false otherwise
  5829 + * @dtopt API
  5830 + * @deprecated Since v1.10
  5831 + *
  5832 + * @example
  5833 + * $(document).ready(function() {
  5834 + * var oTable;
  5835 + *
  5836 + * // 'open' an information row when a row is clicked on
  5837 + * $('#example tbody tr').click( function () {
  5838 + * if ( oTable.fnIsOpen(this) ) {
  5839 + * oTable.fnClose( this );
  5840 + * } else {
  5841 + * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  5842 + * }
  5843 + * } );
  5844 + *
  5845 + * oTable = $('#example').dataTable();
  5846 + * } );
  5847 + */
  5848 + this.fnIsOpen = function( nTr )
  5849 + {
  5850 + return this.api( true ).row( nTr ).child.isShown();
  5851 + };
  5852 +
  5853 +
  5854 + /**
  5855 + * This function will place a new row directly after a row which is currently
  5856 + * on display on the page, with the HTML contents that is passed into the
  5857 + * function. This can be used, for example, to ask for confirmation that a
  5858 + * particular record should be deleted.
  5859 + * @param {node} nTr The table row to 'open'
  5860 + * @param {string|node|jQuery} mHtml The HTML to put into the row
  5861 + * @param {string} sClass Class to give the new TD cell
  5862 + * @returns {node} The row opened. Note that if the table row passed in as the
  5863 + * first parameter, is not found in the table, this method will silently
  5864 + * return.
  5865 + * @dtopt API
  5866 + * @deprecated Since v1.10
  5867 + *
  5868 + * @example
  5869 + * $(document).ready(function() {
  5870 + * var oTable;
  5871 + *
  5872 + * // 'open' an information row when a row is clicked on
  5873 + * $('#example tbody tr').click( function () {
  5874 + * if ( oTable.fnIsOpen(this) ) {
  5875 + * oTable.fnClose( this );
  5876 + * } else {
  5877 + * oTable.fnOpen( this, "Temporary row opened", "info_row" );
  5878 + * }
  5879 + * } );
  5880 + *
  5881 + * oTable = $('#example').dataTable();
  5882 + * } );
  5883 + */
  5884 + this.fnOpen = function( nTr, mHtml, sClass )
  5885 + {
  5886 + return this.api( true )
  5887 + .row( nTr )
  5888 + .child( mHtml, sClass )
  5889 + .show()
  5890 + .child()[0];
  5891 + };
  5892 +
  5893 +
  5894 + /**
  5895 + * Change the pagination - provides the internal logic for pagination in a simple API
  5896 + * function. With this function you can have a DataTables table go to the next,
  5897 + * previous, first or last pages.
  5898 + * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
  5899 + * or page number to jump to (integer), note that page 0 is the first page.
  5900 + * @param {bool} [bRedraw=true] Redraw the table or not
  5901 + * @dtopt API
  5902 + * @deprecated Since v1.10
  5903 + *
  5904 + * @example
  5905 + * $(document).ready(function() {
  5906 + * var oTable = $('#example').dataTable();
  5907 + * oTable.fnPageChange( 'next' );
  5908 + * } );
  5909 + */
  5910 + this.fnPageChange = function ( mAction, bRedraw )
  5911 + {
  5912 + var api = this.api( true ).page( mAction );
  5913 +
  5914 + if ( bRedraw === undefined || bRedraw ) {
  5915 + api.draw(false);
  5916 + }
  5917 + };
  5918 +
  5919 +
  5920 + /**
  5921 + * Show a particular column
  5922 + * @param {int} iCol The column whose display should be changed
  5923 + * @param {bool} bShow Show (true) or hide (false) the column
  5924 + * @param {bool} [bRedraw=true] Redraw the table or not
  5925 + * @dtopt API
  5926 + * @deprecated Since v1.10
  5927 + *
  5928 + * @example
  5929 + * $(document).ready(function() {
  5930 + * var oTable = $('#example').dataTable();
  5931 + *
  5932 + * // Hide the second column after initialisation
  5933 + * oTable.fnSetColumnVis( 1, false );
  5934 + * } );
  5935 + */
  5936 + this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
  5937 + {
  5938 + var api = this.api( true ).column( iCol ).visible( bShow );
  5939 +
  5940 + if ( bRedraw === undefined || bRedraw ) {
  5941 + api.columns.adjust().draw();
  5942 + }
  5943 + };
  5944 +
  5945 +
  5946 + /**
  5947 + * Get the settings for a particular table for external manipulation
  5948 + * @returns {object} DataTables settings object. See
  5949 + * {@link DataTable.models.oSettings}
  5950 + * @dtopt API
  5951 + * @deprecated Since v1.10
  5952 + *
  5953 + * @example
  5954 + * $(document).ready(function() {
  5955 + * var oTable = $('#example').dataTable();
  5956 + * var oSettings = oTable.fnSettings();
  5957 + *
  5958 + * // Show an example parameter from the settings
  5959 + * alert( oSettings._iDisplayStart );
  5960 + * } );
  5961 + */
  5962 + this.fnSettings = function()
  5963 + {
  5964 + return _fnSettingsFromNode( this[_ext.iApiIndex] );
  5965 + };
  5966 +
  5967 +
  5968 + /**
  5969 + * Sort the table by a particular column
  5970 + * @param {int} iCol the data index to sort on. Note that this will not match the
  5971 + * 'display index' if you have hidden data entries
  5972 + * @dtopt API
  5973 + * @deprecated Since v1.10
  5974 + *
  5975 + * @example
  5976 + * $(document).ready(function() {
  5977 + * var oTable = $('#example').dataTable();
  5978 + *
  5979 + * // Sort immediately with columns 0 and 1
  5980 + * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  5981 + * } );
  5982 + */
  5983 + this.fnSort = function( aaSort )
  5984 + {
  5985 + this.api( true ).order( aaSort ).draw();
  5986 + };
  5987 +
  5988 +
  5989 + /**
  5990 + * Attach a sort listener to an element for a given column
  5991 + * @param {node} nNode the element to attach the sort listener to
  5992 + * @param {int} iColumn the column that a click on this node will sort on
  5993 + * @param {function} [fnCallback] callback function when sort is run
  5994 + * @dtopt API
  5995 + * @deprecated Since v1.10
  5996 + *
  5997 + * @example
  5998 + * $(document).ready(function() {
  5999 + * var oTable = $('#example').dataTable();
  6000 + *
  6001 + * // Sort on column 1, when 'sorter' is clicked on
  6002 + * oTable.fnSortListener( document.getElementById('sorter'), 1 );
  6003 + * } );
  6004 + */
  6005 + this.fnSortListener = function( nNode, iColumn, fnCallback )
  6006 + {
  6007 + this.api( true ).order.listener( nNode, iColumn, fnCallback );
  6008 + };
  6009 +
  6010 +
  6011 + /**
  6012 + * Update a table cell or row - this method will accept either a single value to
  6013 + * update the cell with, an array of values with one element for each column or
  6014 + * an object in the same format as the original data source. The function is
  6015 + * self-referencing in order to make the multi column updates easier.
  6016 + * @param {object|array|string} mData Data to update the cell/row with
  6017 + * @param {node|int} mRow TR element you want to update or the aoData index
  6018 + * @param {int} [iColumn] The column to update, give as null or undefined to
  6019 + * update a whole row.
  6020 + * @param {bool} [bRedraw=true] Redraw the table or not
  6021 + * @param {bool} [bAction=true] Perform pre-draw actions or not
  6022 + * @returns {int} 0 on success, 1 on error
  6023 + * @dtopt API
  6024 + * @deprecated Since v1.10
  6025 + *
  6026 + * @example
  6027 + * $(document).ready(function() {
  6028 + * var oTable = $('#example').dataTable();
  6029 + * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
  6030 + * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
  6031 + * } );
  6032 + */
  6033 + this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
  6034 + {
  6035 + var api = this.api( true );
  6036 +
  6037 + if ( iColumn === undefined || iColumn === null ) {
  6038 + api.row( mRow ).data( mData );
  6039 + }
  6040 + else {
  6041 + api.cell( mRow, iColumn ).data( mData );
  6042 + }
  6043 +
  6044 + if ( bAction === undefined || bAction ) {
  6045 + api.columns.adjust();
  6046 + }
  6047 +
  6048 + if ( bRedraw === undefined || bRedraw ) {
  6049 + api.draw();
  6050 + }
  6051 + return 0;
  6052 + };
  6053 +
  6054 +
  6055 + /**
  6056 + * Provide a common method for plug-ins to check the version of DataTables being used, in order
  6057 + * to ensure compatibility.
  6058 + * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
  6059 + * formats "X" and "X.Y" are also acceptable.
  6060 + * @returns {boolean} true if this version of DataTables is greater or equal to the required
  6061 + * version, or false if this version of DataTales is not suitable
  6062 + * @method
  6063 + * @dtopt API
  6064 + * @deprecated Since v1.10
  6065 + *
  6066 + * @example
  6067 + * $(document).ready(function() {
  6068 + * var oTable = $('#example').dataTable();
  6069 + * alert( oTable.fnVersionCheck( '1.9.0' ) );
  6070 + * } );
  6071 + */
  6072 + this.fnVersionCheck = _ext.fnVersionCheck;
  6073 +
  6074 +
  6075 + var _that = this;
  6076 + var emptyInit = options === undefined;
  6077 + var len = this.length;
  6078 +
  6079 + if ( emptyInit ) {
  6080 + options = {};
  6081 + }
  6082 +
  6083 + this.oApi = this.internal = _ext.internal;
  6084 +
  6085 + // Extend with old style plug-in API methods
  6086 + for ( var fn in DataTable.ext.internal ) {
  6087 + if ( fn ) {
  6088 + this[fn] = _fnExternApiFunc(fn);
  6089 + }
  6090 + }
  6091 +
  6092 + this.each(function() {
  6093 + // For each initialisation we want to give it a clean initialisation
  6094 + // object that can be bashed around
  6095 + var o = {};
  6096 + var oInit = len > 1 ? // optimisation for single table case
  6097 + _fnExtend( o, options, true ) :
  6098 + options;
  6099 +
  6100 + /*global oInit,_that,emptyInit*/
  6101 + var i=0, iLen, j, jLen, k, kLen;
  6102 + var sId = this.getAttribute( 'id' );
  6103 + var bInitHandedOff = false;
  6104 + var defaults = DataTable.defaults;
  6105 + var $this = $(this);
  6106 +
  6107 +
  6108 + /* Sanity check */
  6109 + if ( this.nodeName.toLowerCase() != 'table' )
  6110 + {
  6111 + _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
  6112 + return;
  6113 + }
  6114 +
  6115 + /* Backwards compatibility for the defaults */
  6116 + _fnCompatOpts( defaults );
  6117 + _fnCompatCols( defaults.column );
  6118 +
  6119 + /* Convert the camel-case defaults to Hungarian */
  6120 + _fnCamelToHungarian( defaults, defaults, true );
  6121 + _fnCamelToHungarian( defaults.column, defaults.column, true );
  6122 +
  6123 + /* Setting up the initialisation object */
  6124 + _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
  6125 +
  6126 +
  6127 +
  6128 + /* Check to see if we are re-initialising a table */
  6129 + var allSettings = DataTable.settings;
  6130 + for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
  6131 + {
  6132 + var s = allSettings[i];
  6133 +
  6134 + /* Base check on table node */
  6135 + if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
  6136 + {
  6137 + var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
  6138 + var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
  6139 +
  6140 + if ( emptyInit || bRetrieve )
  6141 + {
  6142 + return s.oInstance;
  6143 + }
  6144 + else if ( bDestroy )
  6145 + {
  6146 + s.oInstance.fnDestroy();
  6147 + break;
  6148 + }
  6149 + else
  6150 + {
  6151 + _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
  6152 + return;
  6153 + }
  6154 + }
  6155 +
  6156 + /* If the element we are initialising has the same ID as a table which was previously
  6157 + * initialised, but the table nodes don't match (from before) then we destroy the old
  6158 + * instance by simply deleting it. This is under the assumption that the table has been
  6159 + * destroyed by other methods. Anyone using non-id selectors will need to do this manually
  6160 + */
  6161 + if ( s.sTableId == this.id )
  6162 + {
  6163 + allSettings.splice( i, 1 );
  6164 + break;
  6165 + }
  6166 + }
  6167 +
  6168 + /* Ensure the table has an ID - required for accessibility */
  6169 + if ( sId === null || sId === "" )
  6170 + {
  6171 + sId = "DataTables_Table_"+(DataTable.ext._unique++);
  6172 + this.id = sId;
  6173 + }
  6174 +
  6175 + /* Create the settings object for this table and set some of the default parameters */
  6176 + var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
  6177 + "sDestroyWidth": $this[0].style.width,
  6178 + "sInstance": sId,
  6179 + "sTableId": sId
  6180 + } );
  6181 + oSettings.nTable = this;
  6182 + oSettings.oApi = _that.internal;
  6183 + oSettings.oInit = oInit;
  6184 +
  6185 + allSettings.push( oSettings );
  6186 +
  6187 + // Need to add the instance after the instance after the settings object has been added
  6188 + // to the settings array, so we can self reference the table instance if more than one
  6189 + oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
  6190 +
  6191 + // Backwards compatibility, before we apply all the defaults
  6192 + _fnCompatOpts( oInit );
  6193 +
  6194 + if ( oInit.oLanguage )
  6195 + {
  6196 + _fnLanguageCompat( oInit.oLanguage );
  6197 + }
  6198 +
  6199 + // If the length menu is given, but the init display length is not, use the length menu
  6200 + if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
  6201 + {
  6202 + oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
  6203 + oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
  6204 + }
  6205 +
  6206 + // Apply the defaults and init options to make a single init object will all
  6207 + // options defined from defaults and instance options.
  6208 + oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
  6209 +
  6210 +
  6211 + // Map the initialisation options onto the settings object
  6212 + _fnMap( oSettings.oFeatures, oInit, [
  6213 + "bPaginate",
  6214 + "bLengthChange",
  6215 + "bFilter",
  6216 + "bSort",
  6217 + "bSortMulti",
  6218 + "bInfo",
  6219 + "bProcessing",
  6220 + "bAutoWidth",
  6221 + "bSortClasses",
  6222 + "bServerSide",
  6223 + "bDeferRender"
  6224 + ] );
  6225 + _fnMap( oSettings, oInit, [
  6226 + "asStripeClasses",
  6227 + "ajax",
  6228 + "fnServerData",
  6229 + "fnFormatNumber",
  6230 + "sServerMethod",
  6231 + "aaSorting",
  6232 + "aaSortingFixed",
  6233 + "aLengthMenu",
  6234 + "sPaginationType",
  6235 + "sAjaxSource",
  6236 + "sAjaxDataProp",
  6237 + "iStateDuration",
  6238 + "sDom",
  6239 + "bSortCellsTop",
  6240 + "iTabIndex",
  6241 + "fnStateLoadCallback",
  6242 + "fnStateSaveCallback",
  6243 + "renderer",
  6244 + "searchDelay",
  6245 + [ "iCookieDuration", "iStateDuration" ], // backwards compat
  6246 + [ "oSearch", "oPreviousSearch" ],
  6247 + [ "aoSearchCols", "aoPreSearchCols" ],
  6248 + [ "iDisplayLength", "_iDisplayLength" ],
  6249 + [ "bJQueryUI", "bJUI" ]
  6250 + ] );
  6251 + _fnMap( oSettings.oScroll, oInit, [
  6252 + [ "sScrollX", "sX" ],
  6253 + [ "sScrollXInner", "sXInner" ],
  6254 + [ "sScrollY", "sY" ],
  6255 + [ "bScrollCollapse", "bCollapse" ]
  6256 + ] );
  6257 + _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
  6258 +
  6259 + /* Callback functions which are array driven */
  6260 + _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
  6261 + _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
  6262 + _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
  6263 + _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
  6264 + _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
  6265 + _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
  6266 + _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
  6267 + _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
  6268 + _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
  6269 + _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
  6270 + _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
  6271 +
  6272 + var oClasses = oSettings.oClasses;
  6273 +
  6274 + // @todo Remove in 1.11
  6275 + if ( oInit.bJQueryUI )
  6276 + {
  6277 + /* Use the JUI classes object for display. You could clone the oStdClasses object if
  6278 + * you want to have multiple tables with multiple independent classes
  6279 + */
  6280 + $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
  6281 +
  6282 + if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
  6283 + {
  6284 + /* Set the DOM to use a layout suitable for jQuery UI's theming */
  6285 + oSettings.sDom = '<"H"lfr>t<"F"ip>';
  6286 + }
  6287 +
  6288 + if ( ! oSettings.renderer ) {
  6289 + oSettings.renderer = 'jqueryui';
  6290 + }
  6291 + else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
  6292 + oSettings.renderer.header = 'jqueryui';
  6293 + }
  6294 + }
  6295 + else
  6296 + {
  6297 + $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
  6298 + }
  6299 + $this.addClass( oClasses.sTable );
  6300 +
  6301 + /* Calculate the scroll bar width and cache it for use later on */
  6302 + if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
  6303 + {
  6304 + oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
  6305 + }
  6306 + if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
  6307 + oSettings.oScroll.sX = '100%';
  6308 + }
  6309 +
  6310 + if ( oSettings.iInitDisplayStart === undefined )
  6311 + {
  6312 + /* Display start point, taking into account the save saving */
  6313 + oSettings.iInitDisplayStart = oInit.iDisplayStart;
  6314 + oSettings._iDisplayStart = oInit.iDisplayStart;
  6315 + }
  6316 +
  6317 + if ( oInit.iDeferLoading !== null )
  6318 + {
  6319 + oSettings.bDeferLoading = true;
  6320 + var tmp = $.isArray( oInit.iDeferLoading );
  6321 + oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
  6322 + oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
  6323 + }
  6324 +
  6325 + /* Language definitions */
  6326 + var oLanguage = oSettings.oLanguage;
  6327 + $.extend( true, oLanguage, oInit.oLanguage );
  6328 +
  6329 + if ( oLanguage.sUrl !== "" )
  6330 + {
  6331 + /* Get the language definitions from a file - because this Ajax call makes the language
  6332 + * get async to the remainder of this function we use bInitHandedOff to indicate that
  6333 + * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
  6334 + */
  6335 + $.ajax( {
  6336 + dataType: 'json',
  6337 + url: oLanguage.sUrl,
  6338 + success: function ( json ) {
  6339 + _fnLanguageCompat( json );
  6340 + _fnCamelToHungarian( defaults.oLanguage, json );
  6341 + $.extend( true, oLanguage, json );
  6342 + _fnInitialise( oSettings );
  6343 + },
  6344 + error: function () {
  6345 + // Error occurred loading language file, continue on as best we can
  6346 + _fnInitialise( oSettings );
  6347 + }
  6348 + } );
  6349 + bInitHandedOff = true;
  6350 + }
  6351 +
  6352 + /*
  6353 + * Stripes
  6354 + */
  6355 + if ( oInit.asStripeClasses === null )
  6356 + {
  6357 + oSettings.asStripeClasses =[
  6358 + oClasses.sStripeOdd,
  6359 + oClasses.sStripeEven
  6360 + ];
  6361 + }
  6362 +
  6363 + /* Remove row stripe classes if they are already on the table row */
  6364 + var stripeClasses = oSettings.asStripeClasses;
  6365 + var rowOne = $this.children('tbody').find('tr').eq(0);
  6366 + if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
  6367 + return rowOne.hasClass(el);
  6368 + } ) ) !== -1 ) {
  6369 + $('tbody tr', this).removeClass( stripeClasses.join(' ') );
  6370 + oSettings.asDestroyStripes = stripeClasses.slice();
  6371 + }
  6372 +
  6373 + /*
  6374 + * Columns
  6375 + * See if we should load columns automatically or use defined ones
  6376 + */
  6377 + var anThs = [];
  6378 + var aoColumnsInit;
  6379 + var nThead = this.getElementsByTagName('thead');
  6380 + if ( nThead.length !== 0 )
  6381 + {
  6382 + _fnDetectHeader( oSettings.aoHeader, nThead[0] );
  6383 + anThs = _fnGetUniqueThs( oSettings );
  6384 + }
  6385 +
  6386 + /* If not given a column array, generate one with nulls */
  6387 + if ( oInit.aoColumns === null )
  6388 + {
  6389 + aoColumnsInit = [];
  6390 + for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
  6391 + {
  6392 + aoColumnsInit.push( null );
  6393 + }
  6394 + }
  6395 + else
  6396 + {
  6397 + aoColumnsInit = oInit.aoColumns;
  6398 + }
  6399 +
  6400 + /* Add the columns */
  6401 + for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
  6402 + {
  6403 + _fnAddColumn( oSettings, anThs ? anThs[i] : null );
  6404 + }
  6405 +
  6406 + /* Apply the column definitions */
  6407 + _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
  6408 + _fnColumnOptions( oSettings, iCol, oDef );
  6409 + } );
  6410 +
  6411 + /* HTML5 attribute detection - build an mData object automatically if the
  6412 + * attributes are found
  6413 + */
  6414 + if ( rowOne.length ) {
  6415 + var a = function ( cell, name ) {
  6416 + return cell.getAttribute( 'data-'+name ) !== null ? name : null;
  6417 + };
  6418 +
  6419 + $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
  6420 + var col = oSettings.aoColumns[i];
  6421 +
  6422 + if ( col.mData === i ) {
  6423 + var sort = a( cell, 'sort' ) || a( cell, 'order' );
  6424 + var filter = a( cell, 'filter' ) || a( cell, 'search' );
  6425 +
  6426 + if ( sort !== null || filter !== null ) {
  6427 + col.mData = {
  6428 + _: i+'.display',
  6429 + sort: sort !== null ? i+'.@data-'+sort : undefined,
  6430 + type: sort !== null ? i+'.@data-'+sort : undefined,
  6431 + filter: filter !== null ? i+'.@data-'+filter : undefined
  6432 + };
  6433 +
  6434 + _fnColumnOptions( oSettings, i );
  6435 + }
  6436 + }
  6437 + } );
  6438 + }
  6439 +
  6440 + var features = oSettings.oFeatures;
  6441 +
  6442 + /* Must be done after everything which can be overridden by the state saving! */
  6443 + if ( oInit.bStateSave )
  6444 + {
  6445 + features.bStateSave = true;
  6446 + _fnLoadState( oSettings, oInit );
  6447 + _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
  6448 + }
  6449 +
  6450 +
  6451 + /*
  6452 + * Sorting
  6453 + * @todo For modularisation (1.11) this needs to do into a sort start up handler
  6454 + */
  6455 +
  6456 + // If aaSorting is not defined, then we use the first indicator in asSorting
  6457 + // in case that has been altered, so the default sort reflects that option
  6458 + if ( oInit.aaSorting === undefined )
  6459 + {
  6460 + var sorting = oSettings.aaSorting;
  6461 + for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
  6462 + {
  6463 + sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
  6464 + }
  6465 + }
  6466 +
  6467 + /* Do a first pass on the sorting classes (allows any size changes to be taken into
  6468 + * account, and also will apply sorting disabled classes if disabled
  6469 + */
  6470 + _fnSortingClasses( oSettings );
  6471 +
  6472 + if ( features.bSort )
  6473 + {
  6474 + _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
  6475 + if ( oSettings.bSorted ) {
  6476 + var aSort = _fnSortFlatten( oSettings );
  6477 + var sortedColumns = {};
  6478 +
  6479 + $.each( aSort, function (i, val) {
  6480 + sortedColumns[ val.src ] = val.dir;
  6481 + } );
  6482 +
  6483 + _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
  6484 + _fnSortAria( oSettings );
  6485 + }
  6486 + } );
  6487 + }
  6488 +
  6489 + _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
  6490 + if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
  6491 + _fnSortingClasses( oSettings );
  6492 + }
  6493 + }, 'sc' );
  6494 +
  6495 +
  6496 + /*
  6497 + * Final init
  6498 + * Cache the header, body and footer as required, creating them if needed
  6499 + */
  6500 +
  6501 + /* Browser support detection */
  6502 + _fnBrowserDetect( oSettings );
  6503 +
  6504 + // Work around for Webkit bug 83867 - store the caption-side before removing from doc
  6505 + var captions = $this.children('caption').each( function () {
  6506 + this._captionSide = $this.css('caption-side');
  6507 + } );
  6508 +
  6509 + var thead = $this.children('thead');
  6510 + if ( thead.length === 0 )
  6511 + {
  6512 + thead = $('<thead/>').appendTo(this);
  6513 + }
  6514 + oSettings.nTHead = thead[0];
  6515 +
  6516 + var tbody = $this.children('tbody');
  6517 + if ( tbody.length === 0 )
  6518 + {
  6519 + tbody = $('<tbody/>').appendTo(this);
  6520 + }
  6521 + oSettings.nTBody = tbody[0];
  6522 +
  6523 + var tfoot = $this.children('tfoot');
  6524 + if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
  6525 + {
  6526 + // If we are a scrolling table, and no footer has been given, then we need to create
  6527 + // a tfoot element for the caption element to be appended to
  6528 + tfoot = $('<tfoot/>').appendTo(this);
  6529 + }
  6530 +
  6531 + if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
  6532 + $this.addClass( oClasses.sNoFooter );
  6533 + }
  6534 + else if ( tfoot.length > 0 ) {
  6535 + oSettings.nTFoot = tfoot[0];
  6536 + _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
  6537 + }
  6538 +
  6539 + /* Check if there is data passing into the constructor */
  6540 + if ( oInit.aaData )
  6541 + {
  6542 + for ( i=0 ; i<oInit.aaData.length ; i++ )
  6543 + {
  6544 + _fnAddData( oSettings, oInit.aaData[ i ] );
  6545 + }
  6546 + }
  6547 + else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
  6548 + {
  6549 + /* Grab the data from the page - only do this when deferred loading or no Ajax
  6550 + * source since there is no point in reading the DOM data if we are then going
  6551 + * to replace it with Ajax data
  6552 + */
  6553 + _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
  6554 + }
  6555 +
  6556 + /* Copy the data index array */
  6557 + oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
  6558 +
  6559 + /* Initialisation complete - table can be drawn */
  6560 + oSettings.bInitialised = true;
  6561 +
  6562 + /* Check if we need to initialise the table (it might not have been handed off to the
  6563 + * language processor)
  6564 + */
  6565 + if ( bInitHandedOff === false )
  6566 + {
  6567 + _fnInitialise( oSettings );
  6568 + }
  6569 + } );
  6570 + _that = null;
  6571 + return this;
  6572 + };
  6573 +
  6574 +
  6575 +
  6576 + /**
  6577 + * Computed structure of the DataTables API, defined by the options passed to
  6578 + * `DataTable.Api.register()` when building the API.
  6579 + *
  6580 + * The structure is built in order to speed creation and extension of the Api
  6581 + * objects since the extensions are effectively pre-parsed.
  6582 + *
  6583 + * The array is an array of objects with the following structure, where this
  6584 + * base array represents the Api prototype base:
  6585 + *
  6586 + * [
  6587 + * {
  6588 + * name: 'data' -- string - Property name
  6589 + * val: function () {}, -- function - Api method (or undefined if just an object
  6590 + * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  6591 + * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  6592 + * },
  6593 + * {
  6594 + * name: 'row'
  6595 + * val: {},
  6596 + * methodExt: [ ... ],
  6597 + * propExt: [
  6598 + * {
  6599 + * name: 'data'
  6600 + * val: function () {},
  6601 + * methodExt: [ ... ],
  6602 + * propExt: [ ... ]
  6603 + * },
  6604 + * ...
  6605 + * ]
  6606 + * }
  6607 + * ]
  6608 + *
  6609 + * @type {Array}
  6610 + * @ignore
  6611 + */
  6612 + var __apiStruct = [];
  6613 +
  6614 +
  6615 + /**
  6616 + * `Array.prototype` reference.
  6617 + *
  6618 + * @type object
  6619 + * @ignore
  6620 + */
  6621 + var __arrayProto = Array.prototype;
  6622 +
  6623 +
  6624 + /**
  6625 + * Abstraction for `context` parameter of the `Api` constructor to allow it to
  6626 + * take several different forms for ease of use.
  6627 + *
  6628 + * Each of the input parameter types will be converted to a DataTables settings
  6629 + * object where possible.
  6630 + *
  6631 + * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
  6632 + * of:
  6633 + *
  6634 + * * `string` - jQuery selector. Any DataTables' matching the given selector
  6635 + * with be found and used.
  6636 + * * `node` - `TABLE` node which has already been formed into a DataTable.
  6637 + * * `jQuery` - A jQuery object of `TABLE` nodes.
  6638 + * * `object` - DataTables settings object
  6639 + * * `DataTables.Api` - API instance
  6640 + * @return {array|null} Matching DataTables settings objects. `null` or
  6641 + * `undefined` is returned if no matching DataTable is found.
  6642 + * @ignore
  6643 + */
  6644 + var _toSettings = function ( mixed )
  6645 + {
  6646 + var idx, jq;
  6647 + var settings = DataTable.settings;
  6648 + var tables = $.map( settings, function (el, i) {
  6649 + return el.nTable;
  6650 + } );
  6651 +
  6652 + if ( ! mixed ) {
  6653 + return [];
  6654 + }
  6655 + else if ( mixed.nTable && mixed.oApi ) {
  6656 + // DataTables settings object
  6657 + return [ mixed ];
  6658 + }
  6659 + else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
  6660 + // Table node
  6661 + idx = $.inArray( mixed, tables );
  6662 + return idx !== -1 ? [ settings[idx] ] : null;
  6663 + }
  6664 + else if ( mixed && typeof mixed.settings === 'function' ) {
  6665 + return mixed.settings().toArray();
  6666 + }
  6667 + else if ( typeof mixed === 'string' ) {
  6668 + // jQuery selector
  6669 + jq = $(mixed);
  6670 + }
  6671 + else if ( mixed instanceof $ ) {
  6672 + // jQuery object (also DataTables instance)
  6673 + jq = mixed;
  6674 + }
  6675 +
  6676 + if ( jq ) {
  6677 + return jq.map( function(i) {
  6678 + idx = $.inArray( this, tables );
  6679 + return idx !== -1 ? settings[idx] : null;
  6680 + } ).toArray();
  6681 + }
  6682 + };
  6683 +
  6684 +
  6685 + /**
  6686 + * DataTables API class - used to control and interface with one or more
  6687 + * DataTables enhanced tables.
  6688 + *
  6689 + * The API class is heavily based on jQuery, presenting a chainable interface
  6690 + * that you can use to interact with tables. Each instance of the API class has
  6691 + * a "context" - i.e. the tables that it will operate on. This could be a single
  6692 + * table, all tables on a page or a sub-set thereof.
  6693 + *
  6694 + * Additionally the API is designed to allow you to easily work with the data in
  6695 + * the tables, retrieving and manipulating it as required. This is done by
  6696 + * presenting the API class as an array like interface. The contents of the
  6697 + * array depend upon the actions requested by each method (for example
  6698 + * `rows().nodes()` will return an array of nodes, while `rows().data()` will
  6699 + * return an array of objects or arrays depending upon your table's
  6700 + * configuration). The API object has a number of array like methods (`push`,
  6701 + * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
  6702 + * `unique` etc) to assist your working with the data held in a table.
  6703 + *
  6704 + * Most methods (those which return an Api instance) are chainable, which means
  6705 + * the return from a method call also has all of the methods available that the
  6706 + * top level object had. For example, these two calls are equivalent:
  6707 + *
  6708 + * // Not chained
  6709 + * api.row.add( {...} );
  6710 + * api.draw();
  6711 + *
  6712 + * // Chained
  6713 + * api.row.add( {...} ).draw();
  6714 + *
  6715 + * @class DataTable.Api
  6716 + * @param {array|object|string|jQuery} context DataTable identifier. This is
  6717 + * used to define which DataTables enhanced tables this API will operate on.
  6718 + * Can be one of:
  6719 + *
  6720 + * * `string` - jQuery selector. Any DataTables' matching the given selector
  6721 + * with be found and used.
  6722 + * * `node` - `TABLE` node which has already been formed into a DataTable.
  6723 + * * `jQuery` - A jQuery object of `TABLE` nodes.
  6724 + * * `object` - DataTables settings object
  6725 + * @param {array} [data] Data to initialise the Api instance with.
  6726 + *
  6727 + * @example
  6728 + * // Direct initialisation during DataTables construction
  6729 + * var api = $('#example').DataTable();
  6730 + *
  6731 + * @example
  6732 + * // Initialisation using a DataTables jQuery object
  6733 + * var api = $('#example').dataTable().api();
  6734 + *
  6735 + * @example
  6736 + * // Initialisation as a constructor
  6737 + * var api = new $.fn.DataTable.Api( 'table.dataTable' );
  6738 + */
  6739 + _Api = function ( context, data )
  6740 + {
  6741 + if ( ! (this instanceof _Api) ) {
  6742 + return new _Api( context, data );
  6743 + }
  6744 +
  6745 + var settings = [];
  6746 + var ctxSettings = function ( o ) {
  6747 + var a = _toSettings( o );
  6748 + if ( a ) {
  6749 + settings.push.apply( settings, a );
  6750 + }
  6751 + };
  6752 +
  6753 + if ( $.isArray( context ) ) {
  6754 + for ( var i=0, ien=context.length ; i<ien ; i++ ) {
  6755 + ctxSettings( context[i] );
  6756 + }
  6757 + }
  6758 + else {
  6759 + ctxSettings( context );
  6760 + }
  6761 +
  6762 + // Remove duplicates
  6763 + this.context = _unique( settings );
  6764 +
  6765 + // Initial data
  6766 + if ( data ) {
  6767 + this.push.apply( this, data.toArray ? data.toArray() : data );
  6768 + }
  6769 +
  6770 + // selector
  6771 + this.selector = {
  6772 + rows: null,
  6773 + cols: null,
  6774 + opts: null
  6775 + };
  6776 +
  6777 + _Api.extend( this, this, __apiStruct );
  6778 + };
  6779 +
  6780 + DataTable.Api = _Api;
  6781 +
  6782 + _Api.prototype = /** @lends DataTables.Api */{
  6783 + any: function ()
  6784 + {
  6785 + return this.flatten().length !== 0;
  6786 + },
  6787 +
  6788 +
  6789 + concat: __arrayProto.concat,
  6790 +
  6791 +
  6792 + context: [], // array of table settings objects
  6793 +
  6794 +
  6795 + each: function ( fn )
  6796 + {
  6797 + for ( var i=0, ien=this.length ; i<ien; i++ ) {
  6798 + fn.call( this, this[i], i, this );
  6799 + }
  6800 +
  6801 + return this;
  6802 + },
  6803 +
  6804 +
  6805 + eq: function ( idx )
  6806 + {
  6807 + var ctx = this.context;
  6808 +
  6809 + return ctx.length > idx ?
  6810 + new _Api( ctx[idx], this[idx] ) :
  6811 + null;
  6812 + },
  6813 +
  6814 +
  6815 + filter: function ( fn )
  6816 + {
  6817 + var a = [];
  6818 +
  6819 + if ( __arrayProto.filter ) {
  6820 + a = __arrayProto.filter.call( this, fn, this );
  6821 + }
  6822 + else {
  6823 + // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6824 + for ( var i=0, ien=this.length ; i<ien ; i++ ) {
  6825 + if ( fn.call( this, this[i], i, this ) ) {
  6826 + a.push( this[i] );
  6827 + }
  6828 + }
  6829 + }
  6830 +
  6831 + return new _Api( this.context, a );
  6832 + },
  6833 +
  6834 +
  6835 + flatten: function ()
  6836 + {
  6837 + var a = [];
  6838 + return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
  6839 + },
  6840 +
  6841 +
  6842 + join: __arrayProto.join,
  6843 +
  6844 +
  6845 + indexOf: __arrayProto.indexOf || function (obj, start)
  6846 + {
  6847 + for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
  6848 + if ( this[i] === obj ) {
  6849 + return i;
  6850 + }
  6851 + }
  6852 + return -1;
  6853 + },
  6854 +
  6855 + iterator: function ( flatten, type, fn, alwaysNew ) {
  6856 + var
  6857 + a = [], ret,
  6858 + i, ien, j, jen,
  6859 + context = this.context,
  6860 + rows, items, item,
  6861 + selector = this.selector;
  6862 +
  6863 + // Argument shifting
  6864 + if ( typeof flatten === 'string' ) {
  6865 + alwaysNew = fn;
  6866 + fn = type;
  6867 + type = flatten;
  6868 + flatten = false;
  6869 + }
  6870 +
  6871 + for ( i=0, ien=context.length ; i<ien ; i++ ) {
  6872 + var apiInst = new _Api( context[i] );
  6873 +
  6874 + if ( type === 'table' ) {
  6875 + ret = fn.call( apiInst, context[i], i );
  6876 +
  6877 + if ( ret !== undefined ) {
  6878 + a.push( ret );
  6879 + }
  6880 + }
  6881 + else if ( type === 'columns' || type === 'rows' ) {
  6882 + // this has same length as context - one entry for each table
  6883 + ret = fn.call( apiInst, context[i], this[i], i );
  6884 +
  6885 + if ( ret !== undefined ) {
  6886 + a.push( ret );
  6887 + }
  6888 + }
  6889 + else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
  6890 + // columns and rows share the same structure.
  6891 + // 'this' is an array of column indexes for each context
  6892 + items = this[i];
  6893 +
  6894 + if ( type === 'column-rows' ) {
  6895 + rows = _selector_row_indexes( context[i], selector.opts );
  6896 + }
  6897 +
  6898 + for ( j=0, jen=items.length ; j<jen ; j++ ) {
  6899 + item = items[j];
  6900 +
  6901 + if ( type === 'cell' ) {
  6902 + ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
  6903 + }
  6904 + else {
  6905 + ret = fn.call( apiInst, context[i], item, i, j, rows );
  6906 + }
  6907 +
  6908 + if ( ret !== undefined ) {
  6909 + a.push( ret );
  6910 + }
  6911 + }
  6912 + }
  6913 + }
  6914 +
  6915 + if ( a.length || alwaysNew ) {
  6916 + var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
  6917 + var apiSelector = api.selector;
  6918 + apiSelector.rows = selector.rows;
  6919 + apiSelector.cols = selector.cols;
  6920 + apiSelector.opts = selector.opts;
  6921 + return api;
  6922 + }
  6923 + return this;
  6924 + },
  6925 +
  6926 +
  6927 + lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
  6928 + {
  6929 + // Bit cheeky...
  6930 + return this.indexOf.apply( this.toArray.reverse(), arguments );
  6931 + },
  6932 +
  6933 +
  6934 + length: 0,
  6935 +
  6936 +
  6937 + map: function ( fn )
  6938 + {
  6939 + var a = [];
  6940 +
  6941 + if ( __arrayProto.map ) {
  6942 + a = __arrayProto.map.call( this, fn, this );
  6943 + }
  6944 + else {
  6945 + // Compatibility for browsers without EMCA-252-5 (JS 1.6)
  6946 + for ( var i=0, ien=this.length ; i<ien ; i++ ) {
  6947 + a.push( fn.call( this, this[i], i ) );
  6948 + }
  6949 + }
  6950 +
  6951 + return new _Api( this.context, a );
  6952 + },
  6953 +
  6954 +
  6955 + pluck: function ( prop )
  6956 + {
  6957 + return this.map( function ( el ) {
  6958 + return el[ prop ];
  6959 + } );
  6960 + },
  6961 +
  6962 + pop: __arrayProto.pop,
  6963 +
  6964 +
  6965 + push: __arrayProto.push,
  6966 +
  6967 +
  6968 + // Does not return an API instance
  6969 + reduce: __arrayProto.reduce || function ( fn, init )
  6970 + {
  6971 + return _fnReduce( this, fn, init, 0, this.length, 1 );
  6972 + },
  6973 +
  6974 +
  6975 + reduceRight: __arrayProto.reduceRight || function ( fn, init )
  6976 + {
  6977 + return _fnReduce( this, fn, init, this.length-1, -1, -1 );
  6978 + },
  6979 +
  6980 +
  6981 + reverse: __arrayProto.reverse,
  6982 +
  6983 +
  6984 + // Object with rows, columns and opts
  6985 + selector: null,
  6986 +
  6987 +
  6988 + shift: __arrayProto.shift,
  6989 +
  6990 +
  6991 + sort: __arrayProto.sort, // ? name - order?
  6992 +
  6993 +
  6994 + splice: __arrayProto.splice,
  6995 +
  6996 +
  6997 + toArray: function ()
  6998 + {
  6999 + return __arrayProto.slice.call( this );
  7000 + },
  7001 +
  7002 +
  7003 + to$: function ()
  7004 + {
  7005 + return $( this );
  7006 + },
  7007 +
  7008 +
  7009 + toJQuery: function ()
  7010 + {
  7011 + return $( this );
  7012 + },
  7013 +
  7014 +
  7015 + unique: function ()
  7016 + {
  7017 + return new _Api( this.context, _unique(this) );
  7018 + },
  7019 +
  7020 +
  7021 + unshift: __arrayProto.unshift
  7022 + };
  7023 +
  7024 +
  7025 + _Api.extend = function ( scope, obj, ext )
  7026 + {
  7027 + // Only extend API instances and static properties of the API
  7028 + if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
  7029 + return;
  7030 + }
  7031 +
  7032 + var
  7033 + i, ien,
  7034 + j, jen,
  7035 + struct, inner,
  7036 + methodScoping = function ( scope, fn, struc ) {
  7037 + return function () {
  7038 + var ret = fn.apply( scope, arguments );
  7039 +
  7040 + // Method extension
  7041 + _Api.extend( ret, ret, struc.methodExt );
  7042 + return ret;
  7043 + };
  7044 + };
  7045 +
  7046 + for ( i=0, ien=ext.length ; i<ien ; i++ ) {
  7047 + struct = ext[i];
  7048 +
  7049 + // Value
  7050 + obj[ struct.name ] = typeof struct.val === 'function' ?
  7051 + methodScoping( scope, struct.val, struct ) :
  7052 + $.isPlainObject( struct.val ) ?
  7053 + {} :
  7054 + struct.val;
  7055 +
  7056 + obj[ struct.name ].__dt_wrapper = true;
  7057 +
  7058 + // Property extension
  7059 + _Api.extend( scope, obj[ struct.name ], struct.propExt );
  7060 + }
  7061 + };
  7062 +
  7063 +
  7064 + // @todo - Is there need for an augment function?
  7065 + // _Api.augment = function ( inst, name )
  7066 + // {
  7067 + // // Find src object in the structure from the name
  7068 + // var parts = name.split('.');
  7069 +
  7070 + // _Api.extend( inst, obj );
  7071 + // };
  7072 +
  7073 +
  7074 + // [
  7075 + // {
  7076 + // name: 'data' -- string - Property name
  7077 + // val: function () {}, -- function - Api method (or undefined if just an object
  7078 + // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
  7079 + // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
  7080 + // },
  7081 + // {
  7082 + // name: 'row'
  7083 + // val: {},
  7084 + // methodExt: [ ... ],
  7085 + // propExt: [
  7086 + // {
  7087 + // name: 'data'
  7088 + // val: function () {},
  7089 + // methodExt: [ ... ],
  7090 + // propExt: [ ... ]
  7091 + // },
  7092 + // ...
  7093 + // ]
  7094 + // }
  7095 + // ]
  7096 +
  7097 + _Api.register = _api_register = function ( name, val )
  7098 + {
  7099 + if ( $.isArray( name ) ) {
  7100 + for ( var j=0, jen=name.length ; j<jen ; j++ ) {
  7101 + _Api.register( name[j], val );
  7102 + }
  7103 + return;
  7104 + }
  7105 +
  7106 + var
  7107 + i, ien,
  7108 + heir = name.split('.'),
  7109 + struct = __apiStruct,
  7110 + key, method;
  7111 +
  7112 + var find = function ( src, name ) {
  7113 + for ( var i=0, ien=src.length ; i<ien ; i++ ) {
  7114 + if ( src[i].name === name ) {
  7115 + return src[i];
  7116 + }
  7117 + }
  7118 + return null;
  7119 + };
  7120 +
  7121 + for ( i=0, ien=heir.length ; i<ien ; i++ ) {
  7122 + method = heir[i].indexOf('()') !== -1;
  7123 + key = method ?
  7124 + heir[i].replace('()', '') :
  7125 + heir[i];
  7126 +
  7127 + var src = find( struct, key );
  7128 + if ( ! src ) {
  7129 + src = {
  7130 + name: key,
  7131 + val: {},
  7132 + methodExt: [],
  7133 + propExt: []
  7134 + };
  7135 + struct.push( src );
  7136 + }
  7137 +
  7138 + if ( i === ien-1 ) {
  7139 + src.val = val;
  7140 + }
  7141 + else {
  7142 + struct = method ?
  7143 + src.methodExt :
  7144 + src.propExt;
  7145 + }
  7146 + }
  7147 + };
  7148 +
  7149 +
  7150 + _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
  7151 + _Api.register( pluralName, val );
  7152 +
  7153 + _Api.register( singularName, function () {
  7154 + var ret = val.apply( this, arguments );
  7155 +
  7156 + if ( ret === this ) {
  7157 + // Returned item is the API instance that was passed in, return it
  7158 + return this;
  7159 + }
  7160 + else if ( ret instanceof _Api ) {
  7161 + // New API instance returned, want the value from the first item
  7162 + // in the returned array for the singular result.
  7163 + return ret.length ?
  7164 + $.isArray( ret[0] ) ?
  7165 + new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
  7166 + ret[0] :
  7167 + undefined;
  7168 + }
  7169 +
  7170 + // Non-API return - just fire it back
  7171 + return ret;
  7172 + } );
  7173 + };
  7174 +
  7175 +
  7176 + /**
  7177 + * Selector for HTML tables. Apply the given selector to the give array of
  7178 + * DataTables settings objects.
  7179 + *
  7180 + * @param {string|integer} [selector] jQuery selector string or integer
  7181 + * @param {array} Array of DataTables settings objects to be filtered
  7182 + * @return {array}
  7183 + * @ignore
  7184 + */
  7185 + var __table_selector = function ( selector, a )
  7186 + {
  7187 + // Integer is used to pick out a table by index
  7188 + if ( typeof selector === 'number' ) {
  7189 + return [ a[ selector ] ];
  7190 + }
  7191 +
  7192 + // Perform a jQuery selector on the table nodes
  7193 + var nodes = $.map( a, function (el, i) {
  7194 + return el.nTable;
  7195 + } );
  7196 +
  7197 + return $(nodes)
  7198 + .filter( selector )
  7199 + .map( function (i) {
  7200 + // Need to translate back from the table node to the settings
  7201 + var idx = $.inArray( this, nodes );
  7202 + return a[ idx ];
  7203 + } )
  7204 + .toArray();
  7205 + };
  7206 +
  7207 +
  7208 +
  7209 + /**
  7210 + * Context selector for the API's context (i.e. the tables the API instance
  7211 + * refers to.
  7212 + *
  7213 + * @name DataTable.Api#tables
  7214 + * @param {string|integer} [selector] Selector to pick which tables the iterator
  7215 + * should operate on. If not given, all tables in the current context are
  7216 + * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
  7217 + * select multiple tables or as an integer to select a single table.
  7218 + * @returns {DataTable.Api} Returns a new API instance if a selector is given.
  7219 + */
  7220 + _api_register( 'tables()', function ( selector ) {
  7221 + // A new instance is created if there was a selector specified
  7222 + return selector ?
  7223 + new _Api( __table_selector( selector, this.context ) ) :
  7224 + this;
  7225 + } );
  7226 +
  7227 +
  7228 + _api_register( 'table()', function ( selector ) {
  7229 + var tables = this.tables( selector );
  7230 + var ctx = tables.context;
  7231 +
  7232 + // Truncate to the first matched table
  7233 + return ctx.length ?
  7234 + new _Api( ctx[0] ) :
  7235 + tables;
  7236 + } );
  7237 +
  7238 +
  7239 + _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
  7240 + return this.iterator( 'table', function ( ctx ) {
  7241 + return ctx.nTable;
  7242 + }, 1 );
  7243 + } );
  7244 +
  7245 +
  7246 + _api_registerPlural( 'tables().body()', 'table().body()' , function () {
  7247 + return this.iterator( 'table', function ( ctx ) {
  7248 + return ctx.nTBody;
  7249 + }, 1 );
  7250 + } );
  7251 +
  7252 +
  7253 + _api_registerPlural( 'tables().header()', 'table().header()' , function () {
  7254 + return this.iterator( 'table', function ( ctx ) {
  7255 + return ctx.nTHead;
  7256 + }, 1 );
  7257 + } );
  7258 +
  7259 +
  7260 + _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
  7261 + return this.iterator( 'table', function ( ctx ) {
  7262 + return ctx.nTFoot;
  7263 + }, 1 );
  7264 + } );
  7265 +
  7266 +
  7267 + _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
  7268 + return this.iterator( 'table', function ( ctx ) {
  7269 + return ctx.nTableWrapper;
  7270 + }, 1 );
  7271 + } );
  7272 +
  7273 +
  7274 +
  7275 + /**
  7276 + * Redraw the tables in the current context.
  7277 + *
  7278 + * @param {boolean} [reset=true] Reset (default) or hold the current paging
  7279 + * position. A full re-sort and re-filter is performed when this method is
  7280 + * called, which is why the pagination reset is the default action.
  7281 + * @returns {DataTables.Api} this
  7282 + */
  7283 + _api_register( 'draw()', function ( resetPaging ) {
  7284 + return this.iterator( 'table', function ( settings ) {
  7285 + _fnReDraw( settings, resetPaging===false );
  7286 + } );
  7287 + } );
  7288 +
  7289 +
  7290 +
  7291 + /**
  7292 + * Get the current page index.
  7293 + *
  7294 + * @return {integer} Current page index (zero based)
  7295 + *//**
  7296 + * Set the current page.
  7297 + *
  7298 + * Note that if you attempt to show a page which does not exist, DataTables will
  7299 + * not throw an error, but rather reset the paging.
  7300 + *
  7301 + * @param {integer|string} action The paging action to take. This can be one of:
  7302 + * * `integer` - The page index to jump to
  7303 + * * `string` - An action to take:
  7304 + * * `first` - Jump to first page.
  7305 + * * `next` - Jump to the next page
  7306 + * * `previous` - Jump to previous page
  7307 + * * `last` - Jump to the last page.
  7308 + * @returns {DataTables.Api} this
  7309 + */
  7310 + _api_register( 'page()', function ( action ) {
  7311 + if ( action === undefined ) {
  7312 + return this.page.info().page; // not an expensive call
  7313 + }
  7314 +
  7315 + // else, have an action to take on all tables
  7316 + return this.iterator( 'table', function ( settings ) {
  7317 + _fnPageChange( settings, action );
  7318 + } );
  7319 + } );
  7320 +
  7321 +
  7322 + /**
  7323 + * Paging information for the first table in the current context.
  7324 + *
  7325 + * If you require paging information for another table, use the `table()` method
  7326 + * with a suitable selector.
  7327 + *
  7328 + * @return {object} Object with the following properties set:
  7329 + * * `page` - Current page index (zero based - i.e. the first page is `0`)
  7330 + * * `pages` - Total number of pages
  7331 + * * `start` - Display index for the first record shown on the current page
  7332 + * * `end` - Display index for the last record shown on the current page
  7333 + * * `length` - Display length (number of records). Note that generally `start
  7334 + * + length = end`, but this is not always true, for example if there are
  7335 + * only 2 records to show on the final page, with a length of 10.
  7336 + * * `recordsTotal` - Full data set length
  7337 + * * `recordsDisplay` - Data set length once the current filtering criterion
  7338 + * are applied.
  7339 + */
  7340 + _api_register( 'page.info()', function ( action ) {
  7341 + if ( this.context.length === 0 ) {
  7342 + return undefined;
  7343 + }
  7344 +
  7345 + var
  7346 + settings = this.context[0],
  7347 + start = settings._iDisplayStart,
  7348 + len = settings._iDisplayLength,
  7349 + visRecords = settings.fnRecordsDisplay(),
  7350 + all = len === -1;
  7351 +
  7352 + return {
  7353 + "page": all ? 0 : Math.floor( start / len ),
  7354 + "pages": all ? 1 : Math.ceil( visRecords / len ),
  7355 + "start": start,
  7356 + "end": settings.fnDisplayEnd(),
  7357 + "length": len,
  7358 + "recordsTotal": settings.fnRecordsTotal(),
  7359 + "recordsDisplay": visRecords
  7360 + };
  7361 + } );
  7362 +
  7363 +
  7364 + /**
  7365 + * Get the current page length.
  7366 + *
  7367 + * @return {integer} Current page length. Note `-1` indicates that all records
  7368 + * are to be shown.
  7369 + *//**
  7370 + * Set the current page length.
  7371 + *
  7372 + * @param {integer} Page length to set. Use `-1` to show all records.
  7373 + * @returns {DataTables.Api} this
  7374 + */
  7375 + _api_register( 'page.len()', function ( len ) {
  7376 + // Note that we can't call this function 'length()' because `length`
  7377 + // is a Javascript property of functions which defines how many arguments
  7378 + // the function expects.
  7379 + if ( len === undefined ) {
  7380 + return this.context.length !== 0 ?
  7381 + this.context[0]._iDisplayLength :
  7382 + undefined;
  7383 + }
  7384 +
  7385 + // else, set the page length
  7386 + return this.iterator( 'table', function ( settings ) {
  7387 + _fnLengthChange( settings, len );
  7388 + } );
  7389 + } );
  7390 +
  7391 +
  7392 +
  7393 + var __reload = function ( settings, holdPosition, callback ) {
  7394 + // Use the draw event to trigger a callback
  7395 + if ( callback ) {
  7396 + var api = new _Api( settings );
  7397 +
  7398 + api.one( 'draw', function () {
  7399 + callback( api.ajax.json() );
  7400 + } );
  7401 + }
  7402 +
  7403 + if ( _fnDataSource( settings ) == 'ssp' ) {
  7404 + _fnReDraw( settings, holdPosition );
  7405 + }
  7406 + else {
  7407 + // Trigger xhr
  7408 + _fnProcessingDisplay( settings, true );
  7409 +
  7410 + _fnBuildAjax( settings, [], function( json ) {
  7411 + _fnClearTable( settings );
  7412 +
  7413 + var data = _fnAjaxDataSrc( settings, json );
  7414 + for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  7415 + _fnAddData( settings, data[i] );
  7416 + }
  7417 +
  7418 + _fnReDraw( settings, holdPosition );
  7419 + _fnProcessingDisplay( settings, false );
  7420 + } );
  7421 + }
  7422 + };
  7423 +
  7424 +
  7425 + /**
  7426 + * Get the JSON response from the last Ajax request that DataTables made to the
  7427 + * server. Note that this returns the JSON from the first table in the current
  7428 + * context.
  7429 + *
  7430 + * @return {object} JSON received from the server.
  7431 + */
  7432 + _api_register( 'ajax.json()', function () {
  7433 + var ctx = this.context;
  7434 +
  7435 + if ( ctx.length > 0 ) {
  7436 + return ctx[0].json;
  7437 + }
  7438 +
  7439 + // else return undefined;
  7440 + } );
  7441 +
  7442 +
  7443 + /**
  7444 + * Get the data submitted in the last Ajax request
  7445 + */
  7446 + _api_register( 'ajax.params()', function () {
  7447 + var ctx = this.context;
  7448 +
  7449 + if ( ctx.length > 0 ) {
  7450 + return ctx[0].oAjaxData;
  7451 + }
  7452 +
  7453 + // else return undefined;
  7454 + } );
  7455 +
  7456 +
  7457 + /**
  7458 + * Reload tables from the Ajax data source. Note that this function will
  7459 + * automatically re-draw the table when the remote data has been loaded.
  7460 + *
  7461 + * @param {boolean} [reset=true] Reset (default) or hold the current paging
  7462 + * position. A full re-sort and re-filter is performed when this method is
  7463 + * called, which is why the pagination reset is the default action.
  7464 + * @returns {DataTables.Api} this
  7465 + */
  7466 + _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
  7467 + return this.iterator( 'table', function (settings) {
  7468 + __reload( settings, resetPaging===false, callback );
  7469 + } );
  7470 + } );
  7471 +
  7472 +
  7473 + /**
  7474 + * Get the current Ajax URL. Note that this returns the URL from the first
  7475 + * table in the current context.
  7476 + *
  7477 + * @return {string} Current Ajax source URL
  7478 + *//**
  7479 + * Set the Ajax URL. Note that this will set the URL for all tables in the
  7480 + * current context.
  7481 + *
  7482 + * @param {string} url URL to set.
  7483 + * @returns {DataTables.Api} this
  7484 + */
  7485 + _api_register( 'ajax.url()', function ( url ) {
  7486 + var ctx = this.context;
  7487 +
  7488 + if ( url === undefined ) {
  7489 + // get
  7490 + if ( ctx.length === 0 ) {
  7491 + return undefined;
  7492 + }
  7493 + ctx = ctx[0];
  7494 +
  7495 + return ctx.ajax ?
  7496 + $.isPlainObject( ctx.ajax ) ?
  7497 + ctx.ajax.url :
  7498 + ctx.ajax :
  7499 + ctx.sAjaxSource;
  7500 + }
  7501 +
  7502 + // set
  7503 + return this.iterator( 'table', function ( settings ) {
  7504 + if ( $.isPlainObject( settings.ajax ) ) {
  7505 + settings.ajax.url = url;
  7506 + }
  7507 + else {
  7508 + settings.ajax = url;
  7509 + }
  7510 + // No need to consider sAjaxSource here since DataTables gives priority
  7511 + // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
  7512 + // value of `sAjaxSource` redundant.
  7513 + } );
  7514 + } );
  7515 +
  7516 +
  7517 + /**
  7518 + * Load data from the newly set Ajax URL. Note that this method is only
  7519 + * available when `ajax.url()` is used to set a URL. Additionally, this method
  7520 + * has the same effect as calling `ajax.reload()` but is provided for
  7521 + * convenience when setting a new URL. Like `ajax.reload()` it will
  7522 + * automatically redraw the table once the remote data has been loaded.
  7523 + *
  7524 + * @returns {DataTables.Api} this
  7525 + */
  7526 + _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
  7527 + // Same as a reload, but makes sense to present it for easy access after a
  7528 + // url change
  7529 + return this.iterator( 'table', function ( ctx ) {
  7530 + __reload( ctx, resetPaging===false, callback );
  7531 + } );
  7532 + } );
  7533 +
  7534 +
  7535 +
  7536 +
  7537 + var _selector_run = function ( type, selector, selectFn, settings, opts )
  7538 + {
  7539 + var
  7540 + out = [], res,
  7541 + a, i, ien, j, jen,
  7542 + selectorType = typeof selector;
  7543 +
  7544 + // Can't just check for isArray here, as an API or jQuery instance might be
  7545 + // given with their array like look
  7546 + if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
  7547 + selector = [ selector ];
  7548 + }
  7549 +
  7550 + for ( i=0, ien=selector.length ; i<ien ; i++ ) {
  7551 + a = selector[i] && selector[i].split ?
  7552 + selector[i].split(',') :
  7553 + [ selector[i] ];
  7554 +
  7555 + for ( j=0, jen=a.length ; j<jen ; j++ ) {
  7556 + res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
  7557 +
  7558 + if ( res && res.length ) {
  7559 + out.push.apply( out, res );
  7560 + }
  7561 + }
  7562 + }
  7563 +
  7564 + // selector extensions
  7565 + var ext = _ext.selector[ type ];
  7566 + if ( ext.length ) {
  7567 + for ( i=0, ien=ext.length ; i<ien ; i++ ) {
  7568 + out = ext[i]( settings, opts, out );
  7569 + }
  7570 + }
  7571 +
  7572 + return out;
  7573 + };
  7574 +
  7575 +
  7576 + var _selector_opts = function ( opts )
  7577 + {
  7578 + if ( ! opts ) {
  7579 + opts = {};
  7580 + }
  7581 +
  7582 + // Backwards compatibility for 1.9- which used the terminology filter rather
  7583 + // than search
  7584 + if ( opts.filter && opts.search === undefined ) {
  7585 + opts.search = opts.filter;
  7586 + }
  7587 +
  7588 + return $.extend( {
  7589 + search: 'none',
  7590 + order: 'current',
  7591 + page: 'all'
  7592 + }, opts );
  7593 + };
  7594 +
  7595 +
  7596 + var _selector_first = function ( inst )
  7597 + {
  7598 + // Reduce the API instance to the first item found
  7599 + for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
  7600 + if ( inst[i].length > 0 ) {
  7601 + // Assign the first element to the first item in the instance
  7602 + // and truncate the instance and context
  7603 + inst[0] = inst[i];
  7604 + inst[0].length = 1;
  7605 + inst.length = 1;
  7606 + inst.context = [ inst.context[i] ];
  7607 +
  7608 + return inst;
  7609 + }
  7610 + }
  7611 +
  7612 + // Not found - return an empty instance
  7613 + inst.length = 0;
  7614 + return inst;
  7615 + };
  7616 +
  7617 +
  7618 + var _selector_row_indexes = function ( settings, opts )
  7619 + {
  7620 + var
  7621 + i, ien, tmp, a=[],
  7622 + displayFiltered = settings.aiDisplay,
  7623 + displayMaster = settings.aiDisplayMaster;
  7624 +
  7625 + var
  7626 + search = opts.search, // none, applied, removed
  7627 + order = opts.order, // applied, current, index (original - compatibility with 1.9)
  7628 + page = opts.page; // all, current
  7629 +
  7630 + if ( _fnDataSource( settings ) == 'ssp' ) {
  7631 + // In server-side processing mode, most options are irrelevant since
  7632 + // rows not shown don't exist and the index order is the applied order
  7633 + // Removed is a special case - for consistency just return an empty
  7634 + // array
  7635 + return search === 'removed' ?
  7636 + [] :
  7637 + _range( 0, displayMaster.length );
  7638 + }
  7639 + else if ( page == 'current' ) {
  7640 + // Current page implies that order=current and fitler=applied, since it is
  7641 + // fairly senseless otherwise, regardless of what order and search actually
  7642 + // are
  7643 + for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
  7644 + a.push( displayFiltered[i] );
  7645 + }
  7646 + }
  7647 + else if ( order == 'current' || order == 'applied' ) {
  7648 + a = search == 'none' ?
  7649 + displayMaster.slice() : // no search
  7650 + search == 'applied' ?
  7651 + displayFiltered.slice() : // applied search
  7652 + $.map( displayMaster, function (el, i) { // removed search
  7653 + return $.inArray( el, displayFiltered ) === -1 ? el : null;
  7654 + } );
  7655 + }
  7656 + else if ( order == 'index' || order == 'original' ) {
  7657 + for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
  7658 + if ( search == 'none' ) {
  7659 + a.push( i );
  7660 + }
  7661 + else { // applied | removed
  7662 + tmp = $.inArray( i, displayFiltered );
  7663 +
  7664 + if ((tmp === -1 && search == 'removed') ||
  7665 + (tmp >= 0 && search == 'applied') )
  7666 + {
  7667 + a.push( i );
  7668 + }
  7669 + }
  7670 + }
  7671 + }
  7672 +
  7673 + return a;
  7674 + };
  7675 +
  7676 +
  7677 + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  7678 + * Rows
  7679 + *
  7680 + * {} - no selector - use all available rows
  7681 + * {integer} - row aoData index
  7682 + * {node} - TR node
  7683 + * {string} - jQuery selector to apply to the TR elements
  7684 + * {array} - jQuery array of nodes, or simply an array of TR nodes
  7685 + *
  7686 + */
  7687 +
  7688 +
  7689 + var __row_selector = function ( settings, selector, opts )
  7690 + {
  7691 + var run = function ( sel ) {
  7692 + var selInt = _intVal( sel );
  7693 + var i, ien;
  7694 +
  7695 + // Short cut - selector is a number and no options provided (default is
  7696 + // all records, so no need to check if the index is in there, since it
  7697 + // must be - dev error if the index doesn't exist).
  7698 + if ( selInt !== null && ! opts ) {
  7699 + return [ selInt ];
  7700 + }
  7701 +
  7702 + var rows = _selector_row_indexes( settings, opts );
  7703 +
  7704 + if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
  7705 + // Selector - integer
  7706 + return [ selInt ];
  7707 + }
  7708 + else if ( ! sel ) {
  7709 + // Selector - none
  7710 + return rows;
  7711 + }
  7712 +
  7713 + // Selector - function
  7714 + if ( typeof sel === 'function' ) {
  7715 + return $.map( rows, function (idx) {
  7716 + var row = settings.aoData[ idx ];
  7717 + return sel( idx, row._aData, row.nTr ) ? idx : null;
  7718 + } );
  7719 + }
  7720 +
  7721 + // Get nodes in the order from the `rows` array with null values removed
  7722 + var nodes = _removeEmpty(
  7723 + _pluck_order( settings.aoData, rows, 'nTr' )
  7724 + );
  7725 +
  7726 + // Selector - node
  7727 + if ( sel.nodeName ) {
  7728 + if ( $.inArray( sel, nodes ) !== -1 ) {
  7729 + return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
  7730 + // and DataTables adds a prop for fast lookup
  7731 + }
  7732 + }
  7733 +
  7734 + // Selector - jQuery selector string, array of nodes or jQuery object/
  7735 + // As jQuery's .filter() allows jQuery objects to be passed in filter,
  7736 + // it also allows arrays, so this will cope with all three options
  7737 + return $(nodes)
  7738 + .filter( sel )
  7739 + .map( function () {
  7740 + return this._DT_RowIndex;
  7741 + } )
  7742 + .toArray();
  7743 + };
  7744 +
  7745 + return _selector_run( 'row', selector, run, settings, opts );
  7746 + };
  7747 +
  7748 +
  7749 + _api_register( 'rows()', function ( selector, opts ) {
  7750 + // argument shifting
  7751 + if ( selector === undefined ) {
  7752 + selector = '';
  7753 + }
  7754 + else if ( $.isPlainObject( selector ) ) {
  7755 + opts = selector;
  7756 + selector = '';
  7757 + }
  7758 +
  7759 + opts = _selector_opts( opts );
  7760 +
  7761 + var inst = this.iterator( 'table', function ( settings ) {
  7762 + return __row_selector( settings, selector, opts );
  7763 + }, 1 );
  7764 +
  7765 + // Want argument shifting here and in __row_selector?
  7766 + inst.selector.rows = selector;
  7767 + inst.selector.opts = opts;
  7768 +
  7769 + return inst;
  7770 + } );
  7771 +
  7772 + _api_register( 'rows().nodes()', function () {
  7773 + return this.iterator( 'row', function ( settings, row ) {
  7774 + return settings.aoData[ row ].nTr || undefined;
  7775 + }, 1 );
  7776 + } );
  7777 +
  7778 + _api_register( 'rows().data()', function () {
  7779 + return this.iterator( true, 'rows', function ( settings, rows ) {
  7780 + return _pluck_order( settings.aoData, rows, '_aData' );
  7781 + }, 1 );
  7782 + } );
  7783 +
  7784 + _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
  7785 + return this.iterator( 'row', function ( settings, row ) {
  7786 + var r = settings.aoData[ row ];
  7787 + return type === 'search' ? r._aFilterData : r._aSortData;
  7788 + }, 1 );
  7789 + } );
  7790 +
  7791 + _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
  7792 + return this.iterator( 'row', function ( settings, row ) {
  7793 + _fnInvalidate( settings, row, src );
  7794 + } );
  7795 + } );
  7796 +
  7797 + _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
  7798 + return this.iterator( 'row', function ( settings, row ) {
  7799 + return row;
  7800 + }, 1 );
  7801 + } );
  7802 +
  7803 + _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
  7804 + var that = this;
  7805 +
  7806 + return this.iterator( 'row', function ( settings, row, thatIdx ) {
  7807 + var data = settings.aoData;
  7808 +
  7809 + data.splice( row, 1 );
  7810 +
  7811 + // Update the _DT_RowIndex parameter on all rows in the table
  7812 + for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  7813 + if ( data[i].nTr !== null ) {
  7814 + data[i].nTr._DT_RowIndex = i;
  7815 + }
  7816 + }
  7817 +
  7818 + // Remove the target row from the search array
  7819 + var displayIndex = $.inArray( row, settings.aiDisplay );
  7820 +
  7821 + // Delete from the display arrays
  7822 + _fnDeleteIndex( settings.aiDisplayMaster, row );
  7823 + _fnDeleteIndex( settings.aiDisplay, row );
  7824 + _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
  7825 +
  7826 + // Check for an 'overflow' they case for displaying the table
  7827 + _fnLengthOverflow( settings );
  7828 + } );
  7829 + } );
  7830 +
  7831 +
  7832 + _api_register( 'rows.add()', function ( rows ) {
  7833 + var newRows = this.iterator( 'table', function ( settings ) {
  7834 + var row, i, ien;
  7835 + var out = [];
  7836 +
  7837 + for ( i=0, ien=rows.length ; i<ien ; i++ ) {
  7838 + row = rows[i];
  7839 +
  7840 + if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
  7841 + out.push( _fnAddTr( settings, row )[0] );
  7842 + }
  7843 + else {
  7844 + out.push( _fnAddData( settings, row ) );
  7845 + }
  7846 + }
  7847 +
  7848 + return out;
  7849 + }, 1 );
  7850 +
  7851 + // Return an Api.rows() extended instance, so rows().nodes() etc can be used
  7852 + var modRows = this.rows( -1 );
  7853 + modRows.pop();
  7854 + modRows.push.apply( modRows, newRows.toArray() );
  7855 +
  7856 + return modRows;
  7857 + } );
  7858 +
  7859 +
  7860 +
  7861 +
  7862 +
  7863 + /**
  7864 + *
  7865 + */
  7866 + _api_register( 'row()', function ( selector, opts ) {
  7867 + return _selector_first( this.rows( selector, opts ) );
  7868 + } );
  7869 +
  7870 +
  7871 + _api_register( 'row().data()', function ( data ) {
  7872 + var ctx = this.context;
  7873 +
  7874 + if ( data === undefined ) {
  7875 + // Get
  7876 + return ctx.length && this.length ?
  7877 + ctx[0].aoData[ this[0] ]._aData :
  7878 + undefined;
  7879 + }
  7880 +
  7881 + // Set
  7882 + ctx[0].aoData[ this[0] ]._aData = data;
  7883 +
  7884 + // Automatically invalidate
  7885 + _fnInvalidate( ctx[0], this[0], 'data' );
  7886 +
  7887 + return this;
  7888 + } );
  7889 +
  7890 +
  7891 + _api_register( 'row().node()', function () {
  7892 + var ctx = this.context;
  7893 +
  7894 + return ctx.length && this.length ?
  7895 + ctx[0].aoData[ this[0] ].nTr || null :
  7896 + null;
  7897 + } );
  7898 +
  7899 +
  7900 + _api_register( 'row.add()', function ( row ) {
  7901 + // Allow a jQuery object to be passed in - only a single row is added from
  7902 + // it though - the first element in the set
  7903 + if ( row instanceof $ && row.length ) {
  7904 + row = row[0];
  7905 + }
  7906 +
  7907 + var rows = this.iterator( 'table', function ( settings ) {
  7908 + if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
  7909 + return _fnAddTr( settings, row )[0];
  7910 + }
  7911 + return _fnAddData( settings, row );
  7912 + } );
  7913 +
  7914 + // Return an Api.rows() extended instance, with the newly added row selected
  7915 + return this.row( rows[0] );
  7916 + } );
  7917 +
  7918 +
  7919 +
  7920 + var __details_add = function ( ctx, row, data, klass )
  7921 + {
  7922 + // Convert to array of TR elements
  7923 + var rows = [];
  7924 + var addRow = function ( r, k ) {
  7925 + // Recursion to allow for arrays of jQuery objects
  7926 + if ( $.isArray( r ) || r instanceof $ ) {
  7927 + for ( var i=0, ien=r.length ; i<ien ; i++ ) {
  7928 + addRow( r[i], k );
  7929 + }
  7930 + return;
  7931 + }
  7932 +
  7933 + // If we get a TR element, then just add it directly - up to the dev
  7934 + // to add the correct number of columns etc
  7935 + if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
  7936 + rows.push( r );
  7937 + }
  7938 + else {
  7939 + // Otherwise create a row with a wrapper
  7940 + var created = $('<tr><td/></tr>').addClass( k );
  7941 + $('td', created)
  7942 + .addClass( k )
  7943 + .html( r )
  7944 + [0].colSpan = _fnVisbleColumns( ctx );
  7945 +
  7946 + rows.push( created[0] );
  7947 + }
  7948 + };
  7949 +
  7950 + addRow( data, klass );
  7951 +
  7952 + if ( row._details ) {
  7953 + row._details.remove();
  7954 + }
  7955 +
  7956 + row._details = $(rows);
  7957 +
  7958 + // If the children were already shown, that state should be retained
  7959 + if ( row._detailsShow ) {
  7960 + row._details.insertAfter( row.nTr );
  7961 + }
  7962 + };
  7963 +
  7964 +
  7965 + var __details_remove = function ( api, idx )
  7966 + {
  7967 + var ctx = api.context;
  7968 +
  7969 + if ( ctx.length ) {
  7970 + var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
  7971 +
  7972 + if ( row._details ) {
  7973 + row._details.remove();
  7974 +
  7975 + row._detailsShow = undefined;
  7976 + row._details = undefined;
  7977 + }
  7978 + }
  7979 + };
  7980 +
  7981 +
  7982 + var __details_display = function ( api, show ) {
  7983 + var ctx = api.context;
  7984 +
  7985 + if ( ctx.length && api.length ) {
  7986 + var row = ctx[0].aoData[ api[0] ];
  7987 +
  7988 + if ( row._details ) {
  7989 + row._detailsShow = show;
  7990 +
  7991 + if ( show ) {
  7992 + row._details.insertAfter( row.nTr );
  7993 + }
  7994 + else {
  7995 + row._details.detach();
  7996 + }
  7997 +
  7998 + __details_events( ctx[0] );
  7999 + }
  8000 + }
  8001 + };
  8002 +
  8003 +
  8004 + var __details_events = function ( settings )
  8005 + {
  8006 + var api = new _Api( settings );
  8007 + var namespace = '.dt.DT_details';
  8008 + var drawEvent = 'draw'+namespace;
  8009 + var colvisEvent = 'column-visibility'+namespace;
  8010 + var destroyEvent = 'destroy'+namespace;
  8011 + var data = settings.aoData;
  8012 +
  8013 + api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
  8014 +
  8015 + if ( _pluck( data, '_details' ).length > 0 ) {
  8016 + // On each draw, insert the required elements into the document
  8017 + api.on( drawEvent, function ( e, ctx ) {
  8018 + if ( settings !== ctx ) {
  8019 + return;
  8020 + }
  8021 +
  8022 + api.rows( {page:'current'} ).eq(0).each( function (idx) {
  8023 + // Internal data grab
  8024 + var row = data[ idx ];
  8025 +
  8026 + if ( row._detailsShow ) {
  8027 + row._details.insertAfter( row.nTr );
  8028 + }
  8029 + } );
  8030 + } );
  8031 +
  8032 + // Column visibility change - update the colspan
  8033 + api.on( colvisEvent, function ( e, ctx, idx, vis ) {
  8034 + if ( settings !== ctx ) {
  8035 + return;
  8036 + }
  8037 +
  8038 + // Update the colspan for the details rows (note, only if it already has
  8039 + // a colspan)
  8040 + var row, visible = _fnVisbleColumns( ctx );
  8041 +
  8042 + for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  8043 + row = data[i];
  8044 +
  8045 + if ( row._details ) {
  8046 + row._details.children('td[colspan]').attr('colspan', visible );
  8047 + }
  8048 + }
  8049 + } );
  8050 +
  8051 + // Table destroyed - nuke any child rows
  8052 + api.on( destroyEvent, function ( e, ctx ) {
  8053 + if ( settings !== ctx ) {
  8054 + return;
  8055 + }
  8056 +
  8057 + for ( var i=0, ien=data.length ; i<ien ; i++ ) {
  8058 + if ( data[i]._details ) {
  8059 + __details_remove( api, i );
  8060 + }
  8061 + }
  8062 + } );
  8063 + }
  8064 + };
  8065 +
  8066 + // Strings for the method names to help minification
  8067 + var _emp = '';
  8068 + var _child_obj = _emp+'row().child';
  8069 + var _child_mth = _child_obj+'()';
  8070 +
  8071 + // data can be:
  8072 + // tr
  8073 + // string
  8074 + // jQuery or array of any of the above
  8075 + _api_register( _child_mth, function ( data, klass ) {
  8076 + var ctx = this.context;
  8077 +
  8078 + if ( data === undefined ) {
  8079 + // get
  8080 + return ctx.length && this.length ?
  8081 + ctx[0].aoData[ this[0] ]._details :
  8082 + undefined;
  8083 + }
  8084 + else if ( data === true ) {
  8085 + // show
  8086 + this.child.show();
  8087 + }
  8088 + else if ( data === false ) {
  8089 + // remove
  8090 + __details_remove( this );
  8091 + }
  8092 + else if ( ctx.length && this.length ) {
  8093 + // set
  8094 + __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
  8095 + }
  8096 +
  8097 + return this;
  8098 + } );
  8099 +
  8100 +
  8101 + _api_register( [
  8102 + _child_obj+'.show()',
  8103 + _child_mth+'.show()' // only when `child()` was called with parameters (without
  8104 + ], function ( show ) { // it returns an object and this method is not executed)
  8105 + __details_display( this, true );
  8106 + return this;
  8107 + } );
  8108 +
  8109 +
  8110 + _api_register( [
  8111 + _child_obj+'.hide()',
  8112 + _child_mth+'.hide()' // only when `child()` was called with parameters (without
  8113 + ], function () { // it returns an object and this method is not executed)
  8114 + __details_display( this, false );
  8115 + return this;
  8116 + } );
  8117 +
  8118 +
  8119 + _api_register( [
  8120 + _child_obj+'.remove()',
  8121 + _child_mth+'.remove()' // only when `child()` was called with parameters (without
  8122 + ], function () { // it returns an object and this method is not executed)
  8123 + __details_remove( this );
  8124 + return this;
  8125 + } );
  8126 +
  8127 +
  8128 + _api_register( _child_obj+'.isShown()', function () {
  8129 + var ctx = this.context;
  8130 +
  8131 + if ( ctx.length && this.length ) {
  8132 + // _detailsShown as false or undefined will fall through to return false
  8133 + return ctx[0].aoData[ this[0] ]._detailsShow || false;
  8134 + }
  8135 + return false;
  8136 + } );
  8137 +
  8138 +
  8139 +
  8140 + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  8141 + * Columns
  8142 + *
  8143 + * {integer} - column index (>=0 count from left, <0 count from right)
  8144 + * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
  8145 + * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
  8146 + * "{string}:name" - column name
  8147 + * "{string}" - jQuery selector on column header nodes
  8148 + *
  8149 + */
  8150 +
  8151 + // can be an array of these items, comma separated list, or an array of comma
  8152 + // separated lists
  8153 +
  8154 + var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
  8155 +
  8156 +
  8157 + // r1 and r2 are redundant - but it means that the parameters match for the
  8158 + // iterator callback in columns().data()
  8159 + var __columnData = function ( settings, column, r1, r2, rows ) {
  8160 + var a = [];
  8161 + for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
  8162 + a.push( _fnGetCellData( settings, rows[row], column ) );
  8163 + }
  8164 + return a;
  8165 + };
  8166 +
  8167 +
  8168 + var __column_selector = function ( settings, selector, opts )
  8169 + {
  8170 + var
  8171 + columns = settings.aoColumns,
  8172 + names = _pluck( columns, 'sName' ),
  8173 + nodes = _pluck( columns, 'nTh' );
  8174 +
  8175 + var run = function ( s ) {
  8176 + var selInt = _intVal( s );
  8177 +
  8178 + // Selector - all
  8179 + if ( s === '' ) {
  8180 + return _range( columns.length );
  8181 + }
  8182 +
  8183 + // Selector - index
  8184 + if ( selInt !== null ) {
  8185 + return [ selInt >= 0 ?
  8186 + selInt : // Count from left
  8187 + columns.length + selInt // Count from right (+ because its a negative value)
  8188 + ];
  8189 + }
  8190 +
  8191 + // Selector = function
  8192 + if ( typeof s === 'function' ) {
  8193 + var rows = _selector_row_indexes( settings, opts );
  8194 +
  8195 + return $.map( columns, function (col, idx) {
  8196 + return s(
  8197 + idx,
  8198 + __columnData( settings, idx, 0, 0, rows ),
  8199 + nodes[ idx ]
  8200 + ) ? idx : null;
  8201 + } );
  8202 + }
  8203 +
  8204 + // jQuery or string selector
  8205 + var match = typeof s === 'string' ?
  8206 + s.match( __re_column_selector ) :
  8207 + '';
  8208 +
  8209 + if ( match ) {
  8210 + switch( match[2] ) {
  8211 + case 'visIdx':
  8212 + case 'visible':
  8213 + var idx = parseInt( match[1], 10 );
  8214 + // Visible index given, convert to column index
  8215 + if ( idx < 0 ) {
  8216 + // Counting from the right
  8217 + var visColumns = $.map( columns, function (col,i) {
  8218 + return col.bVisible ? i : null;
  8219 + } );
  8220 + return [ visColumns[ visColumns.length + idx ] ];
  8221 + }
  8222 + // Counting from the left
  8223 + return [ _fnVisibleToColumnIndex( settings, idx ) ];
  8224 +
  8225 + case 'name':
  8226 + // match by name. `names` is column index complete and in order
  8227 + return $.map( names, function (name, i) {
  8228 + return name === match[1] ? i : null;
  8229 + } );
  8230 + }
  8231 + }
  8232 + else {
  8233 + // jQuery selector on the TH elements for the columns
  8234 + return $( nodes )
  8235 + .filter( s )
  8236 + .map( function () {
  8237 + return $.inArray( this, nodes ); // `nodes` is column index complete and in order
  8238 + } )
  8239 + .toArray();
  8240 + }
  8241 + };
  8242 +
  8243 + return _selector_run( 'column', selector, run, settings, opts );
  8244 + };
  8245 +
  8246 +
  8247 + var __setColumnVis = function ( settings, column, vis, recalc ) {
  8248 + var
  8249 + cols = settings.aoColumns,
  8250 + col = cols[ column ],
  8251 + data = settings.aoData,
  8252 + row, cells, i, ien, tr;
  8253 +
  8254 + // Get
  8255 + if ( vis === undefined ) {
  8256 + return col.bVisible;
  8257 + }
  8258 +
  8259 + // Set
  8260 + // No change
  8261 + if ( col.bVisible === vis ) {
  8262 + return;
  8263 + }
  8264 +
  8265 + if ( vis ) {
  8266 + // Insert column
  8267 + // Need to decide if we should use appendChild or insertBefore
  8268 + var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
  8269 +
  8270 + for ( i=0, ien=data.length ; i<ien ; i++ ) {
  8271 + tr = data[i].nTr;
  8272 + cells = data[i].anCells;
  8273 +
  8274 + if ( tr ) {
  8275 + // insertBefore can act like appendChild if 2nd arg is null
  8276 + tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
  8277 + }
  8278 + }
  8279 + }
  8280 + else {
  8281 + // Remove column
  8282 + $( _pluck( settings.aoData, 'anCells', column ) ).detach();
  8283 + }
  8284 +
  8285 + // Common actions
  8286 + col.bVisible = vis;
  8287 + _fnDrawHead( settings, settings.aoHeader );
  8288 + _fnDrawHead( settings, settings.aoFooter );
  8289 +
  8290 + if ( recalc === undefined || recalc ) {
  8291 + // Automatically adjust column sizing
  8292 + _fnAdjustColumnSizing( settings );
  8293 +
  8294 + // Realign columns for scrolling
  8295 + if ( settings.oScroll.sX || settings.oScroll.sY ) {
  8296 + _fnScrollDraw( settings );
  8297 + }
  8298 + }
  8299 +
  8300 + _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
  8301 +
  8302 + _fnSaveState( settings );
  8303 + };
  8304 +
  8305 +
  8306 + _api_register( 'columns()', function ( selector, opts ) {
  8307 + // argument shifting
  8308 + if ( selector === undefined ) {
  8309 + selector = '';
  8310 + }
  8311 + else if ( $.isPlainObject( selector ) ) {
  8312 + opts = selector;
  8313 + selector = '';
  8314 + }
  8315 +
  8316 + opts = _selector_opts( opts );
  8317 +
  8318 + var inst = this.iterator( 'table', function ( settings ) {
  8319 + return __column_selector( settings, selector, opts );
  8320 + }, 1 );
  8321 +
  8322 + // Want argument shifting here and in _row_selector?
  8323 + inst.selector.cols = selector;
  8324 + inst.selector.opts = opts;
  8325 +
  8326 + return inst;
  8327 + } );
  8328 +
  8329 + _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
  8330 + return this.iterator( 'column', function ( settings, column ) {
  8331 + return settings.aoColumns[column].nTh;
  8332 + }, 1 );
  8333 + } );
  8334 +
  8335 + _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
  8336 + return this.iterator( 'column', function ( settings, column ) {
  8337 + return settings.aoColumns[column].nTf;
  8338 + }, 1 );
  8339 + } );
  8340 +
  8341 + _api_registerPlural( 'columns().data()', 'column().data()', function () {
  8342 + return this.iterator( 'column-rows', __columnData, 1 );
  8343 + } );
  8344 +
  8345 + _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
  8346 + return this.iterator( 'column', function ( settings, column ) {
  8347 + return settings.aoColumns[column].mData;
  8348 + }, 1 );
  8349 + } );
  8350 +
  8351 + _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
  8352 + return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
  8353 + return _pluck_order( settings.aoData, rows,
  8354 + type === 'search' ? '_aFilterData' : '_aSortData', column
  8355 + );
  8356 + }, 1 );
  8357 + } );
  8358 +
  8359 + _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
  8360 + return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
  8361 + return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
  8362 + }, 1 );
  8363 + } );
  8364 +
  8365 + _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
  8366 + return this.iterator( 'column', function ( settings, column ) {
  8367 + if ( vis === undefined ) {
  8368 + return settings.aoColumns[ column ].bVisible;
  8369 + } // else
  8370 + __setColumnVis( settings, column, vis, calc );
  8371 + } );
  8372 + } );
  8373 +
  8374 + _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
  8375 + return this.iterator( 'column', function ( settings, column ) {
  8376 + return type === 'visible' ?
  8377 + _fnColumnIndexToVisible( settings, column ) :
  8378 + column;
  8379 + }, 1 );
  8380 + } );
  8381 +
  8382 + _api_register( 'columns.adjust()', function () {
  8383 + return this.iterator( 'table', function ( settings ) {
  8384 + _fnAdjustColumnSizing( settings );
  8385 + }, 1 );
  8386 + } );
  8387 +
  8388 + _api_register( 'column.index()', function ( type, idx ) {
  8389 + if ( this.context.length !== 0 ) {
  8390 + var ctx = this.context[0];
  8391 +
  8392 + if ( type === 'fromVisible' || type === 'toData' ) {
  8393 + return _fnVisibleToColumnIndex( ctx, idx );
  8394 + }
  8395 + else if ( type === 'fromData' || type === 'toVisible' ) {
  8396 + return _fnColumnIndexToVisible( ctx, idx );
  8397 + }
  8398 + }
  8399 + } );
  8400 +
  8401 + _api_register( 'column()', function ( selector, opts ) {
  8402 + return _selector_first( this.columns( selector, opts ) );
  8403 + } );
  8404 +
  8405 +
  8406 +
  8407 +
  8408 + var __cell_selector = function ( settings, selector, opts )
  8409 + {
  8410 + var data = settings.aoData;
  8411 + var rows = _selector_row_indexes( settings, opts );
  8412 + var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
  8413 + var allCells = $( [].concat.apply([], cells) );
  8414 + var row;
  8415 + var columns = settings.aoColumns.length;
  8416 + var a, i, ien, j, o, host;
  8417 +
  8418 + var run = function ( s ) {
  8419 + var fnSelector = typeof s === 'function';
  8420 +
  8421 + if ( s === null || s === undefined || fnSelector ) {
  8422 + // All cells and function selectors
  8423 + a = [];
  8424 +
  8425 + for ( i=0, ien=rows.length ; i<ien ; i++ ) {
  8426 + row = rows[i];
  8427 +
  8428 + for ( j=0 ; j<columns ; j++ ) {
  8429 + o = {
  8430 + row: row,
  8431 + column: j
  8432 + };
  8433 +
  8434 + if ( fnSelector ) {
  8435 + // Selector - function
  8436 + host = settings.aoData[ row ];
  8437 +
  8438 + if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
  8439 + a.push( o );
  8440 + }
  8441 + }
  8442 + else {
  8443 + // Selector - all
  8444 + a.push( o );
  8445 + }
  8446 + }
  8447 + }
  8448 +
  8449 + return a;
  8450 + }
  8451 +
  8452 + // Selector - index
  8453 + if ( $.isPlainObject( s ) ) {
  8454 + return [s];
  8455 + }
  8456 +
  8457 + // Selector - jQuery filtered cells
  8458 + return allCells
  8459 + .filter( s )
  8460 + .map( function (i, el) {
  8461 + row = el.parentNode._DT_RowIndex;
  8462 +
  8463 + return {
  8464 + row: row,
  8465 + column: $.inArray( el, data[ row ].anCells )
  8466 + };
  8467 + } )
  8468 + .toArray();
  8469 + };
  8470 +
  8471 + return _selector_run( 'cell', selector, run, settings, opts );
  8472 + };
  8473 +
  8474 +
  8475 +
  8476 +
  8477 + _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
  8478 + // Argument shifting
  8479 + if ( $.isPlainObject( rowSelector ) ) {
  8480 + // Indexes
  8481 + if ( rowSelector.row === undefined ) {
  8482 + // Selector options in first parameter
  8483 + opts = rowSelector;
  8484 + rowSelector = null;
  8485 + }
  8486 + else {
  8487 + // Cell index objects in first parameter
  8488 + opts = columnSelector;
  8489 + columnSelector = null;
  8490 + }
  8491 + }
  8492 + if ( $.isPlainObject( columnSelector ) ) {
  8493 + opts = columnSelector;
  8494 + columnSelector = null;
  8495 + }
  8496 +
  8497 + // Cell selector
  8498 + if ( columnSelector === null || columnSelector === undefined ) {
  8499 + return this.iterator( 'table', function ( settings ) {
  8500 + return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
  8501 + } );
  8502 + }
  8503 +
  8504 + // Row + column selector
  8505 + var columns = this.columns( columnSelector, opts );
  8506 + var rows = this.rows( rowSelector, opts );
  8507 + var a, i, ien, j, jen;
  8508 +
  8509 + var cells = this.iterator( 'table', function ( settings, idx ) {
  8510 + a = [];
  8511 +
  8512 + for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
  8513 + for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
  8514 + a.push( {
  8515 + row: rows[idx][i],
  8516 + column: columns[idx][j]
  8517 + } );
  8518 + }
  8519 + }
  8520 +
  8521 + return a;
  8522 + }, 1 );
  8523 +
  8524 + $.extend( cells.selector, {
  8525 + cols: columnSelector,
  8526 + rows: rowSelector,
  8527 + opts: opts
  8528 + } );
  8529 +
  8530 + return cells;
  8531 + } );
  8532 +
  8533 +
  8534 + _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
  8535 + return this.iterator( 'cell', function ( settings, row, column ) {
  8536 + var cells = settings.aoData[ row ].anCells;
  8537 + return cells ?
  8538 + cells[ column ] :
  8539 + undefined;
  8540 + }, 1 );
  8541 + } );
  8542 +
  8543 +
  8544 + _api_register( 'cells().data()', function () {
  8545 + return this.iterator( 'cell', function ( settings, row, column ) {
  8546 + return _fnGetCellData( settings, row, column );
  8547 + }, 1 );
  8548 + } );
  8549 +
  8550 +
  8551 + _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
  8552 + type = type === 'search' ? '_aFilterData' : '_aSortData';
  8553 +
  8554 + return this.iterator( 'cell', function ( settings, row, column ) {
  8555 + return settings.aoData[ row ][ type ][ column ];
  8556 + }, 1 );
  8557 + } );
  8558 +
  8559 +
  8560 + _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
  8561 + return this.iterator( 'cell', function ( settings, row, column ) {
  8562 + return _fnGetCellData( settings, row, column, type );
  8563 + }, 1 );
  8564 + } );
  8565 +
  8566 +
  8567 + _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
  8568 + return this.iterator( 'cell', function ( settings, row, column ) {
  8569 + return {
  8570 + row: row,
  8571 + column: column,
  8572 + columnVisible: _fnColumnIndexToVisible( settings, column )
  8573 + };
  8574 + }, 1 );
  8575 + } );
  8576 +
  8577 +
  8578 + _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
  8579 + return this.iterator( 'cell', function ( settings, row, column ) {
  8580 + _fnInvalidate( settings, row, src, column );
  8581 + } );
  8582 + } );
  8583 +
  8584 +
  8585 +
  8586 + _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
  8587 + return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
  8588 + } );
  8589 +
  8590 +
  8591 + _api_register( 'cell().data()', function ( data ) {
  8592 + var ctx = this.context;
  8593 + var cell = this[0];
  8594 +
  8595 + if ( data === undefined ) {
  8596 + // Get
  8597 + return ctx.length && cell.length ?
  8598 + _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
  8599 + undefined;
  8600 + }
  8601 +
  8602 + // Set
  8603 + _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
  8604 + _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
  8605 +
  8606 + return this;
  8607 + } );
  8608 +
  8609 +
  8610 +
  8611 + /**
  8612 + * Get current ordering (sorting) that has been applied to the table.
  8613 + *
  8614 + * @returns {array} 2D array containing the sorting information for the first
  8615 + * table in the current context. Each element in the parent array represents
  8616 + * a column being sorted upon (i.e. multi-sorting with two columns would have
  8617 + * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
  8618 + * the column index that the sorting condition applies to, the second is the
  8619 + * direction of the sort (`desc` or `asc`) and, optionally, the third is the
  8620 + * index of the sorting order from the `column.sorting` initialisation array.
  8621 + *//**
  8622 + * Set the ordering for the table.
  8623 + *
  8624 + * @param {integer} order Column index to sort upon.
  8625 + * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
  8626 + * @returns {DataTables.Api} this
  8627 + *//**
  8628 + * Set the ordering for the table.
  8629 + *
  8630 + * @param {array} order 1D array of sorting information to be applied.
  8631 + * @param {array} [...] Optional additional sorting conditions
  8632 + * @returns {DataTables.Api} this
  8633 + *//**
  8634 + * Set the ordering for the table.
  8635 + *
  8636 + * @param {array} order 2D array of sorting information to be applied.
  8637 + * @returns {DataTables.Api} this
  8638 + */
  8639 + _api_register( 'order()', function ( order, dir ) {
  8640 + var ctx = this.context;
  8641 +
  8642 + if ( order === undefined ) {
  8643 + // get
  8644 + return ctx.length !== 0 ?
  8645 + ctx[0].aaSorting :
  8646 + undefined;
  8647 + }
  8648 +
  8649 + // set
  8650 + if ( typeof order === 'number' ) {
  8651 + // Simple column / direction passed in
  8652 + order = [ [ order, dir ] ];
  8653 + }
  8654 + else if ( ! $.isArray( order[0] ) ) {
  8655 + // Arguments passed in (list of 1D arrays)
  8656 + order = Array.prototype.slice.call( arguments );
  8657 + }
  8658 + // otherwise a 2D array was passed in
  8659 +
  8660 + return this.iterator( 'table', function ( settings ) {
  8661 + settings.aaSorting = order.slice();
  8662 + } );
  8663 + } );
  8664 +
  8665 +
  8666 + /**
  8667 + * Attach a sort listener to an element for a given column
  8668 + *
  8669 + * @param {node|jQuery|string} node Identifier for the element(s) to attach the
  8670 + * listener to. This can take the form of a single DOM node, a jQuery
  8671 + * collection of nodes or a jQuery selector which will identify the node(s).
  8672 + * @param {integer} column the column that a click on this node will sort on
  8673 + * @param {function} [callback] callback function when sort is run
  8674 + * @returns {DataTables.Api} this
  8675 + */
  8676 + _api_register( 'order.listener()', function ( node, column, callback ) {
  8677 + return this.iterator( 'table', function ( settings ) {
  8678 + _fnSortAttachListener( settings, node, column, callback );
  8679 + } );
  8680 + } );
  8681 +
  8682 +
  8683 + // Order by the selected column(s)
  8684 + _api_register( [
  8685 + 'columns().order()',
  8686 + 'column().order()'
  8687 + ], function ( dir ) {
  8688 + var that = this;
  8689 +
  8690 + return this.iterator( 'table', function ( settings, i ) {
  8691 + var sort = [];
  8692 +
  8693 + $.each( that[i], function (j, col) {
  8694 + sort.push( [ col, dir ] );
  8695 + } );
  8696 +
  8697 + settings.aaSorting = sort;
  8698 + } );
  8699 + } );
  8700 +
  8701 +
  8702 +
  8703 + _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
  8704 + var ctx = this.context;
  8705 +
  8706 + if ( input === undefined ) {
  8707 + // get
  8708 + return ctx.length !== 0 ?
  8709 + ctx[0].oPreviousSearch.sSearch :
  8710 + undefined;
  8711 + }
  8712 +
  8713 + // set
  8714 + return this.iterator( 'table', function ( settings ) {
  8715 + if ( ! settings.oFeatures.bFilter ) {
  8716 + return;
  8717 + }
  8718 +
  8719 + _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
  8720 + "sSearch": input+"",
  8721 + "bRegex": regex === null ? false : regex,
  8722 + "bSmart": smart === null ? true : smart,
  8723 + "bCaseInsensitive": caseInsen === null ? true : caseInsen
  8724 + } ), 1 );
  8725 + } );
  8726 + } );
  8727 +
  8728 +
  8729 + _api_registerPlural(
  8730 + 'columns().search()',
  8731 + 'column().search()',
  8732 + function ( input, regex, smart, caseInsen ) {
  8733 + return this.iterator( 'column', function ( settings, column ) {
  8734 + var preSearch = settings.aoPreSearchCols;
  8735 +
  8736 + if ( input === undefined ) {
  8737 + // get
  8738 + return preSearch[ column ].sSearch;
  8739 + }
  8740 +
  8741 + // set
  8742 + if ( ! settings.oFeatures.bFilter ) {
  8743 + return;
  8744 + }
  8745 +
  8746 + $.extend( preSearch[ column ], {
  8747 + "sSearch": input+"",
  8748 + "bRegex": regex === null ? false : regex,
  8749 + "bSmart": smart === null ? true : smart,
  8750 + "bCaseInsensitive": caseInsen === null ? true : caseInsen
  8751 + } );
  8752 +
  8753 + _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
  8754 + } );
  8755 + }
  8756 + );
  8757 +
  8758 + /*
  8759 + * State API methods
  8760 + */
  8761 +
  8762 + _api_register( 'state()', function () {
  8763 + return this.context.length ?
  8764 + this.context[0].oSavedState :
  8765 + null;
  8766 + } );
  8767 +
  8768 +
  8769 + _api_register( 'state.clear()', function () {
  8770 + return this.iterator( 'table', function ( settings ) {
  8771 + // Save an empty object
  8772 + settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
  8773 + } );
  8774 + } );
  8775 +
  8776 +
  8777 + _api_register( 'state.loaded()', function () {
  8778 + return this.context.length ?
  8779 + this.context[0].oLoadedState :
  8780 + null;
  8781 + } );
  8782 +
  8783 +
  8784 + _api_register( 'state.save()', function () {
  8785 + return this.iterator( 'table', function ( settings ) {
  8786 + _fnSaveState( settings );
  8787 + } );
  8788 + } );
  8789 +
  8790 +
  8791 +
  8792 + /**
  8793 + * Provide a common method for plug-ins to check the version of DataTables being
  8794 + * used, in order to ensure compatibility.
  8795 + *
  8796 + * @param {string} version Version string to check for, in the format "X.Y.Z".
  8797 + * Note that the formats "X" and "X.Y" are also acceptable.
  8798 + * @returns {boolean} true if this version of DataTables is greater or equal to
  8799 + * the required version, or false if this version of DataTales is not
  8800 + * suitable
  8801 + * @static
  8802 + * @dtopt API-Static
  8803 + *
  8804 + * @example
  8805 + * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
  8806 + */
  8807 + DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
  8808 + {
  8809 + var aThis = DataTable.version.split('.');
  8810 + var aThat = version.split('.');
  8811 + var iThis, iThat;
  8812 +
  8813 + for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
  8814 + iThis = parseInt( aThis[i], 10 ) || 0;
  8815 + iThat = parseInt( aThat[i], 10 ) || 0;
  8816 +
  8817 + // Parts are the same, keep comparing
  8818 + if (iThis === iThat) {
  8819 + continue;
  8820 + }
  8821 +
  8822 + // Parts are different, return immediately
  8823 + return iThis > iThat;
  8824 + }
  8825 +
  8826 + return true;
  8827 + };
  8828 +
  8829 +
  8830 + /**
  8831 + * Check if a `<table>` node is a DataTable table already or not.
  8832 + *
  8833 + * @param {node|jquery|string} table Table node, jQuery object or jQuery
  8834 + * selector for the table to test. Note that if more than more than one
  8835 + * table is passed on, only the first will be checked
  8836 + * @returns {boolean} true the table given is a DataTable, or false otherwise
  8837 + * @static
  8838 + * @dtopt API-Static
  8839 + *
  8840 + * @example
  8841 + * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
  8842 + * $('#example').dataTable();
  8843 + * }
  8844 + */
  8845 + DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
  8846 + {
  8847 + var t = $(table).get(0);
  8848 + var is = false;
  8849 +
  8850 + $.each( DataTable.settings, function (i, o) {
  8851 + var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
  8852 + var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
  8853 +
  8854 + if ( o.nTable === t || head === t || foot === t ) {
  8855 + is = true;
  8856 + }
  8857 + } );
  8858 +
  8859 + return is;
  8860 + };
  8861 +
  8862 +
  8863 + /**
  8864 + * Get all DataTable tables that have been initialised - optionally you can
  8865 + * select to get only currently visible tables.
  8866 + *
  8867 + * @param {boolean} [visible=false] Flag to indicate if you want all (default)
  8868 + * or visible tables only.
  8869 + * @returns {array} Array of `table` nodes (not DataTable instances) which are
  8870 + * DataTables
  8871 + * @static
  8872 + * @dtopt API-Static
  8873 + *
  8874 + * @example
  8875 + * $.each( $.fn.dataTable.tables(true), function () {
  8876 + * $(table).DataTable().columns.adjust();
  8877 + * } );
  8878 + */
  8879 + DataTable.tables = DataTable.fnTables = function ( visible )
  8880 + {
  8881 + return $.map( DataTable.settings, function (o) {
  8882 + if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
  8883 + return o.nTable;
  8884 + }
  8885 + } );
  8886 + };
  8887 +
  8888 +
  8889 + /**
  8890 + * DataTables utility methods
  8891 + *
  8892 + * This namespace provides helper methods that DataTables uses internally to
  8893 + * create a DataTable, but which are not exclusively used only for DataTables.
  8894 + * These methods can be used by extension authors to save the duplication of
  8895 + * code.
  8896 + *
  8897 + * @namespace
  8898 + */
  8899 + DataTable.util = {
  8900 + /**
  8901 + * Throttle the calls to a function. Arguments and context are maintained
  8902 + * for the throttled function.
  8903 + *
  8904 + * @param {function} fn Function to be called
  8905 + * @param {integer} freq Call frequency in mS
  8906 + * @return {function} Wrapped function
  8907 + */
  8908 + throttle: _fnThrottle,
  8909 +
  8910 +
  8911 + /**
  8912 + * Escape a string such that it can be used in a regular expression
  8913 + *
  8914 + * @param {string} sVal string to escape
  8915 + * @returns {string} escaped string
  8916 + */
  8917 + escapeRegex: _fnEscapeRegex
  8918 + };
  8919 +
  8920 +
  8921 + /**
  8922 + * Convert from camel case parameters to Hungarian notation. This is made public
  8923 + * for the extensions to provide the same ability as DataTables core to accept
  8924 + * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
  8925 + * parameters.
  8926 + *
  8927 + * @param {object} src The model object which holds all parameters that can be
  8928 + * mapped.
  8929 + * @param {object} user The object to convert from camel case to Hungarian.
  8930 + * @param {boolean} force When set to `true`, properties which already have a
  8931 + * Hungarian value in the `user` object will be overwritten. Otherwise they
  8932 + * won't be.
  8933 + */
  8934 + DataTable.camelToHungarian = _fnCamelToHungarian;
  8935 +
  8936 +
  8937 +
  8938 + /**
  8939 + *
  8940 + */
  8941 + _api_register( '$()', function ( selector, opts ) {
  8942 + var
  8943 + rows = this.rows( opts ).nodes(), // Get all rows
  8944 + jqRows = $(rows);
  8945 +
  8946 + return $( [].concat(
  8947 + jqRows.filter( selector ).toArray(),
  8948 + jqRows.find( selector ).toArray()
  8949 + ) );
  8950 + } );
  8951 +
  8952 +
  8953 + // jQuery functions to operate on the tables
  8954 + $.each( [ 'on', 'one', 'off' ], function (i, key) {
  8955 + _api_register( key+'()', function ( /* event, handler */ ) {
  8956 + var args = Array.prototype.slice.call(arguments);
  8957 +
  8958 + // Add the `dt` namespace automatically if it isn't already present
  8959 + if ( ! args[0].match(/\.dt\b/) ) {
  8960 + args[0] += '.dt';
  8961 + }
  8962 +
  8963 + var inst = $( this.tables().nodes() );
  8964 + inst[key].apply( inst, args );
  8965 + return this;
  8966 + } );
  8967 + } );
  8968 +
  8969 +
  8970 + _api_register( 'clear()', function () {
  8971 + return this.iterator( 'table', function ( settings ) {
  8972 + _fnClearTable( settings );
  8973 + } );
  8974 + } );
  8975 +
  8976 +
  8977 + _api_register( 'settings()', function () {
  8978 + return new _Api( this.context, this.context );
  8979 + } );
  8980 +
  8981 +
  8982 + _api_register( 'init()', function () {
  8983 + var ctx = this.context;
  8984 + return ctx.length ? ctx[0].oInit : null;
  8985 + } );
  8986 +
  8987 +
  8988 + _api_register( 'data()', function () {
  8989 + return this.iterator( 'table', function ( settings ) {
  8990 + return _pluck( settings.aoData, '_aData' );
  8991 + } ).flatten();
  8992 + } );
  8993 +
  8994 +
  8995 + _api_register( 'destroy()', function ( remove ) {
  8996 + remove = remove || false;
  8997 +
  8998 + return this.iterator( 'table', function ( settings ) {
  8999 + var orig = settings.nTableWrapper.parentNode;
  9000 + var classes = settings.oClasses;
  9001 + var table = settings.nTable;
  9002 + var tbody = settings.nTBody;
  9003 + var thead = settings.nTHead;
  9004 + var tfoot = settings.nTFoot;
  9005 + var jqTable = $(table);
  9006 + var jqTbody = $(tbody);
  9007 + var jqWrapper = $(settings.nTableWrapper);
  9008 + var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
  9009 + var i, ien;
  9010 +
  9011 + // Flag to note that the table is currently being destroyed - no action
  9012 + // should be taken
  9013 + settings.bDestroying = true;
  9014 +
  9015 + // Fire off the destroy callbacks for plug-ins etc
  9016 + _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
  9017 +
  9018 + // If not being removed from the document, make all columns visible
  9019 + if ( ! remove ) {
  9020 + new _Api( settings ).columns().visible( true );
  9021 + }
  9022 +
  9023 + // Blitz all `DT` namespaced events (these are internal events, the
  9024 + // lowercase, `dt` events are user subscribed and they are responsible
  9025 + // for removing them
  9026 + jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
  9027 + $(window).unbind('.DT-'+settings.sInstance);
  9028 +
  9029 + // When scrolling we had to break the table up - restore it
  9030 + if ( table != thead.parentNode ) {
  9031 + jqTable.children('thead').detach();
  9032 + jqTable.append( thead );
  9033 + }
  9034 +
  9035 + if ( tfoot && table != tfoot.parentNode ) {
  9036 + jqTable.children('tfoot').detach();
  9037 + jqTable.append( tfoot );
  9038 + }
  9039 +
  9040 + // Remove the DataTables generated nodes, events and classes
  9041 + jqTable.detach();
  9042 + jqWrapper.detach();
  9043 +
  9044 + settings.aaSorting = [];
  9045 + settings.aaSortingFixed = [];
  9046 + _fnSortingClasses( settings );
  9047 +
  9048 + $( rows ).removeClass( settings.asStripeClasses.join(' ') );
  9049 +
  9050 + $('th, td', thead).removeClass( classes.sSortable+' '+
  9051 + classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
  9052 + );
  9053 +
  9054 + if ( settings.bJUI ) {
  9055 + $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
  9056 + $('th, td', thead).each( function () {
  9057 + var wrapper = $('div.'+classes.sSortJUIWrapper, this);
  9058 + $(this).append( wrapper.contents() );
  9059 + wrapper.detach();
  9060 + } );
  9061 + }
  9062 +
  9063 + if ( ! remove && orig ) {
  9064 + // insertBefore acts like appendChild if !arg[1]
  9065 + orig.insertBefore( table, settings.nTableReinsertBefore );
  9066 + }
  9067 +
  9068 + // Add the TR elements back into the table in their original order
  9069 + jqTbody.children().detach();
  9070 + jqTbody.append( rows );
  9071 +
  9072 + // Restore the width of the original table - was read from the style property,
  9073 + // so we can restore directly to that
  9074 + jqTable
  9075 + .css( 'width', settings.sDestroyWidth )
  9076 + .removeClass( classes.sTable );
  9077 +
  9078 + // If the were originally stripe classes - then we add them back here.
  9079 + // Note this is not fool proof (for example if not all rows had stripe
  9080 + // classes - but it's a good effort without getting carried away
  9081 + ien = settings.asDestroyStripes.length;
  9082 +
  9083 + if ( ien ) {
  9084 + jqTbody.children().each( function (i) {
  9085 + $(this).addClass( settings.asDestroyStripes[i % ien] );
  9086 + } );
  9087 + }
  9088 +
  9089 + /* Remove the settings object from the settings array */
  9090 + var idx = $.inArray( settings, DataTable.settings );
  9091 + if ( idx !== -1 ) {
  9092 + DataTable.settings.splice( idx, 1 );
  9093 + }
  9094 + } );
  9095 + } );
  9096 +
  9097 +
  9098 + // Add the `every()` method for rows, columns and cells in a compact form
  9099 + $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
  9100 + _api_register( type+'s().every()', function ( fn ) {
  9101 + return this.iterator( type, function ( settings, idx, idx2 ) {
  9102 + // idx2 is undefined for rows and columns.
  9103 + fn.call( new _Api( settings )[ type ]( idx, idx2 ) );
  9104 + } );
  9105 + } );
  9106 + } );
  9107 +
  9108 +
  9109 + // i18n method for extensions to be able to use the language object from the
  9110 + // DataTable
  9111 + _api_register( 'i18n()', function ( token, def, plural ) {
  9112 + var ctx = this.context[0];
  9113 + var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
  9114 +
  9115 + if ( resolved === undefined ) {
  9116 + resolved = def;
  9117 + }
  9118 +
  9119 + if ( plural !== undefined && $.isPlainObject( resolved ) ) {
  9120 + resolved = resolved[ plural ] !== undefined ?
  9121 + resolved[ plural ] :
  9122 + resolved._;
  9123 + }
  9124 +
  9125 + return resolved.replace( '%d', plural ); // nb: plural might be undefined,
  9126 + } );
  9127 +
  9128 + /**
  9129 + * Version string for plug-ins to check compatibility. Allowed format is
  9130 + * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
  9131 + * only for non-release builds. See http://semver.org/ for more information.
  9132 + * @member
  9133 + * @type string
  9134 + * @default Version number
  9135 + */
  9136 + DataTable.version = "1.10.7";
  9137 +
  9138 + /**
  9139 + * Private data store, containing all of the settings objects that are
  9140 + * created for the tables on a given page.
  9141 + *
  9142 + * Note that the `DataTable.settings` object is aliased to
  9143 + * `jQuery.fn.dataTableExt` through which it may be accessed and
  9144 + * manipulated, or `jQuery.fn.dataTable.settings`.
  9145 + * @member
  9146 + * @type array
  9147 + * @default []
  9148 + * @private
  9149 + */
  9150 + DataTable.settings = [];
  9151 +
  9152 + /**
  9153 + * Object models container, for the various models that DataTables has
  9154 + * available to it. These models define the objects that are used to hold
  9155 + * the active state and configuration of the table.
  9156 + * @namespace
  9157 + */
  9158 + DataTable.models = {};
  9159 +
  9160 +
  9161 +
  9162 + /**
  9163 + * Template object for the way in which DataTables holds information about
  9164 + * search information for the global filter and individual column filters.
  9165 + * @namespace
  9166 + */
  9167 + DataTable.models.oSearch = {
  9168 + /**
  9169 + * Flag to indicate if the filtering should be case insensitive or not
  9170 + * @type boolean
  9171 + * @default true
  9172 + */
  9173 + "bCaseInsensitive": true,
  9174 +
  9175 + /**
  9176 + * Applied search term
  9177 + * @type string
  9178 + * @default <i>Empty string</i>
  9179 + */
  9180 + "sSearch": "",
  9181 +
  9182 + /**
  9183 + * Flag to indicate if the search term should be interpreted as a
  9184 + * regular expression (true) or not (false) and therefore and special
  9185 + * regex characters escaped.
  9186 + * @type boolean
  9187 + * @default false
  9188 + */
  9189 + "bRegex": false,
  9190 +
  9191 + /**
  9192 + * Flag to indicate if DataTables is to use its smart filtering or not.
  9193 + * @type boolean
  9194 + * @default true
  9195 + */
  9196 + "bSmart": true
  9197 + };
  9198 +
  9199 +
  9200 +
  9201 +
  9202 + /**
  9203 + * Template object for the way in which DataTables holds information about
  9204 + * each individual row. This is the object format used for the settings
  9205 + * aoData array.
  9206 + * @namespace
  9207 + */
  9208 + DataTable.models.oRow = {
  9209 + /**
  9210 + * TR element for the row
  9211 + * @type node
  9212 + * @default null
  9213 + */
  9214 + "nTr": null,
  9215 +
  9216 + /**
  9217 + * Array of TD elements for each row. This is null until the row has been
  9218 + * created.
  9219 + * @type array nodes
  9220 + * @default []
  9221 + */
  9222 + "anCells": null,
  9223 +
  9224 + /**
  9225 + * Data object from the original data source for the row. This is either
  9226 + * an array if using the traditional form of DataTables, or an object if
  9227 + * using mData options. The exact type will depend on the passed in
  9228 + * data from the data source, or will be an array if using DOM a data
  9229 + * source.
  9230 + * @type array|object
  9231 + * @default []
  9232 + */
  9233 + "_aData": [],
  9234 +
  9235 + /**
  9236 + * Sorting data cache - this array is ostensibly the same length as the
  9237 + * number of columns (although each index is generated only as it is
  9238 + * needed), and holds the data that is used for sorting each column in the
  9239 + * row. We do this cache generation at the start of the sort in order that
  9240 + * the formatting of the sort data need be done only once for each cell
  9241 + * per sort. This array should not be read from or written to by anything
  9242 + * other than the master sorting methods.
  9243 + * @type array
  9244 + * @default null
  9245 + * @private
  9246 + */
  9247 + "_aSortData": null,
  9248 +
  9249 + /**
  9250 + * Per cell filtering data cache. As per the sort data cache, used to
  9251 + * increase the performance of the filtering in DataTables
  9252 + * @type array
  9253 + * @default null
  9254 + * @private
  9255 + */
  9256 + "_aFilterData": null,
  9257 +
  9258 + /**
  9259 + * Filtering data cache. This is the same as the cell filtering cache, but
  9260 + * in this case a string rather than an array. This is easily computed with
  9261 + * a join on `_aFilterData`, but is provided as a cache so the join isn't
  9262 + * needed on every search (memory traded for performance)
  9263 + * @type array
  9264 + * @default null
  9265 + * @private
  9266 + */
  9267 + "_sFilterRow": null,
  9268 +
  9269 + /**
  9270 + * Cache of the class name that DataTables has applied to the row, so we
  9271 + * can quickly look at this variable rather than needing to do a DOM check
  9272 + * on className for the nTr property.
  9273 + * @type string
  9274 + * @default <i>Empty string</i>
  9275 + * @private
  9276 + */
  9277 + "_sRowStripe": "",
  9278 +
  9279 + /**
  9280 + * Denote if the original data source was from the DOM, or the data source
  9281 + * object. This is used for invalidating data, so DataTables can
  9282 + * automatically read data from the original source, unless uninstructed
  9283 + * otherwise.
  9284 + * @type string
  9285 + * @default null
  9286 + * @private
  9287 + */
  9288 + "src": null
  9289 + };
  9290 +
  9291 +
  9292 + /**
  9293 + * Template object for the column information object in DataTables. This object
  9294 + * is held in the settings aoColumns array and contains all the information that
  9295 + * DataTables needs about each individual column.
  9296 + *
  9297 + * Note that this object is related to {@link DataTable.defaults.column}
  9298 + * but this one is the internal data store for DataTables's cache of columns.
  9299 + * It should NOT be manipulated outside of DataTables. Any configuration should
  9300 + * be done through the initialisation options.
  9301 + * @namespace
  9302 + */
  9303 + DataTable.models.oColumn = {
  9304 + /**
  9305 + * Column index. This could be worked out on-the-fly with $.inArray, but it
  9306 + * is faster to just hold it as a variable
  9307 + * @type integer
  9308 + * @default null
  9309 + */
  9310 + "idx": null,
  9311 +
  9312 + /**
  9313 + * A list of the columns that sorting should occur on when this column
  9314 + * is sorted. That this property is an array allows multi-column sorting
  9315 + * to be defined for a column (for example first name / last name columns
  9316 + * would benefit from this). The values are integers pointing to the
  9317 + * columns to be sorted on (typically it will be a single integer pointing
  9318 + * at itself, but that doesn't need to be the case).
  9319 + * @type array
  9320 + */
  9321 + "aDataSort": null,
  9322 +
  9323 + /**
  9324 + * Define the sorting directions that are applied to the column, in sequence
  9325 + * as the column is repeatedly sorted upon - i.e. the first value is used
  9326 + * as the sorting direction when the column if first sorted (clicked on).
  9327 + * Sort it again (click again) and it will move on to the next index.
  9328 + * Repeat until loop.
  9329 + * @type array
  9330 + */
  9331 + "asSorting": null,
  9332 +
  9333 + /**
  9334 + * Flag to indicate if the column is searchable, and thus should be included
  9335 + * in the filtering or not.
  9336 + * @type boolean
  9337 + */
  9338 + "bSearchable": null,
  9339 +
  9340 + /**
  9341 + * Flag to indicate if the column is sortable or not.
  9342 + * @type boolean
  9343 + */
  9344 + "bSortable": null,
  9345 +
  9346 + /**
  9347 + * Flag to indicate if the column is currently visible in the table or not
  9348 + * @type boolean
  9349 + */
  9350 + "bVisible": null,
  9351 +
  9352 + /**
  9353 + * Store for manual type assignment using the `column.type` option. This
  9354 + * is held in store so we can manipulate the column's `sType` property.
  9355 + * @type string
  9356 + * @default null
  9357 + * @private
  9358 + */
  9359 + "_sManualType": null,
  9360 +
  9361 + /**
  9362 + * Flag to indicate if HTML5 data attributes should be used as the data
  9363 + * source for filtering or sorting. True is either are.
  9364 + * @type boolean
  9365 + * @default false
  9366 + * @private
  9367 + */
  9368 + "_bAttrSrc": false,
  9369 +
  9370 + /**
  9371 + * Developer definable function that is called whenever a cell is created (Ajax source,
  9372 + * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  9373 + * allowing you to modify the DOM element (add background colour for example) when the
  9374 + * element is available.
  9375 + * @type function
  9376 + * @param {element} nTd The TD node that has been created
  9377 + * @param {*} sData The Data for the cell
  9378 + * @param {array|object} oData The data for the whole row
  9379 + * @param {int} iRow The row index for the aoData data store
  9380 + * @default null
  9381 + */
  9382 + "fnCreatedCell": null,
  9383 +
  9384 + /**
  9385 + * Function to get data from a cell in a column. You should <b>never</b>
  9386 + * access data directly through _aData internally in DataTables - always use
  9387 + * the method attached to this property. It allows mData to function as
  9388 + * required. This function is automatically assigned by the column
  9389 + * initialisation method
  9390 + * @type function
  9391 + * @param {array|object} oData The data array/object for the array
  9392 + * (i.e. aoData[]._aData)
  9393 + * @param {string} sSpecific The specific data type you want to get -
  9394 + * 'display', 'type' 'filter' 'sort'
  9395 + * @returns {*} The data for the cell from the given row's data
  9396 + * @default null
  9397 + */
  9398 + "fnGetData": null,
  9399 +
  9400 + /**
  9401 + * Function to set data for a cell in the column. You should <b>never</b>
  9402 + * set the data directly to _aData internally in DataTables - always use
  9403 + * this method. It allows mData to function as required. This function
  9404 + * is automatically assigned by the column initialisation method
  9405 + * @type function
  9406 + * @param {array|object} oData The data array/object for the array
  9407 + * (i.e. aoData[]._aData)
  9408 + * @param {*} sValue Value to set
  9409 + * @default null
  9410 + */
  9411 + "fnSetData": null,
  9412 +
  9413 + /**
  9414 + * Property to read the value for the cells in the column from the data
  9415 + * source array / object. If null, then the default content is used, if a
  9416 + * function is given then the return from the function is used.
  9417 + * @type function|int|string|null
  9418 + * @default null
  9419 + */
  9420 + "mData": null,
  9421 +
  9422 + /**
  9423 + * Partner property to mData which is used (only when defined) to get
  9424 + * the data - i.e. it is basically the same as mData, but without the
  9425 + * 'set' option, and also the data fed to it is the result from mData.
  9426 + * This is the rendering method to match the data method of mData.
  9427 + * @type function|int|string|null
  9428 + * @default null
  9429 + */
  9430 + "mRender": null,
  9431 +
  9432 + /**
  9433 + * Unique header TH/TD element for this column - this is what the sorting
  9434 + * listener is attached to (if sorting is enabled.)
  9435 + * @type node
  9436 + * @default null
  9437 + */
  9438 + "nTh": null,
  9439 +
  9440 + /**
  9441 + * Unique footer TH/TD element for this column (if there is one). Not used
  9442 + * in DataTables as such, but can be used for plug-ins to reference the
  9443 + * footer for each column.
  9444 + * @type node
  9445 + * @default null
  9446 + */
  9447 + "nTf": null,
  9448 +
  9449 + /**
  9450 + * The class to apply to all TD elements in the table's TBODY for the column
  9451 + * @type string
  9452 + * @default null
  9453 + */
  9454 + "sClass": null,
  9455 +
  9456 + /**
  9457 + * When DataTables calculates the column widths to assign to each column,
  9458 + * it finds the longest string in each column and then constructs a
  9459 + * temporary table and reads the widths from that. The problem with this
  9460 + * is that "mmm" is much wider then "iiii", but the latter is a longer
  9461 + * string - thus the calculation can go wrong (doing it properly and putting
  9462 + * it into an DOM object and measuring that is horribly(!) slow). Thus as
  9463 + * a "work around" we provide this option. It will append its value to the
  9464 + * text that is found to be the longest string for the column - i.e. padding.
  9465 + * @type string
  9466 + */
  9467 + "sContentPadding": null,
  9468 +
  9469 + /**
  9470 + * Allows a default value to be given for a column's data, and will be used
  9471 + * whenever a null data source is encountered (this can be because mData
  9472 + * is set to null, or because the data source itself is null).
  9473 + * @type string
  9474 + * @default null
  9475 + */
  9476 + "sDefaultContent": null,
  9477 +
  9478 + /**
  9479 + * Name for the column, allowing reference to the column by name as well as
  9480 + * by index (needs a lookup to work by name).
  9481 + * @type string
  9482 + */
  9483 + "sName": null,
  9484 +
  9485 + /**
  9486 + * Custom sorting data type - defines which of the available plug-ins in
  9487 + * afnSortData the custom sorting will use - if any is defined.
  9488 + * @type string
  9489 + * @default std
  9490 + */
  9491 + "sSortDataType": 'std',
  9492 +
  9493 + /**
  9494 + * Class to be applied to the header element when sorting on this column
  9495 + * @type string
  9496 + * @default null
  9497 + */
  9498 + "sSortingClass": null,
  9499 +
  9500 + /**
  9501 + * Class to be applied to the header element when sorting on this column -
  9502 + * when jQuery UI theming is used.
  9503 + * @type string
  9504 + * @default null
  9505 + */
  9506 + "sSortingClassJUI": null,
  9507 +
  9508 + /**
  9509 + * Title of the column - what is seen in the TH element (nTh).
  9510 + * @type string
  9511 + */
  9512 + "sTitle": null,
  9513 +
  9514 + /**
  9515 + * Column sorting and filtering type
  9516 + * @type string
  9517 + * @default null
  9518 + */
  9519 + "sType": null,
  9520 +
  9521 + /**
  9522 + * Width of the column
  9523 + * @type string
  9524 + * @default null
  9525 + */
  9526 + "sWidth": null,
  9527 +
  9528 + /**
  9529 + * Width of the column when it was first "encountered"
  9530 + * @type string
  9531 + * @default null
  9532 + */
  9533 + "sWidthOrig": null
  9534 + };
  9535 +
  9536 +
  9537 + /*
  9538 + * Developer note: The properties of the object below are given in Hungarian
  9539 + * notation, that was used as the interface for DataTables prior to v1.10, however
  9540 + * from v1.10 onwards the primary interface is camel case. In order to avoid
  9541 + * breaking backwards compatibility utterly with this change, the Hungarian
  9542 + * version is still, internally the primary interface, but is is not documented
  9543 + * - hence the @name tags in each doc comment. This allows a Javascript function
  9544 + * to create a map from Hungarian notation to camel case (going the other direction
  9545 + * would require each property to be listed, which would at around 3K to the size
  9546 + * of DataTables, while this method is about a 0.5K hit.
  9547 + *
  9548 + * Ultimately this does pave the way for Hungarian notation to be dropped
  9549 + * completely, but that is a massive amount of work and will break current
  9550 + * installs (therefore is on-hold until v2).
  9551 + */
  9552 +
  9553 + /**
  9554 + * Initialisation options that can be given to DataTables at initialisation
  9555 + * time.
  9556 + * @namespace
  9557 + */
  9558 + DataTable.defaults = {
  9559 + /**
  9560 + * An array of data to use for the table, passed in at initialisation which
  9561 + * will be used in preference to any data which is already in the DOM. This is
  9562 + * particularly useful for constructing tables purely in Javascript, for
  9563 + * example with a custom Ajax call.
  9564 + * @type array
  9565 + * @default null
  9566 + *
  9567 + * @dtopt Option
  9568 + * @name DataTable.defaults.data
  9569 + *
  9570 + * @example
  9571 + * // Using a 2D array data source
  9572 + * $(document).ready( function () {
  9573 + * $('#example').dataTable( {
  9574 + * "data": [
  9575 + * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
  9576 + * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
  9577 + * ],
  9578 + * "columns": [
  9579 + * { "title": "Engine" },
  9580 + * { "title": "Browser" },
  9581 + * { "title": "Platform" },
  9582 + * { "title": "Version" },
  9583 + * { "title": "Grade" }
  9584 + * ]
  9585 + * } );
  9586 + * } );
  9587 + *
  9588 + * @example
  9589 + * // Using an array of objects as a data source (`data`)
  9590 + * $(document).ready( function () {
  9591 + * $('#example').dataTable( {
  9592 + * "data": [
  9593 + * {
  9594 + * "engine": "Trident",
  9595 + * "browser": "Internet Explorer 4.0",
  9596 + * "platform": "Win 95+",
  9597 + * "version": 4,
  9598 + * "grade": "X"
  9599 + * },
  9600 + * {
  9601 + * "engine": "Trident",
  9602 + * "browser": "Internet Explorer 5.0",
  9603 + * "platform": "Win 95+",
  9604 + * "version": 5,
  9605 + * "grade": "C"
  9606 + * }
  9607 + * ],
  9608 + * "columns": [
  9609 + * { "title": "Engine", "data": "engine" },
  9610 + * { "title": "Browser", "data": "browser" },
  9611 + * { "title": "Platform", "data": "platform" },
  9612 + * { "title": "Version", "data": "version" },
  9613 + * { "title": "Grade", "data": "grade" }
  9614 + * ]
  9615 + * } );
  9616 + * } );
  9617 + */
  9618 + "aaData": null,
  9619 +
  9620 +
  9621 + /**
  9622 + * If ordering is enabled, then DataTables will perform a first pass sort on
  9623 + * initialisation. You can define which column(s) the sort is performed
  9624 + * upon, and the sorting direction, with this variable. The `sorting` array
  9625 + * should contain an array for each column to be sorted initially containing
  9626 + * the column's index and a direction string ('asc' or 'desc').
  9627 + * @type array
  9628 + * @default [[0,'asc']]
  9629 + *
  9630 + * @dtopt Option
  9631 + * @name DataTable.defaults.order
  9632 + *
  9633 + * @example
  9634 + * // Sort by 3rd column first, and then 4th column
  9635 + * $(document).ready( function() {
  9636 + * $('#example').dataTable( {
  9637 + * "order": [[2,'asc'], [3,'desc']]
  9638 + * } );
  9639 + * } );
  9640 + *
  9641 + * // No initial sorting
  9642 + * $(document).ready( function() {
  9643 + * $('#example').dataTable( {
  9644 + * "order": []
  9645 + * } );
  9646 + * } );
  9647 + */
  9648 + "aaSorting": [[0,'asc']],
  9649 +
  9650 +
  9651 + /**
  9652 + * This parameter is basically identical to the `sorting` parameter, but
  9653 + * cannot be overridden by user interaction with the table. What this means
  9654 + * is that you could have a column (visible or hidden) which the sorting
  9655 + * will always be forced on first - any sorting after that (from the user)
  9656 + * will then be performed as required. This can be useful for grouping rows
  9657 + * together.
  9658 + * @type array
  9659 + * @default null
  9660 + *
  9661 + * @dtopt Option
  9662 + * @name DataTable.defaults.orderFixed
  9663 + *
  9664 + * @example
  9665 + * $(document).ready( function() {
  9666 + * $('#example').dataTable( {
  9667 + * "orderFixed": [[0,'asc']]
  9668 + * } );
  9669 + * } )
  9670 + */
  9671 + "aaSortingFixed": [],
  9672 +
  9673 +
  9674 + /**
  9675 + * DataTables can be instructed to load data to display in the table from a
  9676 + * Ajax source. This option defines how that Ajax call is made and where to.
  9677 + *
  9678 + * The `ajax` property has three different modes of operation, depending on
  9679 + * how it is defined. These are:
  9680 + *
  9681 + * * `string` - Set the URL from where the data should be loaded from.
  9682 + * * `object` - Define properties for `jQuery.ajax`.
  9683 + * * `function` - Custom data get function
  9684 + *
  9685 + * `string`
  9686 + * --------
  9687 + *
  9688 + * As a string, the `ajax` property simply defines the URL from which
  9689 + * DataTables will load data.
  9690 + *
  9691 + * `object`
  9692 + * --------
  9693 + *
  9694 + * As an object, the parameters in the object are passed to
  9695 + * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
  9696 + * of the Ajax request. DataTables has a number of default parameters which
  9697 + * you can override using this option. Please refer to the jQuery
  9698 + * documentation for a full description of the options available, although
  9699 + * the following parameters provide additional options in DataTables or
  9700 + * require special consideration:
  9701 + *
  9702 + * * `data` - As with jQuery, `data` can be provided as an object, but it
  9703 + * can also be used as a function to manipulate the data DataTables sends
  9704 + * to the server. The function takes a single parameter, an object of
  9705 + * parameters with the values that DataTables has readied for sending. An
  9706 + * object may be returned which will be merged into the DataTables
  9707 + * defaults, or you can add the items to the object that was passed in and
  9708 + * not return anything from the function. This supersedes `fnServerParams`
  9709 + * from DataTables 1.9-.
  9710 + *
  9711 + * * `dataSrc` - By default DataTables will look for the property `data` (or
  9712 + * `aaData` for compatibility with DataTables 1.9-) when obtaining data
  9713 + * from an Ajax source or for server-side processing - this parameter
  9714 + * allows that property to be changed. You can use Javascript dotted
  9715 + * object notation to get a data source for multiple levels of nesting, or
  9716 + * it my be used as a function. As a function it takes a single parameter,
  9717 + * the JSON returned from the server, which can be manipulated as
  9718 + * required, with the returned value being that used by DataTables as the
  9719 + * data source for the table. This supersedes `sAjaxDataProp` from
  9720 + * DataTables 1.9-.
  9721 + *
  9722 + * * `success` - Should not be overridden it is used internally in
  9723 + * DataTables. To manipulate / transform the data returned by the server
  9724 + * use `ajax.dataSrc`, or use `ajax` as a function (see below).
  9725 + *
  9726 + * `function`
  9727 + * ----------
  9728 + *
  9729 + * As a function, making the Ajax call is left up to yourself allowing
  9730 + * complete control of the Ajax request. Indeed, if desired, a method other
  9731 + * than Ajax could be used to obtain the required data, such as Web storage
  9732 + * or an AIR database.
  9733 + *
  9734 + * The function is given four parameters and no return is required. The
  9735 + * parameters are:
  9736 + *
  9737 + * 1. _object_ - Data to send to the server
  9738 + * 2. _function_ - Callback function that must be executed when the required
  9739 + * data has been obtained. That data should be passed into the callback
  9740 + * as the only parameter
  9741 + * 3. _object_ - DataTables settings object for the table
  9742 + *
  9743 + * Note that this supersedes `fnServerData` from DataTables 1.9-.
  9744 + *
  9745 + * @type string|object|function
  9746 + * @default null
  9747 + *
  9748 + * @dtopt Option
  9749 + * @name DataTable.defaults.ajax
  9750 + * @since 1.10.0
  9751 + *
  9752 + * @example
  9753 + * // Get JSON data from a file via Ajax.
  9754 + * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
  9755 + * $('#example').dataTable( {
  9756 + * "ajax": "data.json"
  9757 + * } );
  9758 + *
  9759 + * @example
  9760 + * // Get JSON data from a file via Ajax, using `dataSrc` to change
  9761 + * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
  9762 + * $('#example').dataTable( {
  9763 + * "ajax": {
  9764 + * "url": "data.json",
  9765 + * "dataSrc": "tableData"
  9766 + * }
  9767 + * } );
  9768 + *
  9769 + * @example
  9770 + * // Get JSON data from a file via Ajax, using `dataSrc` to read data
  9771 + * // from a plain array rather than an array in an object
  9772 + * $('#example').dataTable( {
  9773 + * "ajax": {
  9774 + * "url": "data.json",
  9775 + * "dataSrc": ""
  9776 + * }
  9777 + * } );
  9778 + *
  9779 + * @example
  9780 + * // Manipulate the data returned from the server - add a link to data
  9781 + * // (note this can, should, be done using `render` for the column - this
  9782 + * // is just a simple example of how the data can be manipulated).
  9783 + * $('#example').dataTable( {
  9784 + * "ajax": {
  9785 + * "url": "data.json",
  9786 + * "dataSrc": function ( json ) {
  9787 + * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
  9788 + * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
  9789 + * }
  9790 + * return json;
  9791 + * }
  9792 + * }
  9793 + * } );
  9794 + *
  9795 + * @example
  9796 + * // Add data to the request
  9797 + * $('#example').dataTable( {
  9798 + * "ajax": {
  9799 + * "url": "data.json",
  9800 + * "data": function ( d ) {
  9801 + * return {
  9802 + * "extra_search": $('#extra').val()
  9803 + * };
  9804 + * }
  9805 + * }
  9806 + * } );
  9807 + *
  9808 + * @example
  9809 + * // Send request as POST
  9810 + * $('#example').dataTable( {
  9811 + * "ajax": {
  9812 + * "url": "data.json",
  9813 + * "type": "POST"
  9814 + * }
  9815 + * } );
  9816 + *
  9817 + * @example
  9818 + * // Get the data from localStorage (could interface with a form for
  9819 + * // adding, editing and removing rows).
  9820 + * $('#example').dataTable( {
  9821 + * "ajax": function (data, callback, settings) {
  9822 + * callback(
  9823 + * JSON.parse( localStorage.getItem('dataTablesData') )
  9824 + * );
  9825 + * }
  9826 + * } );
  9827 + */
  9828 + "ajax": null,
  9829 +
  9830 +
  9831 + /**
  9832 + * This parameter allows you to readily specify the entries in the length drop
  9833 + * down menu that DataTables shows when pagination is enabled. It can be
  9834 + * either a 1D array of options which will be used for both the displayed
  9835 + * option and the value, or a 2D array which will use the array in the first
  9836 + * position as the value, and the array in the second position as the
  9837 + * displayed options (useful for language strings such as 'All').
  9838 + *
  9839 + * Note that the `pageLength` property will be automatically set to the
  9840 + * first value given in this array, unless `pageLength` is also provided.
  9841 + * @type array
  9842 + * @default [ 10, 25, 50, 100 ]
  9843 + *
  9844 + * @dtopt Option
  9845 + * @name DataTable.defaults.lengthMenu
  9846 + *
  9847 + * @example
  9848 + * $(document).ready( function() {
  9849 + * $('#example').dataTable( {
  9850 + * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
  9851 + * } );
  9852 + * } );
  9853 + */
  9854 + "aLengthMenu": [ 10, 25, 50, 100 ],
  9855 +
  9856 +
  9857 + /**
  9858 + * The `columns` option in the initialisation parameter allows you to define
  9859 + * details about the way individual columns behave. For a full list of
  9860 + * column options that can be set, please see
  9861 + * {@link DataTable.defaults.column}. Note that if you use `columns` to
  9862 + * define your columns, you must have an entry in the array for every single
  9863 + * column that you have in your table (these can be null if you don't which
  9864 + * to specify any options).
  9865 + * @member
  9866 + *
  9867 + * @name DataTable.defaults.column
  9868 + */
  9869 + "aoColumns": null,
  9870 +
  9871 + /**
  9872 + * Very similar to `columns`, `columnDefs` allows you to target a specific
  9873 + * column, multiple columns, or all columns, using the `targets` property of
  9874 + * each object in the array. This allows great flexibility when creating
  9875 + * tables, as the `columnDefs` arrays can be of any length, targeting the
  9876 + * columns you specifically want. `columnDefs` may use any of the column
  9877 + * options available: {@link DataTable.defaults.column}, but it _must_
  9878 + * have `targets` defined in each object in the array. Values in the `targets`
  9879 + * array may be:
  9880 + * <ul>
  9881 + * <li>a string - class name will be matched on the TH for the column</li>
  9882 + * <li>0 or a positive integer - column index counting from the left</li>
  9883 + * <li>a negative integer - column index counting from the right</li>
  9884 + * <li>the string "_all" - all columns (i.e. assign a default)</li>
  9885 + * </ul>
  9886 + * @member
  9887 + *
  9888 + * @name DataTable.defaults.columnDefs
  9889 + */
  9890 + "aoColumnDefs": null,
  9891 +
  9892 +
  9893 + /**
  9894 + * Basically the same as `search`, this parameter defines the individual column
  9895 + * filtering state at initialisation time. The array must be of the same size
  9896 + * as the number of columns, and each element be an object with the parameters
  9897 + * `search` and `escapeRegex` (the latter is optional). 'null' is also
  9898 + * accepted and the default will be used.
  9899 + * @type array
  9900 + * @default []
  9901 + *
  9902 + * @dtopt Option
  9903 + * @name DataTable.defaults.searchCols
  9904 + *
  9905 + * @example
  9906 + * $(document).ready( function() {
  9907 + * $('#example').dataTable( {
  9908 + * "searchCols": [
  9909 + * null,
  9910 + * { "search": "My filter" },
  9911 + * null,
  9912 + * { "search": "^[0-9]", "escapeRegex": false }
  9913 + * ]
  9914 + * } );
  9915 + * } )
  9916 + */
  9917 + "aoSearchCols": [],
  9918 +
  9919 +
  9920 + /**
  9921 + * An array of CSS classes that should be applied to displayed rows. This
  9922 + * array may be of any length, and DataTables will apply each class
  9923 + * sequentially, looping when required.
  9924 + * @type array
  9925 + * @default null <i>Will take the values determined by the `oClasses.stripe*`
  9926 + * options</i>
  9927 + *
  9928 + * @dtopt Option
  9929 + * @name DataTable.defaults.stripeClasses
  9930 + *
  9931 + * @example
  9932 + * $(document).ready( function() {
  9933 + * $('#example').dataTable( {
  9934 + * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
  9935 + * } );
  9936 + * } )
  9937 + */
  9938 + "asStripeClasses": null,
  9939 +
  9940 +
  9941 + /**
  9942 + * Enable or disable automatic column width calculation. This can be disabled
  9943 + * as an optimisation (it takes some time to calculate the widths) if the
  9944 + * tables widths are passed in using `columns`.
  9945 + * @type boolean
  9946 + * @default true
  9947 + *
  9948 + * @dtopt Features
  9949 + * @name DataTable.defaults.autoWidth
  9950 + *
  9951 + * @example
  9952 + * $(document).ready( function () {
  9953 + * $('#example').dataTable( {
  9954 + * "autoWidth": false
  9955 + * } );
  9956 + * } );
  9957 + */
  9958 + "bAutoWidth": true,
  9959 +
  9960 +
  9961 + /**
  9962 + * Deferred rendering can provide DataTables with a huge speed boost when you
  9963 + * are using an Ajax or JS data source for the table. This option, when set to
  9964 + * true, will cause DataTables to defer the creation of the table elements for
  9965 + * each row until they are needed for a draw - saving a significant amount of
  9966 + * time.
  9967 + * @type boolean
  9968 + * @default false
  9969 + *
  9970 + * @dtopt Features
  9971 + * @name DataTable.defaults.deferRender
  9972 + *
  9973 + * @example
  9974 + * $(document).ready( function() {
  9975 + * $('#example').dataTable( {
  9976 + * "ajax": "sources/arrays.txt",
  9977 + * "deferRender": true
  9978 + * } );
  9979 + * } );
  9980 + */
  9981 + "bDeferRender": false,
  9982 +
  9983 +
  9984 + /**
  9985 + * Replace a DataTable which matches the given selector and replace it with
  9986 + * one which has the properties of the new initialisation object passed. If no
  9987 + * table matches the selector, then the new DataTable will be constructed as
  9988 + * per normal.
  9989 + * @type boolean
  9990 + * @default false
  9991 + *
  9992 + * @dtopt Options
  9993 + * @name DataTable.defaults.destroy
  9994 + *
  9995 + * @example
  9996 + * $(document).ready( function() {
  9997 + * $('#example').dataTable( {
  9998 + * "srollY": "200px",
  9999 + * "paginate": false
  10000 + * } );
  10001 + *
  10002 + * // Some time later....
  10003 + * $('#example').dataTable( {
  10004 + * "filter": false,
  10005 + * "destroy": true
  10006 + * } );
  10007 + * } );
  10008 + */
  10009 + "bDestroy": false,
  10010 +
  10011 +
  10012 + /**
  10013 + * Enable or disable filtering of data. Filtering in DataTables is "smart" in
  10014 + * that it allows the end user to input multiple words (space separated) and
  10015 + * will match a row containing those words, even if not in the order that was
  10016 + * specified (this allow matching across multiple columns). Note that if you
  10017 + * wish to use filtering in DataTables this must remain 'true' - to remove the
  10018 + * default filtering input box and retain filtering abilities, please use
  10019 + * {@link DataTable.defaults.dom}.
  10020 + * @type boolean
  10021 + * @default true
  10022 + *
  10023 + * @dtopt Features
  10024 + * @name DataTable.defaults.searching
  10025 + *
  10026 + * @example
  10027 + * $(document).ready( function () {
  10028 + * $('#example').dataTable( {
  10029 + * "searching": false
  10030 + * } );
  10031 + * } );
  10032 + */
  10033 + "bFilter": true,
  10034 +
  10035 +
  10036 + /**
  10037 + * Enable or disable the table information display. This shows information
  10038 + * about the data that is currently visible on the page, including information
  10039 + * about filtered data if that action is being performed.
  10040 + * @type boolean
  10041 + * @default true
  10042 + *
  10043 + * @dtopt Features
  10044 + * @name DataTable.defaults.info
  10045 + *
  10046 + * @example
  10047 + * $(document).ready( function () {
  10048 + * $('#example').dataTable( {
  10049 + * "info": false
  10050 + * } );
  10051 + * } );
  10052 + */
  10053 + "bInfo": true,
  10054 +
  10055 +
  10056 + /**
  10057 + * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
  10058 + * slightly different and additional mark-up from what DataTables has
  10059 + * traditionally used).
  10060 + * @type boolean
  10061 + * @default false
  10062 + *
  10063 + * @dtopt Features
  10064 + * @name DataTable.defaults.jQueryUI
  10065 + *
  10066 + * @example
  10067 + * $(document).ready( function() {
  10068 + * $('#example').dataTable( {
  10069 + * "jQueryUI": true
  10070 + * } );
  10071 + * } );
  10072 + */
  10073 + "bJQueryUI": false,
  10074 +
  10075 +
  10076 + /**
  10077 + * Allows the end user to select the size of a formatted page from a select
  10078 + * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
  10079 + * @type boolean
  10080 + * @default true
  10081 + *
  10082 + * @dtopt Features
  10083 + * @name DataTable.defaults.lengthChange
  10084 + *
  10085 + * @example
  10086 + * $(document).ready( function () {
  10087 + * $('#example').dataTable( {
  10088 + * "lengthChange": false
  10089 + * } );
  10090 + * } );
  10091 + */
  10092 + "bLengthChange": true,
  10093 +
  10094 +
  10095 + /**
  10096 + * Enable or disable pagination.
  10097 + * @type boolean
  10098 + * @default true
  10099 + *
  10100 + * @dtopt Features
  10101 + * @name DataTable.defaults.paging
  10102 + *
  10103 + * @example
  10104 + * $(document).ready( function () {
  10105 + * $('#example').dataTable( {
  10106 + * "paging": false
  10107 + * } );
  10108 + * } );
  10109 + */
  10110 + "bPaginate": true,
  10111 +
  10112 +
  10113 + /**
  10114 + * Enable or disable the display of a 'processing' indicator when the table is
  10115 + * being processed (e.g. a sort). This is particularly useful for tables with
  10116 + * large amounts of data where it can take a noticeable amount of time to sort
  10117 + * the entries.
  10118 + * @type boolean
  10119 + * @default false
  10120 + *
  10121 + * @dtopt Features
  10122 + * @name DataTable.defaults.processing
  10123 + *
  10124 + * @example
  10125 + * $(document).ready( function () {
  10126 + * $('#example').dataTable( {
  10127 + * "processing": true
  10128 + * } );
  10129 + * } );
  10130 + */
  10131 + "bProcessing": false,
  10132 +
  10133 +
  10134 + /**
  10135 + * Retrieve the DataTables object for the given selector. Note that if the
  10136 + * table has already been initialised, this parameter will cause DataTables
  10137 + * to simply return the object that has already been set up - it will not take
  10138 + * account of any changes you might have made to the initialisation object
  10139 + * passed to DataTables (setting this parameter to true is an acknowledgement
  10140 + * that you understand this). `destroy` can be used to reinitialise a table if
  10141 + * you need.
  10142 + * @type boolean
  10143 + * @default false
  10144 + *
  10145 + * @dtopt Options
  10146 + * @name DataTable.defaults.retrieve
  10147 + *
  10148 + * @example
  10149 + * $(document).ready( function() {
  10150 + * initTable();
  10151 + * tableActions();
  10152 + * } );
  10153 + *
  10154 + * function initTable ()
  10155 + * {
  10156 + * return $('#example').dataTable( {
  10157 + * "scrollY": "200px",
  10158 + * "paginate": false,
  10159 + * "retrieve": true
  10160 + * } );
  10161 + * }
  10162 + *
  10163 + * function tableActions ()
  10164 + * {
  10165 + * var table = initTable();
  10166 + * // perform API operations with oTable
  10167 + * }
  10168 + */
  10169 + "bRetrieve": false,
  10170 +
  10171 +
  10172 + /**
  10173 + * When vertical (y) scrolling is enabled, DataTables will force the height of
  10174 + * the table's viewport to the given height at all times (useful for layout).
  10175 + * However, this can look odd when filtering data down to a small data set,
  10176 + * and the footer is left "floating" further down. This parameter (when
  10177 + * enabled) will cause DataTables to collapse the table's viewport down when
  10178 + * the result set will fit within the given Y height.
  10179 + * @type boolean
  10180 + * @default false
  10181 + *
  10182 + * @dtopt Options
  10183 + * @name DataTable.defaults.scrollCollapse
  10184 + *
  10185 + * @example
  10186 + * $(document).ready( function() {
  10187 + * $('#example').dataTable( {
  10188 + * "scrollY": "200",
  10189 + * "scrollCollapse": true
  10190 + * } );
  10191 + * } );
  10192 + */
  10193 + "bScrollCollapse": false,
  10194 +
  10195 +
  10196 + /**
  10197 + * Configure DataTables to use server-side processing. Note that the
  10198 + * `ajax` parameter must also be given in order to give DataTables a
  10199 + * source to obtain the required data for each draw.
  10200 + * @type boolean
  10201 + * @default false
  10202 + *
  10203 + * @dtopt Features
  10204 + * @dtopt Server-side
  10205 + * @name DataTable.defaults.serverSide
  10206 + *
  10207 + * @example
  10208 + * $(document).ready( function () {
  10209 + * $('#example').dataTable( {
  10210 + * "serverSide": true,
  10211 + * "ajax": "xhr.php"
  10212 + * } );
  10213 + * } );
  10214 + */
  10215 + "bServerSide": false,
  10216 +
  10217 +
  10218 + /**
  10219 + * Enable or disable sorting of columns. Sorting of individual columns can be
  10220 + * disabled by the `sortable` option for each column.
  10221 + * @type boolean
  10222 + * @default true
  10223 + *
  10224 + * @dtopt Features
  10225 + * @name DataTable.defaults.ordering
  10226 + *
  10227 + * @example
  10228 + * $(document).ready( function () {
  10229 + * $('#example').dataTable( {
  10230 + * "ordering": false
  10231 + * } );
  10232 + * } );
  10233 + */
  10234 + "bSort": true,
  10235 +
  10236 +
  10237 + /**
  10238 + * Enable or display DataTables' ability to sort multiple columns at the
  10239 + * same time (activated by shift-click by the user).
  10240 + * @type boolean
  10241 + * @default true
  10242 + *
  10243 + * @dtopt Options
  10244 + * @name DataTable.defaults.orderMulti
  10245 + *
  10246 + * @example
  10247 + * // Disable multiple column sorting ability
  10248 + * $(document).ready( function () {
  10249 + * $('#example').dataTable( {
  10250 + * "orderMulti": false
  10251 + * } );
  10252 + * } );
  10253 + */
  10254 + "bSortMulti": true,
  10255 +
  10256 +
  10257 + /**
  10258 + * Allows control over whether DataTables should use the top (true) unique
  10259 + * cell that is found for a single column, or the bottom (false - default).
  10260 + * This is useful when using complex headers.
  10261 + * @type boolean
  10262 + * @default false
  10263 + *
  10264 + * @dtopt Options
  10265 + * @name DataTable.defaults.orderCellsTop
  10266 + *
  10267 + * @example
  10268 + * $(document).ready( function() {
  10269 + * $('#example').dataTable( {
  10270 + * "orderCellsTop": true
  10271 + * } );
  10272 + * } );
  10273 + */
  10274 + "bSortCellsTop": false,
  10275 +
  10276 +
  10277 + /**
  10278 + * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
  10279 + * `sorting\_3` to the columns which are currently being sorted on. This is
  10280 + * presented as a feature switch as it can increase processing time (while
  10281 + * classes are removed and added) so for large data sets you might want to
  10282 + * turn this off.
  10283 + * @type boolean
  10284 + * @default true
  10285 + *
  10286 + * @dtopt Features
  10287 + * @name DataTable.defaults.orderClasses
  10288 + *
  10289 + * @example
  10290 + * $(document).ready( function () {
  10291 + * $('#example').dataTable( {
  10292 + * "orderClasses": false
  10293 + * } );
  10294 + * } );
  10295 + */
  10296 + "bSortClasses": true,
  10297 +
  10298 +
  10299 + /**
  10300 + * Enable or disable state saving. When enabled HTML5 `localStorage` will be
  10301 + * used to save table display information such as pagination information,
  10302 + * display length, filtering and sorting. As such when the end user reloads
  10303 + * the page the display display will match what thy had previously set up.
  10304 + *
  10305 + * Due to the use of `localStorage` the default state saving is not supported
  10306 + * in IE6 or 7. If state saving is required in those browsers, use
  10307 + * `stateSaveCallback` to provide a storage solution such as cookies.
  10308 + * @type boolean
  10309 + * @default false
  10310 + *
  10311 + * @dtopt Features
  10312 + * @name DataTable.defaults.stateSave
  10313 + *
  10314 + * @example
  10315 + * $(document).ready( function () {
  10316 + * $('#example').dataTable( {
  10317 + * "stateSave": true
  10318 + * } );
  10319 + * } );
  10320 + */
  10321 + "bStateSave": false,
  10322 +
  10323 +
  10324 + /**
  10325 + * This function is called when a TR element is created (and all TD child
  10326 + * elements have been inserted), or registered if using a DOM source, allowing
  10327 + * manipulation of the TR element (adding classes etc).
  10328 + * @type function
  10329 + * @param {node} row "TR" element for the current row
  10330 + * @param {array} data Raw data array for this row
  10331 + * @param {int} dataIndex The index of this row in the internal aoData array
  10332 + *
  10333 + * @dtopt Callbacks
  10334 + * @name DataTable.defaults.createdRow
  10335 + *
  10336 + * @example
  10337 + * $(document).ready( function() {
  10338 + * $('#example').dataTable( {
  10339 + * "createdRow": function( row, data, dataIndex ) {
  10340 + * // Bold the grade for all 'A' grade browsers
  10341 + * if ( data[4] == "A" )
  10342 + * {
  10343 + * $('td:eq(4)', row).html( '<b>A</b>' );
  10344 + * }
  10345 + * }
  10346 + * } );
  10347 + * } );
  10348 + */
  10349 + "fnCreatedRow": null,
  10350 +
  10351 +
  10352 + /**
  10353 + * This function is called on every 'draw' event, and allows you to
  10354 + * dynamically modify any aspect you want about the created DOM.
  10355 + * @type function
  10356 + * @param {object} settings DataTables settings object
  10357 + *
  10358 + * @dtopt Callbacks
  10359 + * @name DataTable.defaults.drawCallback
  10360 + *
  10361 + * @example
  10362 + * $(document).ready( function() {
  10363 + * $('#example').dataTable( {
  10364 + * "drawCallback": function( settings ) {
  10365 + * alert( 'DataTables has redrawn the table' );
  10366 + * }
  10367 + * } );
  10368 + * } );
  10369 + */
  10370 + "fnDrawCallback": null,
  10371 +
  10372 +
  10373 + /**
  10374 + * Identical to fnHeaderCallback() but for the table footer this function
  10375 + * allows you to modify the table footer on every 'draw' event.
  10376 + * @type function
  10377 + * @param {node} foot "TR" element for the footer
  10378 + * @param {array} data Full table data (as derived from the original HTML)
  10379 + * @param {int} start Index for the current display starting point in the
  10380 + * display array
  10381 + * @param {int} end Index for the current display ending point in the
  10382 + * display array
  10383 + * @param {array int} display Index array to translate the visual position
  10384 + * to the full data array
  10385 + *
  10386 + * @dtopt Callbacks
  10387 + * @name DataTable.defaults.footerCallback
  10388 + *
  10389 + * @example
  10390 + * $(document).ready( function() {
  10391 + * $('#example').dataTable( {
  10392 + * "footerCallback": function( tfoot, data, start, end, display ) {
  10393 + * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
  10394 + * }
  10395 + * } );
  10396 + * } )
  10397 + */
  10398 + "fnFooterCallback": null,
  10399 +
  10400 +
  10401 + /**
  10402 + * When rendering large numbers in the information element for the table
  10403 + * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
  10404 + * to have a comma separator for the 'thousands' units (e.g. 1 million is
  10405 + * rendered as "1,000,000") to help readability for the end user. This
  10406 + * function will override the default method DataTables uses.
  10407 + * @type function
  10408 + * @member
  10409 + * @param {int} toFormat number to be formatted
  10410 + * @returns {string} formatted string for DataTables to show the number
  10411 + *
  10412 + * @dtopt Callbacks
  10413 + * @name DataTable.defaults.formatNumber
  10414 + *
  10415 + * @example
  10416 + * // Format a number using a single quote for the separator (note that
  10417 + * // this can also be done with the language.thousands option)
  10418 + * $(document).ready( function() {
  10419 + * $('#example').dataTable( {
  10420 + * "formatNumber": function ( toFormat ) {
  10421 + * return toFormat.toString().replace(
  10422 + * /\B(?=(\d{3})+(?!\d))/g, "'"
  10423 + * );
  10424 + * };
  10425 + * } );
  10426 + * } );
  10427 + */
  10428 + "fnFormatNumber": function ( toFormat ) {
  10429 + return toFormat.toString().replace(
  10430 + /\B(?=(\d{3})+(?!\d))/g,
  10431 + this.oLanguage.sThousands
  10432 + );
  10433 + },
  10434 +
  10435 +
  10436 + /**
  10437 + * This function is called on every 'draw' event, and allows you to
  10438 + * dynamically modify the header row. This can be used to calculate and
  10439 + * display useful information about the table.
  10440 + * @type function
  10441 + * @param {node} head "TR" element for the header
  10442 + * @param {array} data Full table data (as derived from the original HTML)
  10443 + * @param {int} start Index for the current display starting point in the
  10444 + * display array
  10445 + * @param {int} end Index for the current display ending point in the
  10446 + * display array
  10447 + * @param {array int} display Index array to translate the visual position
  10448 + * to the full data array
  10449 + *
  10450 + * @dtopt Callbacks
  10451 + * @name DataTable.defaults.headerCallback
  10452 + *
  10453 + * @example
  10454 + * $(document).ready( function() {
  10455 + * $('#example').dataTable( {
  10456 + * "fheaderCallback": function( head, data, start, end, display ) {
  10457 + * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
  10458 + * }
  10459 + * } );
  10460 + * } )
  10461 + */
  10462 + "fnHeaderCallback": null,
  10463 +
  10464 +
  10465 + /**
  10466 + * The information element can be used to convey information about the current
  10467 + * state of the table. Although the internationalisation options presented by
  10468 + * DataTables are quite capable of dealing with most customisations, there may
  10469 + * be times where you wish to customise the string further. This callback
  10470 + * allows you to do exactly that.
  10471 + * @type function
  10472 + * @param {object} oSettings DataTables settings object
  10473 + * @param {int} start Starting position in data for the draw
  10474 + * @param {int} end End position in data for the draw
  10475 + * @param {int} max Total number of rows in the table (regardless of
  10476 + * filtering)
  10477 + * @param {int} total Total number of rows in the data set, after filtering
  10478 + * @param {string} pre The string that DataTables has formatted using it's
  10479 + * own rules
  10480 + * @returns {string} The string to be displayed in the information element.
  10481 + *
  10482 + * @dtopt Callbacks
  10483 + * @name DataTable.defaults.infoCallback
  10484 + *
  10485 + * @example
  10486 + * $('#example').dataTable( {
  10487 + * "infoCallback": function( settings, start, end, max, total, pre ) {
  10488 + * return start +" to "+ end;
  10489 + * }
  10490 + * } );
  10491 + */
  10492 + "fnInfoCallback": null,
  10493 +
  10494 +
  10495 + /**
  10496 + * Called when the table has been initialised. Normally DataTables will
  10497 + * initialise sequentially and there will be no need for this function,
  10498 + * however, this does not hold true when using external language information
  10499 + * since that is obtained using an async XHR call.
  10500 + * @type function
  10501 + * @param {object} settings DataTables settings object
  10502 + * @param {object} json The JSON object request from the server - only
  10503 + * present if client-side Ajax sourced data is used
  10504 + *
  10505 + * @dtopt Callbacks
  10506 + * @name DataTable.defaults.initComplete
  10507 + *
  10508 + * @example
  10509 + * $(document).ready( function() {
  10510 + * $('#example').dataTable( {
  10511 + * "initComplete": function(settings, json) {
  10512 + * alert( 'DataTables has finished its initialisation.' );
  10513 + * }
  10514 + * } );
  10515 + * } )
  10516 + */
  10517 + "fnInitComplete": null,
  10518 +
  10519 +
  10520 + /**
  10521 + * Called at the very start of each table draw and can be used to cancel the
  10522 + * draw by returning false, any other return (including undefined) results in
  10523 + * the full draw occurring).
  10524 + * @type function
  10525 + * @param {object} settings DataTables settings object
  10526 + * @returns {boolean} False will cancel the draw, anything else (including no
  10527 + * return) will allow it to complete.
  10528 + *
  10529 + * @dtopt Callbacks
  10530 + * @name DataTable.defaults.preDrawCallback
  10531 + *
  10532 + * @example
  10533 + * $(document).ready( function() {
  10534 + * $('#example').dataTable( {
  10535 + * "preDrawCallback": function( settings ) {
  10536 + * if ( $('#test').val() == 1 ) {
  10537 + * return false;
  10538 + * }
  10539 + * }
  10540 + * } );
  10541 + * } );
  10542 + */
  10543 + "fnPreDrawCallback": null,
  10544 +
  10545 +
  10546 + /**
  10547 + * This function allows you to 'post process' each row after it have been
  10548 + * generated for each table draw, but before it is rendered on screen. This
  10549 + * function might be used for setting the row class name etc.
  10550 + * @type function
  10551 + * @param {node} row "TR" element for the current row
  10552 + * @param {array} data Raw data array for this row
  10553 + * @param {int} displayIndex The display index for the current table draw
  10554 + * @param {int} displayIndexFull The index of the data in the full list of
  10555 + * rows (after filtering)
  10556 + *
  10557 + * @dtopt Callbacks
  10558 + * @name DataTable.defaults.rowCallback
  10559 + *
  10560 + * @example
  10561 + * $(document).ready( function() {
  10562 + * $('#example').dataTable( {
  10563 + * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
  10564 + * // Bold the grade for all 'A' grade browsers
  10565 + * if ( data[4] == "A" ) {
  10566 + * $('td:eq(4)', row).html( '<b>A</b>' );
  10567 + * }
  10568 + * }
  10569 + * } );
  10570 + * } );
  10571 + */
  10572 + "fnRowCallback": null,
  10573 +
  10574 +
  10575 + /**
  10576 + * __Deprecated__ The functionality provided by this parameter has now been
  10577 + * superseded by that provided through `ajax`, which should be used instead.
  10578 + *
  10579 + * This parameter allows you to override the default function which obtains
  10580 + * the data from the server so something more suitable for your application.
  10581 + * For example you could use POST data, or pull information from a Gears or
  10582 + * AIR database.
  10583 + * @type function
  10584 + * @member
  10585 + * @param {string} source HTTP source to obtain the data from (`ajax`)
  10586 + * @param {array} data A key/value pair object containing the data to send
  10587 + * to the server
  10588 + * @param {function} callback to be called on completion of the data get
  10589 + * process that will draw the data on the page.
  10590 + * @param {object} settings DataTables settings object
  10591 + *
  10592 + * @dtopt Callbacks
  10593 + * @dtopt Server-side
  10594 + * @name DataTable.defaults.serverData
  10595 + *
  10596 + * @deprecated 1.10. Please use `ajax` for this functionality now.
  10597 + */
  10598 + "fnServerData": null,
  10599 +
  10600 +
  10601 + /**
  10602 + * __Deprecated__ The functionality provided by this parameter has now been
  10603 + * superseded by that provided through `ajax`, which should be used instead.
  10604 + *
  10605 + * It is often useful to send extra data to the server when making an Ajax
  10606 + * request - for example custom filtering information, and this callback
  10607 + * function makes it trivial to send extra information to the server. The
  10608 + * passed in parameter is the data set that has been constructed by
  10609 + * DataTables, and you can add to this or modify it as you require.
  10610 + * @type function
  10611 + * @param {array} data Data array (array of objects which are name/value
  10612 + * pairs) that has been constructed by DataTables and will be sent to the
  10613 + * server. In the case of Ajax sourced data with server-side processing
  10614 + * this will be an empty array, for server-side processing there will be a
  10615 + * significant number of parameters!
  10616 + * @returns {undefined} Ensure that you modify the data array passed in,
  10617 + * as this is passed by reference.
  10618 + *
  10619 + * @dtopt Callbacks
  10620 + * @dtopt Server-side
  10621 + * @name DataTable.defaults.serverParams
  10622 + *
  10623 + * @deprecated 1.10. Please use `ajax` for this functionality now.
  10624 + */
  10625 + "fnServerParams": null,
  10626 +
  10627 +
  10628 + /**
  10629 + * Load the table state. With this function you can define from where, and how, the
  10630 + * state of a table is loaded. By default DataTables will load from `localStorage`
  10631 + * but you might wish to use a server-side database or cookies.
  10632 + * @type function
  10633 + * @member
  10634 + * @param {object} settings DataTables settings object
  10635 + * @return {object} The DataTables state object to be loaded
  10636 + *
  10637 + * @dtopt Callbacks
  10638 + * @name DataTable.defaults.stateLoadCallback
  10639 + *
  10640 + * @example
  10641 + * $(document).ready( function() {
  10642 + * $('#example').dataTable( {
  10643 + * "stateSave": true,
  10644 + * "stateLoadCallback": function (settings) {
  10645 + * var o;
  10646 + *
  10647 + * // Send an Ajax request to the server to get the data. Note that
  10648 + * // this is a synchronous request.
  10649 + * $.ajax( {
  10650 + * "url": "/state_load",
  10651 + * "async": false,
  10652 + * "dataType": "json",
  10653 + * "success": function (json) {
  10654 + * o = json;
  10655 + * }
  10656 + * } );
  10657 + *
  10658 + * return o;
  10659 + * }
  10660 + * } );
  10661 + * } );
  10662 + */
  10663 + "fnStateLoadCallback": function ( settings ) {
  10664 + try {
  10665 + return JSON.parse(
  10666 + (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
  10667 + 'DataTables_'+settings.sInstance+'_'+location.pathname
  10668 + )
  10669 + );
  10670 + } catch (e) {}
  10671 + },
  10672 +
  10673 +
  10674 + /**
  10675 + * Callback which allows modification of the saved state prior to loading that state.
  10676 + * This callback is called when the table is loading state from the stored data, but
  10677 + * prior to the settings object being modified by the saved state. Note that for
  10678 + * plug-in authors, you should use the `stateLoadParams` event to load parameters for
  10679 + * a plug-in.
  10680 + * @type function
  10681 + * @param {object} settings DataTables settings object
  10682 + * @param {object} data The state object that is to be loaded
  10683 + *
  10684 + * @dtopt Callbacks
  10685 + * @name DataTable.defaults.stateLoadParams
  10686 + *
  10687 + * @example
  10688 + * // Remove a saved filter, so filtering is never loaded
  10689 + * $(document).ready( function() {
  10690 + * $('#example').dataTable( {
  10691 + * "stateSave": true,
  10692 + * "stateLoadParams": function (settings, data) {
  10693 + * data.oSearch.sSearch = "";
  10694 + * }
  10695 + * } );
  10696 + * } );
  10697 + *
  10698 + * @example
  10699 + * // Disallow state loading by returning false
  10700 + * $(document).ready( function() {
  10701 + * $('#example').dataTable( {
  10702 + * "stateSave": true,
  10703 + * "stateLoadParams": function (settings, data) {
  10704 + * return false;
  10705 + * }
  10706 + * } );
  10707 + * } );
  10708 + */
  10709 + "fnStateLoadParams": null,
  10710 +
  10711 +
  10712 + /**
  10713 + * Callback that is called when the state has been loaded from the state saving method
  10714 + * and the DataTables settings object has been modified as a result of the loaded state.
  10715 + * @type function
  10716 + * @param {object} settings DataTables settings object
  10717 + * @param {object} data The state object that was loaded
  10718 + *
  10719 + * @dtopt Callbacks
  10720 + * @name DataTable.defaults.stateLoaded
  10721 + *
  10722 + * @example
  10723 + * // Show an alert with the filtering value that was saved
  10724 + * $(document).ready( function() {
  10725 + * $('#example').dataTable( {
  10726 + * "stateSave": true,
  10727 + * "stateLoaded": function (settings, data) {
  10728 + * alert( 'Saved filter was: '+data.oSearch.sSearch );
  10729 + * }
  10730 + * } );
  10731 + * } );
  10732 + */
  10733 + "fnStateLoaded": null,
  10734 +
  10735 +
  10736 + /**
  10737 + * Save the table state. This function allows you to define where and how the state
  10738 + * information for the table is stored By default DataTables will use `localStorage`
  10739 + * but you might wish to use a server-side database or cookies.
  10740 + * @type function
  10741 + * @member
  10742 + * @param {object} settings DataTables settings object
  10743 + * @param {object} data The state object to be saved
  10744 + *
  10745 + * @dtopt Callbacks
  10746 + * @name DataTable.defaults.stateSaveCallback
  10747 + *
  10748 + * @example
  10749 + * $(document).ready( function() {
  10750 + * $('#example').dataTable( {
  10751 + * "stateSave": true,
  10752 + * "stateSaveCallback": function (settings, data) {
  10753 + * // Send an Ajax request to the server with the state object
  10754 + * $.ajax( {
  10755 + * "url": "/state_save",
  10756 + * "data": data,
  10757 + * "dataType": "json",
  10758 + * "method": "POST"
  10759 + * "success": function () {}
  10760 + * } );
  10761 + * }
  10762 + * } );
  10763 + * } );
  10764 + */
  10765 + "fnStateSaveCallback": function ( settings, data ) {
  10766 + try {
  10767 + (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
  10768 + 'DataTables_'+settings.sInstance+'_'+location.pathname,
  10769 + JSON.stringify( data )
  10770 + );
  10771 + } catch (e) {}
  10772 + },
  10773 +
  10774 +
  10775 + /**
  10776 + * Callback which allows modification of the state to be saved. Called when the table
  10777 + * has changed state a new state save is required. This method allows modification of
  10778 + * the state saving object prior to actually doing the save, including addition or
  10779 + * other state properties or modification. Note that for plug-in authors, you should
  10780 + * use the `stateSaveParams` event to save parameters for a plug-in.
  10781 + * @type function
  10782 + * @param {object} settings DataTables settings object
  10783 + * @param {object} data The state object to be saved
  10784 + *
  10785 + * @dtopt Callbacks
  10786 + * @name DataTable.defaults.stateSaveParams
  10787 + *
  10788 + * @example
  10789 + * // Remove a saved filter, so filtering is never saved
  10790 + * $(document).ready( function() {
  10791 + * $('#example').dataTable( {
  10792 + * "stateSave": true,
  10793 + * "stateSaveParams": function (settings, data) {
  10794 + * data.oSearch.sSearch = "";
  10795 + * }
  10796 + * } );
  10797 + * } );
  10798 + */
  10799 + "fnStateSaveParams": null,
  10800 +
  10801 +
  10802 + /**
  10803 + * Duration for which the saved state information is considered valid. After this period
  10804 + * has elapsed the state will be returned to the default.
  10805 + * Value is given in seconds.
  10806 + * @type int
  10807 + * @default 7200 <i>(2 hours)</i>
  10808 + *
  10809 + * @dtopt Options
  10810 + * @name DataTable.defaults.stateDuration
  10811 + *
  10812 + * @example
  10813 + * $(document).ready( function() {
  10814 + * $('#example').dataTable( {
  10815 + * "stateDuration": 60*60*24; // 1 day
  10816 + * } );
  10817 + * } )
  10818 + */
  10819 + "iStateDuration": 7200,
  10820 +
  10821 +
  10822 + /**
  10823 + * When enabled DataTables will not make a request to the server for the first
  10824 + * page draw - rather it will use the data already on the page (no sorting etc
  10825 + * will be applied to it), thus saving on an XHR at load time. `deferLoading`
  10826 + * is used to indicate that deferred loading is required, but it is also used
  10827 + * to tell DataTables how many records there are in the full table (allowing
  10828 + * the information element and pagination to be displayed correctly). In the case
  10829 + * where a filtering is applied to the table on initial load, this can be
  10830 + * indicated by giving the parameter as an array, where the first element is
  10831 + * the number of records available after filtering and the second element is the
  10832 + * number of records without filtering (allowing the table information element
  10833 + * to be shown correctly).
  10834 + * @type int | array
  10835 + * @default null
  10836 + *
  10837 + * @dtopt Options
  10838 + * @name DataTable.defaults.deferLoading
  10839 + *
  10840 + * @example
  10841 + * // 57 records available in the table, no filtering applied
  10842 + * $(document).ready( function() {
  10843 + * $('#example').dataTable( {
  10844 + * "serverSide": true,
  10845 + * "ajax": "scripts/server_processing.php",
  10846 + * "deferLoading": 57
  10847 + * } );
  10848 + * } );
  10849 + *
  10850 + * @example
  10851 + * // 57 records after filtering, 100 without filtering (an initial filter applied)
  10852 + * $(document).ready( function() {
  10853 + * $('#example').dataTable( {
  10854 + * "serverSide": true,
  10855 + * "ajax": "scripts/server_processing.php",
  10856 + * "deferLoading": [ 57, 100 ],
  10857 + * "search": {
  10858 + * "search": "my_filter"
  10859 + * }
  10860 + * } );
  10861 + * } );
  10862 + */
  10863 + "iDeferLoading": null,
  10864 +
  10865 +
  10866 + /**
  10867 + * Number of rows to display on a single page when using pagination. If
  10868 + * feature enabled (`lengthChange`) then the end user will be able to override
  10869 + * this to a custom setting using a pop-up menu.
  10870 + * @type int
  10871 + * @default 10
  10872 + *
  10873 + * @dtopt Options
  10874 + * @name DataTable.defaults.pageLength
  10875 + *
  10876 + * @example
  10877 + * $(document).ready( function() {
  10878 + * $('#example').dataTable( {
  10879 + * "pageLength": 50
  10880 + * } );
  10881 + * } )
  10882 + */
  10883 + "iDisplayLength": 10,
  10884 +
  10885 +
  10886 + /**
  10887 + * Define the starting point for data display when using DataTables with
  10888 + * pagination. Note that this parameter is the number of records, rather than
  10889 + * the page number, so if you have 10 records per page and want to start on
  10890 + * the third page, it should be "20".
  10891 + * @type int
  10892 + * @default 0
  10893 + *
  10894 + * @dtopt Options
  10895 + * @name DataTable.defaults.displayStart
  10896 + *
  10897 + * @example
  10898 + * $(document).ready( function() {
  10899 + * $('#example').dataTable( {
  10900 + * "displayStart": 20
  10901 + * } );
  10902 + * } )
  10903 + */
  10904 + "iDisplayStart": 0,
  10905 +
  10906 +
  10907 + /**
  10908 + * By default DataTables allows keyboard navigation of the table (sorting, paging,
  10909 + * and filtering) by adding a `tabindex` attribute to the required elements. This
  10910 + * allows you to tab through the controls and press the enter key to activate them.
  10911 + * The tabindex is default 0, meaning that the tab follows the flow of the document.
  10912 + * You can overrule this using this parameter if you wish. Use a value of -1 to
  10913 + * disable built-in keyboard navigation.
  10914 + * @type int
  10915 + * @default 0
  10916 + *
  10917 + * @dtopt Options
  10918 + * @name DataTable.defaults.tabIndex
  10919 + *
  10920 + * @example
  10921 + * $(document).ready( function() {
  10922 + * $('#example').dataTable( {
  10923 + * "tabIndex": 1
  10924 + * } );
  10925 + * } );
  10926 + */
  10927 + "iTabIndex": 0,
  10928 +
  10929 +
  10930 + /**
  10931 + * Classes that DataTables assigns to the various components and features
  10932 + * that it adds to the HTML table. This allows classes to be configured
  10933 + * during initialisation in addition to through the static
  10934 + * {@link DataTable.ext.oStdClasses} object).
  10935 + * @namespace
  10936 + * @name DataTable.defaults.classes
  10937 + */
  10938 + "oClasses": {},
  10939 +
  10940 +
  10941 + /**
  10942 + * All strings that DataTables uses in the user interface that it creates
  10943 + * are defined in this object, allowing you to modified them individually or
  10944 + * completely replace them all as required.
  10945 + * @namespace
  10946 + * @name DataTable.defaults.language
  10947 + */
  10948 + "oLanguage": {
  10949 + /**
  10950 + * Strings that are used for WAI-ARIA labels and controls only (these are not
  10951 + * actually visible on the page, but will be read by screenreaders, and thus
  10952 + * must be internationalised as well).
  10953 + * @namespace
  10954 + * @name DataTable.defaults.language.aria
  10955 + */
  10956 + "oAria": {
  10957 + /**
  10958 + * ARIA label that is added to the table headers when the column may be
  10959 + * sorted ascending by activing the column (click or return when focused).
  10960 + * Note that the column header is prefixed to this string.
  10961 + * @type string
  10962 + * @default : activate to sort column ascending
  10963 + *
  10964 + * @dtopt Language
  10965 + * @name DataTable.defaults.language.aria.sortAscending
  10966 + *
  10967 + * @example
  10968 + * $(document).ready( function() {
  10969 + * $('#example').dataTable( {
  10970 + * "language": {
  10971 + * "aria": {
  10972 + * "sortAscending": " - click/return to sort ascending"
  10973 + * }
  10974 + * }
  10975 + * } );
  10976 + * } );
  10977 + */
  10978 + "sSortAscending": ": activate to sort column ascending",
  10979 +
  10980 + /**
  10981 + * ARIA label that is added to the table headers when the column may be
  10982 + * sorted descending by activing the column (click or return when focused).
  10983 + * Note that the column header is prefixed to this string.
  10984 + * @type string
  10985 + * @default : activate to sort column ascending
  10986 + *
  10987 + * @dtopt Language
  10988 + * @name DataTable.defaults.language.aria.sortDescending
  10989 + *
  10990 + * @example
  10991 + * $(document).ready( function() {
  10992 + * $('#example').dataTable( {
  10993 + * "language": {
  10994 + * "aria": {
  10995 + * "sortDescending": " - click/return to sort descending"
  10996 + * }
  10997 + * }
  10998 + * } );
  10999 + * } );
  11000 + */
  11001 + "sSortDescending": ": activate to sort column descending"
  11002 + },
  11003 +
  11004 + /**
  11005 + * Pagination string used by DataTables for the built-in pagination
  11006 + * control types.
  11007 + * @namespace
  11008 + * @name DataTable.defaults.language.paginate
  11009 + */
  11010 + "oPaginate": {
  11011 + /**
  11012 + * Text to use when using the 'full_numbers' type of pagination for the
  11013 + * button to take the user to the first page.
  11014 + * @type string
  11015 + * @default First
  11016 + *
  11017 + * @dtopt Language
  11018 + * @name DataTable.defaults.language.paginate.first
  11019 + *
  11020 + * @example
  11021 + * $(document).ready( function() {
  11022 + * $('#example').dataTable( {
  11023 + * "language": {
  11024 + * "paginate": {
  11025 + * "first": "First page"
  11026 + * }
  11027 + * }
  11028 + * } );
  11029 + * } );
  11030 + */
  11031 + "sFirst": "First",
  11032 +
  11033 +
  11034 + /**
  11035 + * Text to use when using the 'full_numbers' type of pagination for the
  11036 + * button to take the user to the last page.
  11037 + * @type string
  11038 + * @default Last
  11039 + *
  11040 + * @dtopt Language
  11041 + * @name DataTable.defaults.language.paginate.last
  11042 + *
  11043 + * @example
  11044 + * $(document).ready( function() {
  11045 + * $('#example').dataTable( {
  11046 + * "language": {
  11047 + * "paginate": {
  11048 + * "last": "Last page"
  11049 + * }
  11050 + * }
  11051 + * } );
  11052 + * } );
  11053 + */
  11054 + "sLast": "Last",
  11055 +
  11056 +
  11057 + /**
  11058 + * Text to use for the 'next' pagination button (to take the user to the
  11059 + * next page).
  11060 + * @type string
  11061 + * @default Next
  11062 + *
  11063 + * @dtopt Language
  11064 + * @name DataTable.defaults.language.paginate.next
  11065 + *
  11066 + * @example
  11067 + * $(document).ready( function() {
  11068 + * $('#example').dataTable( {
  11069 + * "language": {
  11070 + * "paginate": {
  11071 + * "next": "Next page"
  11072 + * }
  11073 + * }
  11074 + * } );
  11075 + * } );
  11076 + */
  11077 + "sNext": "Next",
  11078 +
  11079 +
  11080 + /**
  11081 + * Text to use for the 'previous' pagination button (to take the user to
  11082 + * the previous page).
  11083 + * @type string
  11084 + * @default Previous
  11085 + *
  11086 + * @dtopt Language
  11087 + * @name DataTable.defaults.language.paginate.previous
  11088 + *
  11089 + * @example
  11090 + * $(document).ready( function() {
  11091 + * $('#example').dataTable( {
  11092 + * "language": {
  11093 + * "paginate": {
  11094 + * "previous": "Previous page"
  11095 + * }
  11096 + * }
  11097 + * } );
  11098 + * } );
  11099 + */
  11100 + "sPrevious": "Previous"
  11101 + },
  11102 +
  11103 + /**
  11104 + * This string is shown in preference to `zeroRecords` when the table is
  11105 + * empty of data (regardless of filtering). Note that this is an optional
  11106 + * parameter - if it is not given, the value of `zeroRecords` will be used
  11107 + * instead (either the default or given value).
  11108 + * @type string
  11109 + * @default No data available in table
  11110 + *
  11111 + * @dtopt Language
  11112 + * @name DataTable.defaults.language.emptyTable
  11113 + *
  11114 + * @example
  11115 + * $(document).ready( function() {
  11116 + * $('#example').dataTable( {
  11117 + * "language": {
  11118 + * "emptyTable": "No data available in table"
  11119 + * }
  11120 + * } );
  11121 + * } );
  11122 + */
  11123 + "sEmptyTable": "No data available in table",
  11124 +
  11125 +
  11126 + /**
  11127 + * This string gives information to the end user about the information
  11128 + * that is current on display on the page. The following tokens can be
  11129 + * used in the string and will be dynamically replaced as the table
  11130 + * display updates. This tokens can be placed anywhere in the string, or
  11131 + * removed as needed by the language requires:
  11132 + *
  11133 + * * `\_START\_` - Display index of the first record on the current page
  11134 + * * `\_END\_` - Display index of the last record on the current page
  11135 + * * `\_TOTAL\_` - Number of records in the table after filtering
  11136 + * * `\_MAX\_` - Number of records in the table without filtering
  11137 + * * `\_PAGE\_` - Current page number
  11138 + * * `\_PAGES\_` - Total number of pages of data in the table
  11139 + *
  11140 + * @type string
  11141 + * @default Showing _START_ to _END_ of _TOTAL_ entries
  11142 + *
  11143 + * @dtopt Language
  11144 + * @name DataTable.defaults.language.info
  11145 + *
  11146 + * @example
  11147 + * $(document).ready( function() {
  11148 + * $('#example').dataTable( {
  11149 + * "language": {
  11150 + * "info": "Showing page _PAGE_ of _PAGES_"
  11151 + * }
  11152 + * } );
  11153 + * } );
  11154 + */
  11155 + "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
  11156 +
  11157 +
  11158 + /**
  11159 + * Display information string for when the table is empty. Typically the
  11160 + * format of this string should match `info`.
  11161 + * @type string
  11162 + * @default Showing 0 to 0 of 0 entries
  11163 + *
  11164 + * @dtopt Language
  11165 + * @name DataTable.defaults.language.infoEmpty
  11166 + *
  11167 + * @example
  11168 + * $(document).ready( function() {
  11169 + * $('#example').dataTable( {
  11170 + * "language": {
  11171 + * "infoEmpty": "No entries to show"
  11172 + * }
  11173 + * } );
  11174 + * } );
  11175 + */
  11176 + "sInfoEmpty": "Showing 0 to 0 of 0 entries",
  11177 +
  11178 +
  11179 + /**
  11180 + * When a user filters the information in a table, this string is appended
  11181 + * to the information (`info`) to give an idea of how strong the filtering
  11182 + * is. The variable _MAX_ is dynamically updated.
  11183 + * @type string
  11184 + * @default (filtered from _MAX_ total entries)
  11185 + *
  11186 + * @dtopt Language
  11187 + * @name DataTable.defaults.language.infoFiltered
  11188 + *
  11189 + * @example
  11190 + * $(document).ready( function() {
  11191 + * $('#example').dataTable( {
  11192 + * "language": {
  11193 + * "infoFiltered": " - filtering from _MAX_ records"
  11194 + * }
  11195 + * } );
  11196 + * } );
  11197 + */
  11198 + "sInfoFiltered": "(filtered from _MAX_ total entries)",
  11199 +
  11200 +
  11201 + /**
  11202 + * If can be useful to append extra information to the info string at times,
  11203 + * and this variable does exactly that. This information will be appended to
  11204 + * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
  11205 + * being used) at all times.
  11206 + * @type string
  11207 + * @default <i>Empty string</i>
  11208 + *
  11209 + * @dtopt Language
  11210 + * @name DataTable.defaults.language.infoPostFix
  11211 + *
  11212 + * @example
  11213 + * $(document).ready( function() {
  11214 + * $('#example').dataTable( {
  11215 + * "language": {
  11216 + * "infoPostFix": "All records shown are derived from real information."
  11217 + * }
  11218 + * } );
  11219 + * } );
  11220 + */
  11221 + "sInfoPostFix": "",
  11222 +
  11223 +
  11224 + /**
  11225 + * This decimal place operator is a little different from the other
  11226 + * language options since DataTables doesn't output floating point
  11227 + * numbers, so it won't ever use this for display of a number. Rather,
  11228 + * what this parameter does is modify the sort methods of the table so
  11229 + * that numbers which are in a format which has a character other than
  11230 + * a period (`.`) as a decimal place will be sorted numerically.
  11231 + *
  11232 + * Note that numbers with different decimal places cannot be shown in
  11233 + * the same table and still be sortable, the table must be consistent.
  11234 + * However, multiple different tables on the page can use different
  11235 + * decimal place characters.
  11236 + * @type string
  11237 + * @default
  11238 + *
  11239 + * @dtopt Language
  11240 + * @name DataTable.defaults.language.decimal
  11241 + *
  11242 + * @example
  11243 + * $(document).ready( function() {
  11244 + * $('#example').dataTable( {
  11245 + * "language": {
  11246 + * "decimal": ","
  11247 + * "thousands": "."
  11248 + * }
  11249 + * } );
  11250 + * } );
  11251 + */
  11252 + "sDecimal": "",
  11253 +
  11254 +
  11255 + /**
  11256 + * DataTables has a build in number formatter (`formatNumber`) which is
  11257 + * used to format large numbers that are used in the table information.
  11258 + * By default a comma is used, but this can be trivially changed to any
  11259 + * character you wish with this parameter.
  11260 + * @type string
  11261 + * @default ,
  11262 + *
  11263 + * @dtopt Language
  11264 + * @name DataTable.defaults.language.thousands
  11265 + *
  11266 + * @example
  11267 + * $(document).ready( function() {
  11268 + * $('#example').dataTable( {
  11269 + * "language": {
  11270 + * "thousands": "'"
  11271 + * }
  11272 + * } );
  11273 + * } );
  11274 + */
  11275 + "sThousands": ",",
  11276 +
  11277 +
  11278 + /**
  11279 + * Detail the action that will be taken when the drop down menu for the
  11280 + * pagination length option is changed. The '_MENU_' variable is replaced
  11281 + * with a default select list of 10, 25, 50 and 100, and can be replaced
  11282 + * with a custom select box if required.
  11283 + * @type string
  11284 + * @default Show _MENU_ entries
  11285 + *
  11286 + * @dtopt Language
  11287 + * @name DataTable.defaults.language.lengthMenu
  11288 + *
  11289 + * @example
  11290 + * // Language change only
  11291 + * $(document).ready( function() {
  11292 + * $('#example').dataTable( {
  11293 + * "language": {
  11294 + * "lengthMenu": "Display _MENU_ records"
  11295 + * }
  11296 + * } );
  11297 + * } );
  11298 + *
  11299 + * @example
  11300 + * // Language and options change
  11301 + * $(document).ready( function() {
  11302 + * $('#example').dataTable( {
  11303 + * "language": {
  11304 + * "lengthMenu": 'Display <select>'+
  11305 + * '<option value="10">10</option>'+
  11306 + * '<option value="20">20</option>'+
  11307 + * '<option value="30">30</option>'+
  11308 + * '<option value="40">40</option>'+
  11309 + * '<option value="50">50</option>'+
  11310 + * '<option value="-1">All</option>'+
  11311 + * '</select> records'
  11312 + * }
  11313 + * } );
  11314 + * } );
  11315 + */
  11316 + "sLengthMenu": "Show _MENU_ entries",
  11317 +
  11318 +
  11319 + /**
  11320 + * When using Ajax sourced data and during the first draw when DataTables is
  11321 + * gathering the data, this message is shown in an empty row in the table to
  11322 + * indicate to the end user the the data is being loaded. Note that this
  11323 + * parameter is not used when loading data by server-side processing, just
  11324 + * Ajax sourced data with client-side processing.
  11325 + * @type string
  11326 + * @default Loading...
  11327 + *
  11328 + * @dtopt Language
  11329 + * @name DataTable.defaults.language.loadingRecords
  11330 + *
  11331 + * @example
  11332 + * $(document).ready( function() {
  11333 + * $('#example').dataTable( {
  11334 + * "language": {
  11335 + * "loadingRecords": "Please wait - loading..."
  11336 + * }
  11337 + * } );
  11338 + * } );
  11339 + */
  11340 + "sLoadingRecords": "Loading...",
  11341 +
  11342 +
  11343 + /**
  11344 + * Text which is displayed when the table is processing a user action
  11345 + * (usually a sort command or similar).
  11346 + * @type string
  11347 + * @default Processing...
  11348 + *
  11349 + * @dtopt Language
  11350 + * @name DataTable.defaults.language.processing
  11351 + *
  11352 + * @example
  11353 + * $(document).ready( function() {
  11354 + * $('#example').dataTable( {
  11355 + * "language": {
  11356 + * "processing": "DataTables is currently busy"
  11357 + * }
  11358 + * } );
  11359 + * } );
  11360 + */
  11361 + "sProcessing": "Processing...",
  11362 +
  11363 +
  11364 + /**
  11365 + * Details the actions that will be taken when the user types into the
  11366 + * filtering input text box. The variable "_INPUT_", if used in the string,
  11367 + * is replaced with the HTML text box for the filtering input allowing
  11368 + * control over where it appears in the string. If "_INPUT_" is not given
  11369 + * then the input box is appended to the string automatically.
  11370 + * @type string
  11371 + * @default Search:
  11372 + *
  11373 + * @dtopt Language
  11374 + * @name DataTable.defaults.language.search
  11375 + *
  11376 + * @example
  11377 + * // Input text box will be appended at the end automatically
  11378 + * $(document).ready( function() {
  11379 + * $('#example').dataTable( {
  11380 + * "language": {
  11381 + * "search": "Filter records:"
  11382 + * }
  11383 + * } );
  11384 + * } );
  11385 + *
  11386 + * @example
  11387 + * // Specify where the filter should appear
  11388 + * $(document).ready( function() {
  11389 + * $('#example').dataTable( {
  11390 + * "language": {
  11391 + * "search": "Apply filter _INPUT_ to table"
  11392 + * }
  11393 + * } );
  11394 + * } );
  11395 + */
  11396 + "sSearch": "Search:",
  11397 +
  11398 +
  11399 + /**
  11400 + * Assign a `placeholder` attribute to the search `input` element
  11401 + * @type string
  11402 + * @default
  11403 + *
  11404 + * @dtopt Language
  11405 + * @name DataTable.defaults.language.searchPlaceholder
  11406 + */
  11407 + "sSearchPlaceholder": "",
  11408 +
  11409 +
  11410 + /**
  11411 + * All of the language information can be stored in a file on the
  11412 + * server-side, which DataTables will look up if this parameter is passed.
  11413 + * It must store the URL of the language file, which is in a JSON format,
  11414 + * and the object has the same properties as the oLanguage object in the
  11415 + * initialiser object (i.e. the above parameters). Please refer to one of
  11416 + * the example language files to see how this works in action.
  11417 + * @type string
  11418 + * @default <i>Empty string - i.e. disabled</i>
  11419 + *
  11420 + * @dtopt Language
  11421 + * @name DataTable.defaults.language.url
  11422 + *
  11423 + * @example
  11424 + * $(document).ready( function() {
  11425 + * $('#example').dataTable( {
  11426 + * "language": {
  11427 + * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
  11428 + * }
  11429 + * } );
  11430 + * } );
  11431 + */
  11432 + "sUrl": "",
  11433 +
  11434 +
  11435 + /**
  11436 + * Text shown inside the table records when the is no information to be
  11437 + * displayed after filtering. `emptyTable` is shown when there is simply no
  11438 + * information in the table at all (regardless of filtering).
  11439 + * @type string
  11440 + * @default No matching records found
  11441 + *
  11442 + * @dtopt Language
  11443 + * @name DataTable.defaults.language.zeroRecords
  11444 + *
  11445 + * @example
  11446 + * $(document).ready( function() {
  11447 + * $('#example').dataTable( {
  11448 + * "language": {
  11449 + * "zeroRecords": "No records to display"
  11450 + * }
  11451 + * } );
  11452 + * } );
  11453 + */
  11454 + "sZeroRecords": "No matching records found"
  11455 + },
  11456 +
  11457 +
  11458 + /**
  11459 + * This parameter allows you to have define the global filtering state at
  11460 + * initialisation time. As an object the `search` parameter must be
  11461 + * defined, but all other parameters are optional. When `regex` is true,
  11462 + * the search string will be treated as a regular expression, when false
  11463 + * (default) it will be treated as a straight string. When `smart`
  11464 + * DataTables will use it's smart filtering methods (to word match at
  11465 + * any point in the data), when false this will not be done.
  11466 + * @namespace
  11467 + * @extends DataTable.models.oSearch
  11468 + *
  11469 + * @dtopt Options
  11470 + * @name DataTable.defaults.search
  11471 + *
  11472 + * @example
  11473 + * $(document).ready( function() {
  11474 + * $('#example').dataTable( {
  11475 + * "search": {"search": "Initial search"}
  11476 + * } );
  11477 + * } )
  11478 + */
  11479 + "oSearch": $.extend( {}, DataTable.models.oSearch ),
  11480 +
  11481 +
  11482 + /**
  11483 + * __Deprecated__ The functionality provided by this parameter has now been
  11484 + * superseded by that provided through `ajax`, which should be used instead.
  11485 + *
  11486 + * By default DataTables will look for the property `data` (or `aaData` for
  11487 + * compatibility with DataTables 1.9-) when obtaining data from an Ajax
  11488 + * source or for server-side processing - this parameter allows that
  11489 + * property to be changed. You can use Javascript dotted object notation to
  11490 + * get a data source for multiple levels of nesting.
  11491 + * @type string
  11492 + * @default data
  11493 + *
  11494 + * @dtopt Options
  11495 + * @dtopt Server-side
  11496 + * @name DataTable.defaults.ajaxDataProp
  11497 + *
  11498 + * @deprecated 1.10. Please use `ajax` for this functionality now.
  11499 + */
  11500 + "sAjaxDataProp": "data",
  11501 +
  11502 +
  11503 + /**
  11504 + * __Deprecated__ The functionality provided by this parameter has now been
  11505 + * superseded by that provided through `ajax`, which should be used instead.
  11506 + *
  11507 + * You can instruct DataTables to load data from an external
  11508 + * source using this parameter (use aData if you want to pass data in you
  11509 + * already have). Simply provide a url a JSON object can be obtained from.
  11510 + * @type string
  11511 + * @default null
  11512 + *
  11513 + * @dtopt Options
  11514 + * @dtopt Server-side
  11515 + * @name DataTable.defaults.ajaxSource
  11516 + *
  11517 + * @deprecated 1.10. Please use `ajax` for this functionality now.
  11518 + */
  11519 + "sAjaxSource": null,
  11520 +
  11521 +
  11522 + /**
  11523 + * This initialisation variable allows you to specify exactly where in the
  11524 + * DOM you want DataTables to inject the various controls it adds to the page
  11525 + * (for example you might want the pagination controls at the top of the
  11526 + * table). DIV elements (with or without a custom class) can also be added to
  11527 + * aid styling. The follow syntax is used:
  11528 + * <ul>
  11529 + * <li>The following options are allowed:
  11530 + * <ul>
  11531 + * <li>'l' - Length changing</li>
  11532 + * <li>'f' - Filtering input</li>
  11533 + * <li>'t' - The table!</li>
  11534 + * <li>'i' - Information</li>
  11535 + * <li>'p' - Pagination</li>
  11536 + * <li>'r' - pRocessing</li>
  11537 + * </ul>
  11538 + * </li>
  11539 + * <li>The following constants are allowed:
  11540 + * <ul>
  11541 + * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
  11542 + * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
  11543 + * </ul>
  11544 + * </li>
  11545 + * <li>The following syntax is expected:
  11546 + * <ul>
  11547 + * <li>'&lt;' and '&gt;' - div elements</li>
  11548 + * <li>'&lt;"class" and '&gt;' - div with a class</li>
  11549 + * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
  11550 + * </ul>
  11551 + * </li>
  11552 + * <li>Examples:
  11553 + * <ul>
  11554 + * <li>'&lt;"wrapper"flipt&gt;'</li>
  11555 + * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
  11556 + * </ul>
  11557 + * </li>
  11558 + * </ul>
  11559 + * @type string
  11560 + * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
  11561 + * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
  11562 + *
  11563 + * @dtopt Options
  11564 + * @name DataTable.defaults.dom
  11565 + *
  11566 + * @example
  11567 + * $(document).ready( function() {
  11568 + * $('#example').dataTable( {
  11569 + * "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
  11570 + * } );
  11571 + * } );
  11572 + */
  11573 + "sDom": "lfrtip",
  11574 +
  11575 +
  11576 + /**
  11577 + * Search delay option. This will throttle full table searches that use the
  11578 + * DataTables provided search input element (it does not effect calls to
  11579 + * `dt-api search()`, providing a delay before the search is made.
  11580 + * @type integer
  11581 + * @default 0
  11582 + *
  11583 + * @dtopt Options
  11584 + * @name DataTable.defaults.searchDelay
  11585 + *
  11586 + * @example
  11587 + * $(document).ready( function() {
  11588 + * $('#example').dataTable( {
  11589 + * "searchDelay": 200
  11590 + * } );
  11591 + * } )
  11592 + */
  11593 + "searchDelay": null,
  11594 +
  11595 +
  11596 + /**
  11597 + * DataTables features four different built-in options for the buttons to
  11598 + * display for pagination control:
  11599 + *
  11600 + * * `simple` - 'Previous' and 'Next' buttons only
  11601 + * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
  11602 + * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
  11603 + * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
  11604 + * page numbers
  11605 + *
  11606 + * Further methods can be added using {@link DataTable.ext.oPagination}.
  11607 + * @type string
  11608 + * @default simple_numbers
  11609 + *
  11610 + * @dtopt Options
  11611 + * @name DataTable.defaults.pagingType
  11612 + *
  11613 + * @example
  11614 + * $(document).ready( function() {
  11615 + * $('#example').dataTable( {
  11616 + * "pagingType": "full_numbers"
  11617 + * } );
  11618 + * } )
  11619 + */
  11620 + "sPaginationType": "simple_numbers",
  11621 +
  11622 +
  11623 + /**
  11624 + * Enable horizontal scrolling. When a table is too wide to fit into a
  11625 + * certain layout, or you have a large number of columns in the table, you
  11626 + * can enable x-scrolling to show the table in a viewport, which can be
  11627 + * scrolled. This property can be `true` which will allow the table to
  11628 + * scroll horizontally when needed, or any CSS unit, or a number (in which
  11629 + * case it will be treated as a pixel measurement). Setting as simply `true`
  11630 + * is recommended.
  11631 + * @type boolean|string
  11632 + * @default <i>blank string - i.e. disabled</i>
  11633 + *
  11634 + * @dtopt Features
  11635 + * @name DataTable.defaults.scrollX
  11636 + *
  11637 + * @example
  11638 + * $(document).ready( function() {
  11639 + * $('#example').dataTable( {
  11640 + * "scrollX": true,
  11641 + * "scrollCollapse": true
  11642 + * } );
  11643 + * } );
  11644 + */
  11645 + "sScrollX": "",
  11646 +
  11647 +
  11648 + /**
  11649 + * This property can be used to force a DataTable to use more width than it
  11650 + * might otherwise do when x-scrolling is enabled. For example if you have a
  11651 + * table which requires to be well spaced, this parameter is useful for
  11652 + * "over-sizing" the table, and thus forcing scrolling. This property can by
  11653 + * any CSS unit, or a number (in which case it will be treated as a pixel
  11654 + * measurement).
  11655 + * @type string
  11656 + * @default <i>blank string - i.e. disabled</i>
  11657 + *
  11658 + * @dtopt Options
  11659 + * @name DataTable.defaults.scrollXInner
  11660 + *
  11661 + * @example
  11662 + * $(document).ready( function() {
  11663 + * $('#example').dataTable( {
  11664 + * "scrollX": "100%",
  11665 + * "scrollXInner": "110%"
  11666 + * } );
  11667 + * } );
  11668 + */
  11669 + "sScrollXInner": "",
  11670 +
  11671 +
  11672 + /**
  11673 + * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
  11674 + * to the given height, and enable scrolling for any data which overflows the
  11675 + * current viewport. This can be used as an alternative to paging to display
  11676 + * a lot of data in a small area (although paging and scrolling can both be
  11677 + * enabled at the same time). This property can be any CSS unit, or a number
  11678 + * (in which case it will be treated as a pixel measurement).
  11679 + * @type string
  11680 + * @default <i>blank string - i.e. disabled</i>
  11681 + *
  11682 + * @dtopt Features
  11683 + * @name DataTable.defaults.scrollY
  11684 + *
  11685 + * @example
  11686 + * $(document).ready( function() {
  11687 + * $('#example').dataTable( {
  11688 + * "scrollY": "200px",
  11689 + * "paginate": false
  11690 + * } );
  11691 + * } );
  11692 + */
  11693 + "sScrollY": "",
  11694 +
  11695 +
  11696 + /**
  11697 + * __Deprecated__ The functionality provided by this parameter has now been
  11698 + * superseded by that provided through `ajax`, which should be used instead.
  11699 + *
  11700 + * Set the HTTP method that is used to make the Ajax call for server-side
  11701 + * processing or Ajax sourced data.
  11702 + * @type string
  11703 + * @default GET
  11704 + *
  11705 + * @dtopt Options
  11706 + * @dtopt Server-side
  11707 + * @name DataTable.defaults.serverMethod
  11708 + *
  11709 + * @deprecated 1.10. Please use `ajax` for this functionality now.
  11710 + */
  11711 + "sServerMethod": "GET",
  11712 +
  11713 +
  11714 + /**
  11715 + * DataTables makes use of renderers when displaying HTML elements for
  11716 + * a table. These renderers can be added or modified by plug-ins to
  11717 + * generate suitable mark-up for a site. For example the Bootstrap
  11718 + * integration plug-in for DataTables uses a paging button renderer to
  11719 + * display pagination buttons in the mark-up required by Bootstrap.
  11720 + *
  11721 + * For further information about the renderers available see
  11722 + * DataTable.ext.renderer
  11723 + * @type string|object
  11724 + * @default null
  11725 + *
  11726 + * @name DataTable.defaults.renderer
  11727 + *
  11728 + */
  11729 + "renderer": null
  11730 + };
  11731 +
  11732 + _fnHungarianMap( DataTable.defaults );
  11733 +
  11734 +
  11735 +
  11736 + /*
  11737 + * Developer note - See note in model.defaults.js about the use of Hungarian
  11738 + * notation and camel case.
  11739 + */
  11740 +
  11741 + /**
  11742 + * Column options that can be given to DataTables at initialisation time.
  11743 + * @namespace
  11744 + */
  11745 + DataTable.defaults.column = {
  11746 + /**
  11747 + * Define which column(s) an order will occur on for this column. This
  11748 + * allows a column's ordering to take multiple columns into account when
  11749 + * doing a sort or use the data from a different column. For example first
  11750 + * name / last name columns make sense to do a multi-column sort over the
  11751 + * two columns.
  11752 + * @type array|int
  11753 + * @default null <i>Takes the value of the column index automatically</i>
  11754 + *
  11755 + * @name DataTable.defaults.column.orderData
  11756 + * @dtopt Columns
  11757 + *
  11758 + * @example
  11759 + * // Using `columnDefs`
  11760 + * $(document).ready( function() {
  11761 + * $('#example').dataTable( {
  11762 + * "columnDefs": [
  11763 + * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
  11764 + * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
  11765 + * { "orderData": 2, "targets": [ 2 ] }
  11766 + * ]
  11767 + * } );
  11768 + * } );
  11769 + *
  11770 + * @example
  11771 + * // Using `columns`
  11772 + * $(document).ready( function() {
  11773 + * $('#example').dataTable( {
  11774 + * "columns": [
  11775 + * { "orderData": [ 0, 1 ] },
  11776 + * { "orderData": [ 1, 0 ] },
  11777 + * { "orderData": 2 },
  11778 + * null,
  11779 + * null
  11780 + * ]
  11781 + * } );
  11782 + * } );
  11783 + */
  11784 + "aDataSort": null,
  11785 + "iDataSort": -1,
  11786 +
  11787 +
  11788 + /**
  11789 + * You can control the default ordering direction, and even alter the
  11790 + * behaviour of the sort handler (i.e. only allow ascending ordering etc)
  11791 + * using this parameter.
  11792 + * @type array
  11793 + * @default [ 'asc', 'desc' ]
  11794 + *
  11795 + * @name DataTable.defaults.column.orderSequence
  11796 + * @dtopt Columns
  11797 + *
  11798 + * @example
  11799 + * // Using `columnDefs`
  11800 + * $(document).ready( function() {
  11801 + * $('#example').dataTable( {
  11802 + * "columnDefs": [
  11803 + * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
  11804 + * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
  11805 + * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
  11806 + * ]
  11807 + * } );
  11808 + * } );
  11809 + *
  11810 + * @example
  11811 + * // Using `columns`
  11812 + * $(document).ready( function() {
  11813 + * $('#example').dataTable( {
  11814 + * "columns": [
  11815 + * null,
  11816 + * { "orderSequence": [ "asc" ] },
  11817 + * { "orderSequence": [ "desc", "asc", "asc" ] },
  11818 + * { "orderSequence": [ "desc" ] },
  11819 + * null
  11820 + * ]
  11821 + * } );
  11822 + * } );
  11823 + */
  11824 + "asSorting": [ 'asc', 'desc' ],
  11825 +
  11826 +
  11827 + /**
  11828 + * Enable or disable filtering on the data in this column.
  11829 + * @type boolean
  11830 + * @default true
  11831 + *
  11832 + * @name DataTable.defaults.column.searchable
  11833 + * @dtopt Columns
  11834 + *
  11835 + * @example
  11836 + * // Using `columnDefs`
  11837 + * $(document).ready( function() {
  11838 + * $('#example').dataTable( {
  11839 + * "columnDefs": [
  11840 + * { "searchable": false, "targets": [ 0 ] }
  11841 + * ] } );
  11842 + * } );
  11843 + *
  11844 + * @example
  11845 + * // Using `columns`
  11846 + * $(document).ready( function() {
  11847 + * $('#example').dataTable( {
  11848 + * "columns": [
  11849 + * { "searchable": false },
  11850 + * null,
  11851 + * null,
  11852 + * null,
  11853 + * null
  11854 + * ] } );
  11855 + * } );
  11856 + */
  11857 + "bSearchable": true,
  11858 +
  11859 +
  11860 + /**
  11861 + * Enable or disable ordering on this column.
  11862 + * @type boolean
  11863 + * @default true
  11864 + *
  11865 + * @name DataTable.defaults.column.orderable
  11866 + * @dtopt Columns
  11867 + *
  11868 + * @example
  11869 + * // Using `columnDefs`
  11870 + * $(document).ready( function() {
  11871 + * $('#example').dataTable( {
  11872 + * "columnDefs": [
  11873 + * { "orderable": false, "targets": [ 0 ] }
  11874 + * ] } );
  11875 + * } );
  11876 + *
  11877 + * @example
  11878 + * // Using `columns`
  11879 + * $(document).ready( function() {
  11880 + * $('#example').dataTable( {
  11881 + * "columns": [
  11882 + * { "orderable": false },
  11883 + * null,
  11884 + * null,
  11885 + * null,
  11886 + * null
  11887 + * ] } );
  11888 + * } );
  11889 + */
  11890 + "bSortable": true,
  11891 +
  11892 +
  11893 + /**
  11894 + * Enable or disable the display of this column.
  11895 + * @type boolean
  11896 + * @default true
  11897 + *
  11898 + * @name DataTable.defaults.column.visible
  11899 + * @dtopt Columns
  11900 + *
  11901 + * @example
  11902 + * // Using `columnDefs`
  11903 + * $(document).ready( function() {
  11904 + * $('#example').dataTable( {
  11905 + * "columnDefs": [
  11906 + * { "visible": false, "targets": [ 0 ] }
  11907 + * ] } );
  11908 + * } );
  11909 + *
  11910 + * @example
  11911 + * // Using `columns`
  11912 + * $(document).ready( function() {
  11913 + * $('#example').dataTable( {
  11914 + * "columns": [
  11915 + * { "visible": false },
  11916 + * null,
  11917 + * null,
  11918 + * null,
  11919 + * null
  11920 + * ] } );
  11921 + * } );
  11922 + */
  11923 + "bVisible": true,
  11924 +
  11925 +
  11926 + /**
  11927 + * Developer definable function that is called whenever a cell is created (Ajax source,
  11928 + * etc) or processed for input (DOM source). This can be used as a compliment to mRender
  11929 + * allowing you to modify the DOM element (add background colour for example) when the
  11930 + * element is available.
  11931 + * @type function
  11932 + * @param {element} td The TD node that has been created
  11933 + * @param {*} cellData The Data for the cell
  11934 + * @param {array|object} rowData The data for the whole row
  11935 + * @param {int} row The row index for the aoData data store
  11936 + * @param {int} col The column index for aoColumns
  11937 + *
  11938 + * @name DataTable.defaults.column.createdCell
  11939 + * @dtopt Columns
  11940 + *
  11941 + * @example
  11942 + * $(document).ready( function() {
  11943 + * $('#example').dataTable( {
  11944 + * "columnDefs": [ {
  11945 + * "targets": [3],
  11946 + * "createdCell": function (td, cellData, rowData, row, col) {
  11947 + * if ( cellData == "1.7" ) {
  11948 + * $(td).css('color', 'blue')
  11949 + * }
  11950 + * }
  11951 + * } ]
  11952 + * });
  11953 + * } );
  11954 + */
  11955 + "fnCreatedCell": null,
  11956 +
  11957 +
  11958 + /**
  11959 + * This parameter has been replaced by `data` in DataTables to ensure naming
  11960 + * consistency. `dataProp` can still be used, as there is backwards
  11961 + * compatibility in DataTables for this option, but it is strongly
  11962 + * recommended that you use `data` in preference to `dataProp`.
  11963 + * @name DataTable.defaults.column.dataProp
  11964 + */
  11965 +
  11966 +
  11967 + /**
  11968 + * This property can be used to read data from any data source property,
  11969 + * including deeply nested objects / properties. `data` can be given in a
  11970 + * number of different ways which effect its behaviour:
  11971 + *
  11972 + * * `integer` - treated as an array index for the data source. This is the
  11973 + * default that DataTables uses (incrementally increased for each column).
  11974 + * * `string` - read an object property from the data source. There are
  11975 + * three 'special' options that can be used in the string to alter how
  11976 + * DataTables reads the data from the source object:
  11977 + * * `.` - Dotted Javascript notation. Just as you use a `.` in
  11978 + * Javascript to read from nested objects, so to can the options
  11979 + * specified in `data`. For example: `browser.version` or
  11980 + * `browser.name`. If your object parameter name contains a period, use
  11981 + * `\\` to escape it - i.e. `first\\.name`.
  11982 + * * `[]` - Array notation. DataTables can automatically combine data
  11983 + * from and array source, joining the data with the characters provided
  11984 + * between the two brackets. For example: `name[, ]` would provide a
  11985 + * comma-space separated list from the source array. If no characters
  11986 + * are provided between the brackets, the original array source is
  11987 + * returned.
  11988 + * * `()` - Function notation. Adding `()` to the end of a parameter will
  11989 + * execute a function of the name given. For example: `browser()` for a
  11990 + * simple function on the data source, `browser.version()` for a
  11991 + * function in a nested property or even `browser().version` to get an
  11992 + * object property if the function called returns an object. Note that
  11993 + * function notation is recommended for use in `render` rather than
  11994 + * `data` as it is much simpler to use as a renderer.
  11995 + * * `null` - use the original data source for the row rather than plucking
  11996 + * data directly from it. This action has effects on two other
  11997 + * initialisation options:
  11998 + * * `defaultContent` - When null is given as the `data` option and
  11999 + * `defaultContent` is specified for the column, the value defined by
  12000 + * `defaultContent` will be used for the cell.
  12001 + * * `render` - When null is used for the `data` option and the `render`
  12002 + * option is specified for the column, the whole data source for the
  12003 + * row is used for the renderer.
  12004 + * * `function` - the function given will be executed whenever DataTables
  12005 + * needs to set or get the data for a cell in the column. The function
  12006 + * takes three parameters:
  12007 + * * Parameters:
  12008 + * * `{array|object}` The data source for the row
  12009 + * * `{string}` The type call data requested - this will be 'set' when
  12010 + * setting data or 'filter', 'display', 'type', 'sort' or undefined
  12011 + * when gathering data. Note that when `undefined` is given for the
  12012 + * type DataTables expects to get the raw data for the object back<
  12013 + * * `{*}` Data to set when the second parameter is 'set'.
  12014 + * * Return:
  12015 + * * The return value from the function is not required when 'set' is
  12016 + * the type of call, but otherwise the return is what will be used
  12017 + * for the data requested.
  12018 + *
  12019 + * Note that `data` is a getter and setter option. If you just require
  12020 + * formatting of data for output, you will likely want to use `render` which
  12021 + * is simply a getter and thus simpler to use.
  12022 + *
  12023 + * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
  12024 + * name change reflects the flexibility of this property and is consistent
  12025 + * with the naming of mRender. If 'mDataProp' is given, then it will still
  12026 + * be used by DataTables, as it automatically maps the old name to the new
  12027 + * if required.
  12028 + *
  12029 + * @type string|int|function|null
  12030 + * @default null <i>Use automatically calculated column index</i>
  12031 + *
  12032 + * @name DataTable.defaults.column.data
  12033 + * @dtopt Columns
  12034 + *
  12035 + * @example
  12036 + * // Read table data from objects
  12037 + * // JSON structure for each row:
  12038 + * // {
  12039 + * // "engine": {value},
  12040 + * // "browser": {value},
  12041 + * // "platform": {value},
  12042 + * // "version": {value},
  12043 + * // "grade": {value}
  12044 + * // }
  12045 + * $(document).ready( function() {
  12046 + * $('#example').dataTable( {
  12047 + * "ajaxSource": "sources/objects.txt",
  12048 + * "columns": [
  12049 + * { "data": "engine" },
  12050 + * { "data": "browser" },
  12051 + * { "data": "platform" },
  12052 + * { "data": "version" },
  12053 + * { "data": "grade" }
  12054 + * ]
  12055 + * } );
  12056 + * } );
  12057 + *
  12058 + * @example
  12059 + * // Read information from deeply nested objects
  12060 + * // JSON structure for each row:
  12061 + * // {
  12062 + * // "engine": {value},
  12063 + * // "browser": {value},
  12064 + * // "platform": {
  12065 + * // "inner": {value}
  12066 + * // },
  12067 + * // "details": [
  12068 + * // {value}, {value}
  12069 + * // ]
  12070 + * // }
  12071 + * $(document).ready( function() {
  12072 + * $('#example').dataTable( {
  12073 + * "ajaxSource": "sources/deep.txt",
  12074 + * "columns": [
  12075 + * { "data": "engine" },
  12076 + * { "data": "browser" },
  12077 + * { "data": "platform.inner" },
  12078 + * { "data": "platform.details.0" },
  12079 + * { "data": "platform.details.1" }
  12080 + * ]
  12081 + * } );
  12082 + * } );
  12083 + *
  12084 + * @example
  12085 + * // Using `data` as a function to provide different information for
  12086 + * // sorting, filtering and display. In this case, currency (price)
  12087 + * $(document).ready( function() {
  12088 + * $('#example').dataTable( {
  12089 + * "columnDefs": [ {
  12090 + * "targets": [ 0 ],
  12091 + * "data": function ( source, type, val ) {
  12092 + * if (type === 'set') {
  12093 + * source.price = val;
  12094 + * // Store the computed dislay and filter values for efficiency
  12095 + * source.price_display = val=="" ? "" : "$"+numberFormat(val);
  12096 + * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
  12097 + * return;
  12098 + * }
  12099 + * else if (type === 'display') {
  12100 + * return source.price_display;
  12101 + * }
  12102 + * else if (type === 'filter') {
  12103 + * return source.price_filter;
  12104 + * }
  12105 + * // 'sort', 'type' and undefined all just use the integer
  12106 + * return source.price;
  12107 + * }
  12108 + * } ]
  12109 + * } );
  12110 + * } );
  12111 + *
  12112 + * @example
  12113 + * // Using default content
  12114 + * $(document).ready( function() {
  12115 + * $('#example').dataTable( {
  12116 + * "columnDefs": [ {
  12117 + * "targets": [ 0 ],
  12118 + * "data": null,
  12119 + * "defaultContent": "Click to edit"
  12120 + * } ]
  12121 + * } );
  12122 + * } );
  12123 + *
  12124 + * @example
  12125 + * // Using array notation - outputting a list from an array
  12126 + * $(document).ready( function() {
  12127 + * $('#example').dataTable( {
  12128 + * "columnDefs": [ {
  12129 + * "targets": [ 0 ],
  12130 + * "data": "name[, ]"
  12131 + * } ]
  12132 + * } );
  12133 + * } );
  12134 + *
  12135 + */
  12136 + "mData": null,
  12137 +
  12138 +
  12139 + /**
  12140 + * This property is the rendering partner to `data` and it is suggested that
  12141 + * when you want to manipulate data for display (including filtering,
  12142 + * sorting etc) without altering the underlying data for the table, use this
  12143 + * property. `render` can be considered to be the the read only companion to
  12144 + * `data` which is read / write (then as such more complex). Like `data`
  12145 + * this option can be given in a number of different ways to effect its
  12146 + * behaviour:
  12147 + *
  12148 + * * `integer` - treated as an array index for the data source. This is the
  12149 + * default that DataTables uses (incrementally increased for each column).
  12150 + * * `string` - read an object property from the data source. There are
  12151 + * three 'special' options that can be used in the string to alter how
  12152 + * DataTables reads the data from the source object:
  12153 + * * `.` - Dotted Javascript notation. Just as you use a `.` in
  12154 + * Javascript to read from nested objects, so to can the options
  12155 + * specified in `data`. For example: `browser.version` or
  12156 + * `browser.name`. If your object parameter name contains a period, use
  12157 + * `\\` to escape it - i.e. `first\\.name`.
  12158 + * * `[]` - Array notation. DataTables can automatically combine data
  12159 + * from and array source, joining the data with the characters provided
  12160 + * between the two brackets. For example: `name[, ]` would provide a
  12161 + * comma-space separated list from the source array. If no characters
  12162 + * are provided between the brackets, the original array source is
  12163 + * returned.
  12164 + * * `()` - Function notation. Adding `()` to the end of a parameter will
  12165 + * execute a function of the name given. For example: `browser()` for a
  12166 + * simple function on the data source, `browser.version()` for a
  12167 + * function in a nested property or even `browser().version` to get an
  12168 + * object property if the function called returns an object.
  12169 + * * `object` - use different data for the different data types requested by
  12170 + * DataTables ('filter', 'display', 'type' or 'sort'). The property names
  12171 + * of the object is the data type the property refers to and the value can
  12172 + * defined using an integer, string or function using the same rules as
  12173 + * `render` normally does. Note that an `_` option _must_ be specified.
  12174 + * This is the default value to use if you haven't specified a value for
  12175 + * the data type requested by DataTables.
  12176 + * * `function` - the function given will be executed whenever DataTables
  12177 + * needs to set or get the data for a cell in the column. The function
  12178 + * takes three parameters:
  12179 + * * Parameters:
  12180 + * * {array|object} The data source for the row (based on `data`)
  12181 + * * {string} The type call data requested - this will be 'filter',
  12182 + * 'display', 'type' or 'sort'.
  12183 + * * {array|object} The full data source for the row (not based on
  12184 + * `data`)
  12185 + * * Return:
  12186 + * * The return value from the function is what will be used for the
  12187 + * data requested.
  12188 + *
  12189 + * @type string|int|function|object|null
  12190 + * @default null Use the data source value.
  12191 + *
  12192 + * @name DataTable.defaults.column.render
  12193 + * @dtopt Columns
  12194 + *
  12195 + * @example
  12196 + * // Create a comma separated list from an array of objects
  12197 + * $(document).ready( function() {
  12198 + * $('#example').dataTable( {
  12199 + * "ajaxSource": "sources/deep.txt",
  12200 + * "columns": [
  12201 + * { "data": "engine" },
  12202 + * { "data": "browser" },
  12203 + * {
  12204 + * "data": "platform",
  12205 + * "render": "[, ].name"
  12206 + * }
  12207 + * ]
  12208 + * } );
  12209 + * } );
  12210 + *
  12211 + * @example
  12212 + * // Execute a function to obtain data
  12213 + * $(document).ready( function() {
  12214 + * $('#example').dataTable( {
  12215 + * "columnDefs": [ {
  12216 + * "targets": [ 0 ],
  12217 + * "data": null, // Use the full data source object for the renderer's source
  12218 + * "render": "browserName()"
  12219 + * } ]
  12220 + * } );
  12221 + * } );
  12222 + *
  12223 + * @example
  12224 + * // As an object, extracting different data for the different types
  12225 + * // This would be used with a data source such as:
  12226 + * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
  12227 + * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
  12228 + * // (which has both forms) is used for filtering for if a user inputs either format, while
  12229 + * // the formatted phone number is the one that is shown in the table.
  12230 + * $(document).ready( function() {
  12231 + * $('#example').dataTable( {
  12232 + * "columnDefs": [ {
  12233 + * "targets": [ 0 ],
  12234 + * "data": null, // Use the full data source object for the renderer's source
  12235 + * "render": {
  12236 + * "_": "phone",
  12237 + * "filter": "phone_filter",
  12238 + * "display": "phone_display"
  12239 + * }
  12240 + * } ]
  12241 + * } );
  12242 + * } );
  12243 + *
  12244 + * @example
  12245 + * // Use as a function to create a link from the data source
  12246 + * $(document).ready( function() {
  12247 + * $('#example').dataTable( {
  12248 + * "columnDefs": [ {
  12249 + * "targets": [ 0 ],
  12250 + * "data": "download_link",
  12251 + * "render": function ( data, type, full ) {
  12252 + * return '<a href="'+data+'">Download</a>';
  12253 + * }
  12254 + * } ]
  12255 + * } );
  12256 + * } );
  12257 + */
  12258 + "mRender": null,
  12259 +
  12260 +
  12261 + /**
  12262 + * Change the cell type created for the column - either TD cells or TH cells. This
  12263 + * can be useful as TH cells have semantic meaning in the table body, allowing them
  12264 + * to act as a header for a row (you may wish to add scope='row' to the TH elements).
  12265 + * @type string
  12266 + * @default td
  12267 + *
  12268 + * @name DataTable.defaults.column.cellType
  12269 + * @dtopt Columns
  12270 + *
  12271 + * @example
  12272 + * // Make the first column use TH cells
  12273 + * $(document).ready( function() {
  12274 + * $('#example').dataTable( {
  12275 + * "columnDefs": [ {
  12276 + * "targets": [ 0 ],
  12277 + * "cellType": "th"
  12278 + * } ]
  12279 + * } );
  12280 + * } );
  12281 + */
  12282 + "sCellType": "td",
  12283 +
  12284 +
  12285 + /**
  12286 + * Class to give to each cell in this column.
  12287 + * @type string
  12288 + * @default <i>Empty string</i>
  12289 + *
  12290 + * @name DataTable.defaults.column.class
  12291 + * @dtopt Columns
  12292 + *
  12293 + * @example
  12294 + * // Using `columnDefs`
  12295 + * $(document).ready( function() {
  12296 + * $('#example').dataTable( {
  12297 + * "columnDefs": [
  12298 + * { "class": "my_class", "targets": [ 0 ] }
  12299 + * ]
  12300 + * } );
  12301 + * } );
  12302 + *
  12303 + * @example
  12304 + * // Using `columns`
  12305 + * $(document).ready( function() {
  12306 + * $('#example').dataTable( {
  12307 + * "columns": [
  12308 + * { "class": "my_class" },
  12309 + * null,
  12310 + * null,
  12311 + * null,
  12312 + * null
  12313 + * ]
  12314 + * } );
  12315 + * } );
  12316 + */
  12317 + "sClass": "",
  12318 +
  12319 + /**
  12320 + * When DataTables calculates the column widths to assign to each column,
  12321 + * it finds the longest string in each column and then constructs a
  12322 + * temporary table and reads the widths from that. The problem with this
  12323 + * is that "mmm" is much wider then "iiii", but the latter is a longer
  12324 + * string - thus the calculation can go wrong (doing it properly and putting
  12325 + * it into an DOM object and measuring that is horribly(!) slow). Thus as
  12326 + * a "work around" we provide this option. It will append its value to the
  12327 + * text that is found to be the longest string for the column - i.e. padding.
  12328 + * Generally you shouldn't need this!
  12329 + * @type string
  12330 + * @default <i>Empty string<i>
  12331 + *
  12332 + * @name DataTable.defaults.column.contentPadding
  12333 + * @dtopt Columns
  12334 + *
  12335 + * @example
  12336 + * // Using `columns`
  12337 + * $(document).ready( function() {
  12338 + * $('#example').dataTable( {
  12339 + * "columns": [
  12340 + * null,
  12341 + * null,
  12342 + * null,
  12343 + * {
  12344 + * "contentPadding": "mmm"
  12345 + * }
  12346 + * ]
  12347 + * } );
  12348 + * } );
  12349 + */
  12350 + "sContentPadding": "",
  12351 +
  12352 +
  12353 + /**
  12354 + * Allows a default value to be given for a column's data, and will be used
  12355 + * whenever a null data source is encountered (this can be because `data`
  12356 + * is set to null, or because the data source itself is null).
  12357 + * @type string
  12358 + * @default null
  12359 + *
  12360 + * @name DataTable.defaults.column.defaultContent
  12361 + * @dtopt Columns
  12362 + *
  12363 + * @example
  12364 + * // Using `columnDefs`
  12365 + * $(document).ready( function() {
  12366 + * $('#example').dataTable( {
  12367 + * "columnDefs": [
  12368 + * {
  12369 + * "data": null,
  12370 + * "defaultContent": "Edit",
  12371 + * "targets": [ -1 ]
  12372 + * }
  12373 + * ]
  12374 + * } );
  12375 + * } );
  12376 + *
  12377 + * @example
  12378 + * // Using `columns`
  12379 + * $(document).ready( function() {
  12380 + * $('#example').dataTable( {
  12381 + * "columns": [
  12382 + * null,
  12383 + * null,
  12384 + * null,
  12385 + * {
  12386 + * "data": null,
  12387 + * "defaultContent": "Edit"
  12388 + * }
  12389 + * ]
  12390 + * } );
  12391 + * } );
  12392 + */
  12393 + "sDefaultContent": null,
  12394 +
  12395 +
  12396 + /**
  12397 + * This parameter is only used in DataTables' server-side processing. It can
  12398 + * be exceptionally useful to know what columns are being displayed on the
  12399 + * client side, and to map these to database fields. When defined, the names
  12400 + * also allow DataTables to reorder information from the server if it comes
  12401 + * back in an unexpected order (i.e. if you switch your columns around on the
  12402 + * client-side, your server-side code does not also need updating).
  12403 + * @type string
  12404 + * @default <i>Empty string</i>
  12405 + *
  12406 + * @name DataTable.defaults.column.name
  12407 + * @dtopt Columns
  12408 + *
  12409 + * @example
  12410 + * // Using `columnDefs`
  12411 + * $(document).ready( function() {
  12412 + * $('#example').dataTable( {
  12413 + * "columnDefs": [
  12414 + * { "name": "engine", "targets": [ 0 ] },
  12415 + * { "name": "browser", "targets": [ 1 ] },
  12416 + * { "name": "platform", "targets": [ 2 ] },
  12417 + * { "name": "version", "targets": [ 3 ] },
  12418 + * { "name": "grade", "targets": [ 4 ] }
  12419 + * ]
  12420 + * } );
  12421 + * } );
  12422 + *
  12423 + * @example
  12424 + * // Using `columns`
  12425 + * $(document).ready( function() {
  12426 + * $('#example').dataTable( {
  12427 + * "columns": [
  12428 + * { "name": "engine" },
  12429 + * { "name": "browser" },
  12430 + * { "name": "platform" },
  12431 + * { "name": "version" },
  12432 + * { "name": "grade" }
  12433 + * ]
  12434 + * } );
  12435 + * } );
  12436 + */
  12437 + "sName": "",
  12438 +
  12439 +
  12440 + /**
  12441 + * Defines a data source type for the ordering which can be used to read
  12442 + * real-time information from the table (updating the internally cached
  12443 + * version) prior to ordering. This allows ordering to occur on user
  12444 + * editable elements such as form inputs.
  12445 + * @type string
  12446 + * @default std
  12447 + *
  12448 + * @name DataTable.defaults.column.orderDataType
  12449 + * @dtopt Columns
  12450 + *
  12451 + * @example
  12452 + * // Using `columnDefs`
  12453 + * $(document).ready( function() {
  12454 + * $('#example').dataTable( {
  12455 + * "columnDefs": [
  12456 + * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
  12457 + * { "type": "numeric", "targets": [ 3 ] },
  12458 + * { "orderDataType": "dom-select", "targets": [ 4 ] },
  12459 + * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
  12460 + * ]
  12461 + * } );
  12462 + * } );
  12463 + *
  12464 + * @example
  12465 + * // Using `columns`
  12466 + * $(document).ready( function() {
  12467 + * $('#example').dataTable( {
  12468 + * "columns": [
  12469 + * null,
  12470 + * null,
  12471 + * { "orderDataType": "dom-text" },
  12472 + * { "orderDataType": "dom-text", "type": "numeric" },
  12473 + * { "orderDataType": "dom-select" },
  12474 + * { "orderDataType": "dom-checkbox" }
  12475 + * ]
  12476 + * } );
  12477 + * } );
  12478 + */
  12479 + "sSortDataType": "std",
  12480 +
  12481 +
  12482 + /**
  12483 + * The title of this column.
  12484 + * @type string
  12485 + * @default null <i>Derived from the 'TH' value for this column in the
  12486 + * original HTML table.</i>
  12487 + *
  12488 + * @name DataTable.defaults.column.title
  12489 + * @dtopt Columns
  12490 + *
  12491 + * @example
  12492 + * // Using `columnDefs`
  12493 + * $(document).ready( function() {
  12494 + * $('#example').dataTable( {
  12495 + * "columnDefs": [
  12496 + * { "title": "My column title", "targets": [ 0 ] }
  12497 + * ]
  12498 + * } );
  12499 + * } );
  12500 + *
  12501 + * @example
  12502 + * // Using `columns`
  12503 + * $(document).ready( function() {
  12504 + * $('#example').dataTable( {
  12505 + * "columns": [
  12506 + * { "title": "My column title" },
  12507 + * null,
  12508 + * null,
  12509 + * null,
  12510 + * null
  12511 + * ]
  12512 + * } );
  12513 + * } );
  12514 + */
  12515 + "sTitle": null,
  12516 +
  12517 +
  12518 + /**
  12519 + * The type allows you to specify how the data for this column will be
  12520 + * ordered. Four types (string, numeric, date and html (which will strip
  12521 + * HTML tags before ordering)) are currently available. Note that only date
  12522 + * formats understood by Javascript's Date() object will be accepted as type
  12523 + * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
  12524 + * 'numeric', 'date' or 'html' (by default). Further types can be adding
  12525 + * through plug-ins.
  12526 + * @type string
  12527 + * @default null <i>Auto-detected from raw data</i>
  12528 + *
  12529 + * @name DataTable.defaults.column.type
  12530 + * @dtopt Columns
  12531 + *
  12532 + * @example
  12533 + * // Using `columnDefs`
  12534 + * $(document).ready( function() {
  12535 + * $('#example').dataTable( {
  12536 + * "columnDefs": [
  12537 + * { "type": "html", "targets": [ 0 ] }
  12538 + * ]
  12539 + * } );
  12540 + * } );
  12541 + *
  12542 + * @example
  12543 + * // Using `columns`
  12544 + * $(document).ready( function() {
  12545 + * $('#example').dataTable( {
  12546 + * "columns": [
  12547 + * { "type": "html" },
  12548 + * null,
  12549 + * null,
  12550 + * null,
  12551 + * null
  12552 + * ]
  12553 + * } );
  12554 + * } );
  12555 + */
  12556 + "sType": null,
  12557 +
  12558 +
  12559 + /**
  12560 + * Defining the width of the column, this parameter may take any CSS value
  12561 + * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
  12562 + * been given a specific width through this interface ensuring that the table
  12563 + * remains readable.
  12564 + * @type string
  12565 + * @default null <i>Automatic</i>
  12566 + *
  12567 + * @name DataTable.defaults.column.width
  12568 + * @dtopt Columns
  12569 + *
  12570 + * @example
  12571 + * // Using `columnDefs`
  12572 + * $(document).ready( function() {
  12573 + * $('#example').dataTable( {
  12574 + * "columnDefs": [
  12575 + * { "width": "20%", "targets": [ 0 ] }
  12576 + * ]
  12577 + * } );
  12578 + * } );
  12579 + *
  12580 + * @example
  12581 + * // Using `columns`
  12582 + * $(document).ready( function() {
  12583 + * $('#example').dataTable( {
  12584 + * "columns": [
  12585 + * { "width": "20%" },
  12586 + * null,
  12587 + * null,
  12588 + * null,
  12589 + * null
  12590 + * ]
  12591 + * } );
  12592 + * } );
  12593 + */
  12594 + "sWidth": null
  12595 + };
  12596 +
  12597 + _fnHungarianMap( DataTable.defaults.column );
  12598 +
  12599 +
  12600 +
  12601 + /**
  12602 + * DataTables settings object - this holds all the information needed for a
  12603 + * given table, including configuration, data and current application of the
  12604 + * table options. DataTables does not have a single instance for each DataTable
  12605 + * with the settings attached to that instance, but rather instances of the
  12606 + * DataTable "class" are created on-the-fly as needed (typically by a
  12607 + * $().dataTable() call) and the settings object is then applied to that
  12608 + * instance.
  12609 + *
  12610 + * Note that this object is related to {@link DataTable.defaults} but this
  12611 + * one is the internal data store for DataTables's cache of columns. It should
  12612 + * NOT be manipulated outside of DataTables. Any configuration should be done
  12613 + * through the initialisation options.
  12614 + * @namespace
  12615 + * @todo Really should attach the settings object to individual instances so we
  12616 + * don't need to create new instances on each $().dataTable() call (if the
  12617 + * table already exists). It would also save passing oSettings around and
  12618 + * into every single function. However, this is a very significant
  12619 + * architecture change for DataTables and will almost certainly break
  12620 + * backwards compatibility with older installations. This is something that
  12621 + * will be done in 2.0.
  12622 + */
  12623 + DataTable.models.oSettings = {
  12624 + /**
  12625 + * Primary features of DataTables and their enablement state.
  12626 + * @namespace
  12627 + */
  12628 + "oFeatures": {
  12629 +
  12630 + /**
  12631 + * Flag to say if DataTables should automatically try to calculate the
  12632 + * optimum table and columns widths (true) or not (false).
  12633 + * Note that this parameter will be set by the initialisation routine. To
  12634 + * set a default use {@link DataTable.defaults}.
  12635 + * @type boolean
  12636 + */
  12637 + "bAutoWidth": null,
  12638 +
  12639 + /**
  12640 + * Delay the creation of TR and TD elements until they are actually
  12641 + * needed by a driven page draw. This can give a significant speed
  12642 + * increase for Ajax source and Javascript source data, but makes no
  12643 + * difference at all fro DOM and server-side processing tables.
  12644 + * Note that this parameter will be set by the initialisation routine. To
  12645 + * set a default use {@link DataTable.defaults}.
  12646 + * @type boolean
  12647 + */
  12648 + "bDeferRender": null,
  12649 +
  12650 + /**
  12651 + * Enable filtering on the table or not. Note that if this is disabled
  12652 + * then there is no filtering at all on the table, including fnFilter.
  12653 + * To just remove the filtering input use sDom and remove the 'f' option.
  12654 + * Note that this parameter will be set by the initialisation routine. To
  12655 + * set a default use {@link DataTable.defaults}.
  12656 + * @type boolean
  12657 + */
  12658 + "bFilter": null,
  12659 +
  12660 + /**
  12661 + * Table information element (the 'Showing x of y records' div) enable
  12662 + * flag.
  12663 + * Note that this parameter will be set by the initialisation routine. To
  12664 + * set a default use {@link DataTable.defaults}.
  12665 + * @type boolean
  12666 + */
  12667 + "bInfo": null,
  12668 +
  12669 + /**
  12670 + * Present a user control allowing the end user to change the page size
  12671 + * when pagination is enabled.
  12672 + * Note that this parameter will be set by the initialisation routine. To
  12673 + * set a default use {@link DataTable.defaults}.
  12674 + * @type boolean
  12675 + */
  12676 + "bLengthChange": null,
  12677 +
  12678 + /**
  12679 + * Pagination enabled or not. Note that if this is disabled then length
  12680 + * changing must also be disabled.
  12681 + * Note that this parameter will be set by the initialisation routine. To
  12682 + * set a default use {@link DataTable.defaults}.
  12683 + * @type boolean
  12684 + */
  12685 + "bPaginate": null,
  12686 +
  12687 + /**
  12688 + * Processing indicator enable flag whenever DataTables is enacting a
  12689 + * user request - typically an Ajax request for server-side processing.
  12690 + * Note that this parameter will be set by the initialisation routine. To
  12691 + * set a default use {@link DataTable.defaults}.
  12692 + * @type boolean
  12693 + */
  12694 + "bProcessing": null,
  12695 +
  12696 + /**
  12697 + * Server-side processing enabled flag - when enabled DataTables will
  12698 + * get all data from the server for every draw - there is no filtering,
  12699 + * sorting or paging done on the client-side.
  12700 + * Note that this parameter will be set by the initialisation routine. To
  12701 + * set a default use {@link DataTable.defaults}.
  12702 + * @type boolean
  12703 + */
  12704 + "bServerSide": null,
  12705 +
  12706 + /**
  12707 + * Sorting enablement flag.
  12708 + * Note that this parameter will be set by the initialisation routine. To
  12709 + * set a default use {@link DataTable.defaults}.
  12710 + * @type boolean
  12711 + */
  12712 + "bSort": null,
  12713 +
  12714 + /**
  12715 + * Multi-column sorting
  12716 + * Note that this parameter will be set by the initialisation routine. To
  12717 + * set a default use {@link DataTable.defaults}.
  12718 + * @type boolean
  12719 + */
  12720 + "bSortMulti": null,
  12721 +
  12722 + /**
  12723 + * Apply a class to the columns which are being sorted to provide a
  12724 + * visual highlight or not. This can slow things down when enabled since
  12725 + * there is a lot of DOM interaction.
  12726 + * Note that this parameter will be set by the initialisation routine. To
  12727 + * set a default use {@link DataTable.defaults}.
  12728 + * @type boolean
  12729 + */
  12730 + "bSortClasses": null,
  12731 +
  12732 + /**
  12733 + * State saving enablement flag.
  12734 + * Note that this parameter will be set by the initialisation routine. To
  12735 + * set a default use {@link DataTable.defaults}.
  12736 + * @type boolean
  12737 + */
  12738 + "bStateSave": null
  12739 + },
  12740 +
  12741 +
  12742 + /**
  12743 + * Scrolling settings for a table.
  12744 + * @namespace
  12745 + */
  12746 + "oScroll": {
  12747 + /**
  12748 + * When the table is shorter in height than sScrollY, collapse the
  12749 + * table container down to the height of the table (when true).
  12750 + * Note that this parameter will be set by the initialisation routine. To
  12751 + * set a default use {@link DataTable.defaults}.
  12752 + * @type boolean
  12753 + */
  12754 + "bCollapse": null,
  12755 +
  12756 + /**
  12757 + * Width of the scrollbar for the web-browser's platform. Calculated
  12758 + * during table initialisation.
  12759 + * @type int
  12760 + * @default 0
  12761 + */
  12762 + "iBarWidth": 0,
  12763 +
  12764 + /**
  12765 + * Viewport width for horizontal scrolling. Horizontal scrolling is
  12766 + * disabled if an empty string.
  12767 + * Note that this parameter will be set by the initialisation routine. To
  12768 + * set a default use {@link DataTable.defaults}.
  12769 + * @type string
  12770 + */
  12771 + "sX": null,
  12772 +
  12773 + /**
  12774 + * Width to expand the table to when using x-scrolling. Typically you
  12775 + * should not need to use this.
  12776 + * Note that this parameter will be set by the initialisation routine. To
  12777 + * set a default use {@link DataTable.defaults}.
  12778 + * @type string
  12779 + * @deprecated
  12780 + */
  12781 + "sXInner": null,
  12782 +
  12783 + /**
  12784 + * Viewport height for vertical scrolling. Vertical scrolling is disabled
  12785 + * if an empty string.
  12786 + * Note that this parameter will be set by the initialisation routine. To
  12787 + * set a default use {@link DataTable.defaults}.
  12788 + * @type string
  12789 + */
  12790 + "sY": null
  12791 + },
  12792 +
  12793 + /**
  12794 + * Language information for the table.
  12795 + * @namespace
  12796 + * @extends DataTable.defaults.oLanguage
  12797 + */
  12798 + "oLanguage": {
  12799 + /**
  12800 + * Information callback function. See
  12801 + * {@link DataTable.defaults.fnInfoCallback}
  12802 + * @type function
  12803 + * @default null
  12804 + */
  12805 + "fnInfoCallback": null
  12806 + },
  12807 +
  12808 + /**
  12809 + * Browser support parameters
  12810 + * @namespace
  12811 + */
  12812 + "oBrowser": {
  12813 + /**
  12814 + * Indicate if the browser incorrectly calculates width:100% inside a
  12815 + * scrolling element (IE6/7)
  12816 + * @type boolean
  12817 + * @default false
  12818 + */
  12819 + "bScrollOversize": false,
  12820 +
  12821 + /**
  12822 + * Determine if the vertical scrollbar is on the right or left of the
  12823 + * scrolling container - needed for rtl language layout, although not
  12824 + * all browsers move the scrollbar (Safari).
  12825 + * @type boolean
  12826 + * @default false
  12827 + */
  12828 + "bScrollbarLeft": false
  12829 + },
  12830 +
  12831 +
  12832 + "ajax": null,
  12833 +
  12834 +
  12835 + /**
  12836 + * Array referencing the nodes which are used for the features. The
  12837 + * parameters of this object match what is allowed by sDom - i.e.
  12838 + * <ul>
  12839 + * <li>'l' - Length changing</li>
  12840 + * <li>'f' - Filtering input</li>
  12841 + * <li>'t' - The table!</li>
  12842 + * <li>'i' - Information</li>
  12843 + * <li>'p' - Pagination</li>
  12844 + * <li>'r' - pRocessing</li>
  12845 + * </ul>
  12846 + * @type array
  12847 + * @default []
  12848 + */
  12849 + "aanFeatures": [],
  12850 +
  12851 + /**
  12852 + * Store data information - see {@link DataTable.models.oRow} for detailed
  12853 + * information.
  12854 + * @type array
  12855 + * @default []
  12856 + */
  12857 + "aoData": [],
  12858 +
  12859 + /**
  12860 + * Array of indexes which are in the current display (after filtering etc)
  12861 + * @type array
  12862 + * @default []
  12863 + */
  12864 + "aiDisplay": [],
  12865 +
  12866 + /**
  12867 + * Array of indexes for display - no filtering
  12868 + * @type array
  12869 + * @default []
  12870 + */
  12871 + "aiDisplayMaster": [],
  12872 +
  12873 + /**
  12874 + * Store information about each column that is in use
  12875 + * @type array
  12876 + * @default []
  12877 + */
  12878 + "aoColumns": [],
  12879 +
  12880 + /**
  12881 + * Store information about the table's header
  12882 + * @type array
  12883 + * @default []
  12884 + */
  12885 + "aoHeader": [],
  12886 +
  12887 + /**
  12888 + * Store information about the table's footer
  12889 + * @type array
  12890 + * @default []
  12891 + */
  12892 + "aoFooter": [],
  12893 +
  12894 + /**
  12895 + * Store the applied global search information in case we want to force a
  12896 + * research or compare the old search to a new one.
  12897 + * Note that this parameter will be set by the initialisation routine. To
  12898 + * set a default use {@link DataTable.defaults}.
  12899 + * @namespace
  12900 + * @extends DataTable.models.oSearch
  12901 + */
  12902 + "oPreviousSearch": {},
  12903 +
  12904 + /**
  12905 + * Store the applied search for each column - see
  12906 + * {@link DataTable.models.oSearch} for the format that is used for the
  12907 + * filtering information for each column.
  12908 + * @type array
  12909 + * @default []
  12910 + */
  12911 + "aoPreSearchCols": [],
  12912 +
  12913 + /**
  12914 + * Sorting that is applied to the table. Note that the inner arrays are
  12915 + * used in the following manner:
  12916 + * <ul>
  12917 + * <li>Index 0 - column number</li>
  12918 + * <li>Index 1 - current sorting direction</li>
  12919 + * </ul>
  12920 + * Note that this parameter will be set by the initialisation routine. To
  12921 + * set a default use {@link DataTable.defaults}.
  12922 + * @type array
  12923 + * @todo These inner arrays should really be objects
  12924 + */
  12925 + "aaSorting": null,
  12926 +
  12927 + /**
  12928 + * Sorting that is always applied to the table (i.e. prefixed in front of
  12929 + * aaSorting).
  12930 + * Note that this parameter will be set by the initialisation routine. To
  12931 + * set a default use {@link DataTable.defaults}.
  12932 + * @type array
  12933 + * @default []
  12934 + */
  12935 + "aaSortingFixed": [],
  12936 +
  12937 + /**
  12938 + * Classes to use for the striping of a table.
  12939 + * Note that this parameter will be set by the initialisation routine. To
  12940 + * set a default use {@link DataTable.defaults}.
  12941 + * @type array
  12942 + * @default []
  12943 + */
  12944 + "asStripeClasses": null,
  12945 +
  12946 + /**
  12947 + * If restoring a table - we should restore its striping classes as well
  12948 + * @type array
  12949 + * @default []
  12950 + */
  12951 + "asDestroyStripes": [],
  12952 +
  12953 + /**
  12954 + * If restoring a table - we should restore its width
  12955 + * @type int
  12956 + * @default 0
  12957 + */
  12958 + "sDestroyWidth": 0,
  12959 +
  12960 + /**
  12961 + * Callback functions array for every time a row is inserted (i.e. on a draw).
  12962 + * @type array
  12963 + * @default []
  12964 + */
  12965 + "aoRowCallback": [],
  12966 +
  12967 + /**
  12968 + * Callback functions for the header on each draw.
  12969 + * @type array
  12970 + * @default []
  12971 + */
  12972 + "aoHeaderCallback": [],
  12973 +
  12974 + /**
  12975 + * Callback function for the footer on each draw.
  12976 + * @type array
  12977 + * @default []
  12978 + */
  12979 + "aoFooterCallback": [],
  12980 +
  12981 + /**
  12982 + * Array of callback functions for draw callback functions
  12983 + * @type array
  12984 + * @default []
  12985 + */
  12986 + "aoDrawCallback": [],
  12987 +
  12988 + /**
  12989 + * Array of callback functions for row created function
  12990 + * @type array
  12991 + * @default []
  12992 + */
  12993 + "aoRowCreatedCallback": [],
  12994 +
  12995 + /**
  12996 + * Callback functions for just before the table is redrawn. A return of
  12997 + * false will be used to cancel the draw.
  12998 + * @type array
  12999 + * @default []
  13000 + */
  13001 + "aoPreDrawCallback": [],
  13002 +
  13003 + /**
  13004 + * Callback functions for when the table has been initialised.
  13005 + * @type array
  13006 + * @default []
  13007 + */
  13008 + "aoInitComplete": [],
  13009 +
  13010 +
  13011 + /**
  13012 + * Callbacks for modifying the settings to be stored for state saving, prior to
  13013 + * saving state.
  13014 + * @type array
  13015 + * @default []
  13016 + */
  13017 + "aoStateSaveParams": [],
  13018 +
  13019 + /**
  13020 + * Callbacks for modifying the settings that have been stored for state saving
  13021 + * prior to using the stored values to restore the state.
  13022 + * @type array
  13023 + * @default []
  13024 + */
  13025 + "aoStateLoadParams": [],
  13026 +
  13027 + /**
  13028 + * Callbacks for operating on the settings object once the saved state has been
  13029 + * loaded
  13030 + * @type array
  13031 + * @default []
  13032 + */
  13033 + "aoStateLoaded": [],
  13034 +
  13035 + /**
  13036 + * Cache the table ID for quick access
  13037 + * @type string
  13038 + * @default <i>Empty string</i>
  13039 + */
  13040 + "sTableId": "",
  13041 +
  13042 + /**
  13043 + * The TABLE node for the main table
  13044 + * @type node
  13045 + * @default null
  13046 + */
  13047 + "nTable": null,
  13048 +
  13049 + /**
  13050 + * Permanent ref to the thead element
  13051 + * @type node
  13052 + * @default null
  13053 + */
  13054 + "nTHead": null,
  13055 +
  13056 + /**
  13057 + * Permanent ref to the tfoot element - if it exists
  13058 + * @type node
  13059 + * @default null
  13060 + */
  13061 + "nTFoot": null,
  13062 +
  13063 + /**
  13064 + * Permanent ref to the tbody element
  13065 + * @type node
  13066 + * @default null
  13067 + */
  13068 + "nTBody": null,
  13069 +
  13070 + /**
  13071 + * Cache the wrapper node (contains all DataTables controlled elements)
  13072 + * @type node
  13073 + * @default null
  13074 + */
  13075 + "nTableWrapper": null,
  13076 +
  13077 + /**
  13078 + * Indicate if when using server-side processing the loading of data
  13079 + * should be deferred until the second draw.
  13080 + * Note that this parameter will be set by the initialisation routine. To
  13081 + * set a default use {@link DataTable.defaults}.
  13082 + * @type boolean
  13083 + * @default false
  13084 + */
  13085 + "bDeferLoading": false,
  13086 +
  13087 + /**
  13088 + * Indicate if all required information has been read in
  13089 + * @type boolean
  13090 + * @default false
  13091 + */
  13092 + "bInitialised": false,
  13093 +
  13094 + /**
  13095 + * Information about open rows. Each object in the array has the parameters
  13096 + * 'nTr' and 'nParent'
  13097 + * @type array
  13098 + * @default []
  13099 + */
  13100 + "aoOpenRows": [],
  13101 +
  13102 + /**
  13103 + * Dictate the positioning of DataTables' control elements - see
  13104 + * {@link DataTable.model.oInit.sDom}.
  13105 + * Note that this parameter will be set by the initialisation routine. To
  13106 + * set a default use {@link DataTable.defaults}.
  13107 + * @type string
  13108 + * @default null
  13109 + */
  13110 + "sDom": null,
  13111 +
  13112 + /**
  13113 + * Search delay (in mS)
  13114 + * @type integer
  13115 + * @default null
  13116 + */
  13117 + "searchDelay": null,
  13118 +
  13119 + /**
  13120 + * Which type of pagination should be used.
  13121 + * Note that this parameter will be set by the initialisation routine. To
  13122 + * set a default use {@link DataTable.defaults}.
  13123 + * @type string
  13124 + * @default two_button
  13125 + */
  13126 + "sPaginationType": "two_button",
  13127 +
  13128 + /**
  13129 + * The state duration (for `stateSave`) in seconds.
  13130 + * Note that this parameter will be set by the initialisation routine. To
  13131 + * set a default use {@link DataTable.defaults}.
  13132 + * @type int
  13133 + * @default 0
  13134 + */
  13135 + "iStateDuration": 0,
  13136 +
  13137 + /**
  13138 + * Array of callback functions for state saving. Each array element is an
  13139 + * object with the following parameters:
  13140 + * <ul>
  13141 + * <li>function:fn - function to call. Takes two parameters, oSettings
  13142 + * and the JSON string to save that has been thus far created. Returns
  13143 + * a JSON string to be inserted into a json object
  13144 + * (i.e. '"param": [ 0, 1, 2]')</li>
  13145 + * <li>string:sName - name of callback</li>
  13146 + * </ul>
  13147 + * @type array
  13148 + * @default []
  13149 + */
  13150 + "aoStateSave": [],
  13151 +
  13152 + /**
  13153 + * Array of callback functions for state loading. Each array element is an
  13154 + * object with the following parameters:
  13155 + * <ul>
  13156 + * <li>function:fn - function to call. Takes two parameters, oSettings
  13157 + * and the object stored. May return false to cancel state loading</li>
  13158 + * <li>string:sName - name of callback</li>
  13159 + * </ul>
  13160 + * @type array
  13161 + * @default []
  13162 + */
  13163 + "aoStateLoad": [],
  13164 +
  13165 + /**
  13166 + * State that was saved. Useful for back reference
  13167 + * @type object
  13168 + * @default null
  13169 + */
  13170 + "oSavedState": null,
  13171 +
  13172 + /**
  13173 + * State that was loaded. Useful for back reference
  13174 + * @type object
  13175 + * @default null
  13176 + */
  13177 + "oLoadedState": null,
  13178 +
  13179 + /**
  13180 + * Source url for AJAX data for the table.
  13181 + * Note that this parameter will be set by the initialisation routine. To
  13182 + * set a default use {@link DataTable.defaults}.
  13183 + * @type string
  13184 + * @default null
  13185 + */
  13186 + "sAjaxSource": null,
  13187 +
  13188 + /**
  13189 + * Property from a given object from which to read the table data from. This
  13190 + * can be an empty string (when not server-side processing), in which case
  13191 + * it is assumed an an array is given directly.
  13192 + * Note that this parameter will be set by the initialisation routine. To
  13193 + * set a default use {@link DataTable.defaults}.
  13194 + * @type string
  13195 + */
  13196 + "sAjaxDataProp": null,
  13197 +
  13198 + /**
  13199 + * Note if draw should be blocked while getting data
  13200 + * @type boolean
  13201 + * @default true
  13202 + */
  13203 + "bAjaxDataGet": true,
  13204 +
  13205 + /**
  13206 + * The last jQuery XHR object that was used for server-side data gathering.
  13207 + * This can be used for working with the XHR information in one of the
  13208 + * callbacks
  13209 + * @type object
  13210 + * @default null
  13211 + */
  13212 + "jqXHR": null,
  13213 +
  13214 + /**
  13215 + * JSON returned from the server in the last Ajax request
  13216 + * @type object
  13217 + * @default undefined
  13218 + */
  13219 + "json": undefined,
  13220 +
  13221 + /**
  13222 + * Data submitted as part of the last Ajax request
  13223 + * @type object
  13224 + * @default undefined
  13225 + */
  13226 + "oAjaxData": undefined,
  13227 +
  13228 + /**
  13229 + * Function to get the server-side data.
  13230 + * Note that this parameter will be set by the initialisation routine. To
  13231 + * set a default use {@link DataTable.defaults}.
  13232 + * @type function
  13233 + */
  13234 + "fnServerData": null,
  13235 +
  13236 + /**
  13237 + * Functions which are called prior to sending an Ajax request so extra
  13238 + * parameters can easily be sent to the server
  13239 + * @type array
  13240 + * @default []
  13241 + */
  13242 + "aoServerParams": [],
  13243 +
  13244 + /**
  13245 + * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
  13246 + * required).
  13247 + * Note that this parameter will be set by the initialisation routine. To
  13248 + * set a default use {@link DataTable.defaults}.
  13249 + * @type string
  13250 + */
  13251 + "sServerMethod": null,
  13252 +
  13253 + /**
  13254 + * Format numbers for display.
  13255 + * Note that this parameter will be set by the initialisation routine. To
  13256 + * set a default use {@link DataTable.defaults}.
  13257 + * @type function
  13258 + */
  13259 + "fnFormatNumber": null,
  13260 +
  13261 + /**
  13262 + * List of options that can be used for the user selectable length menu.
  13263 + * Note that this parameter will be set by the initialisation routine. To
  13264 + * set a default use {@link DataTable.defaults}.
  13265 + * @type array
  13266 + * @default []
  13267 + */
  13268 + "aLengthMenu": null,
  13269 +
  13270 + /**
  13271 + * Counter for the draws that the table does. Also used as a tracker for
  13272 + * server-side processing
  13273 + * @type int
  13274 + * @default 0
  13275 + */
  13276 + "iDraw": 0,
  13277 +
  13278 + /**
  13279 + * Indicate if a redraw is being done - useful for Ajax
  13280 + * @type boolean
  13281 + * @default false
  13282 + */
  13283 + "bDrawing": false,
  13284 +
  13285 + /**
  13286 + * Draw index (iDraw) of the last error when parsing the returned data
  13287 + * @type int
  13288 + * @default -1
  13289 + */
  13290 + "iDrawError": -1,
  13291 +
  13292 + /**
  13293 + * Paging display length
  13294 + * @type int
  13295 + * @default 10
  13296 + */
  13297 + "_iDisplayLength": 10,
  13298 +
  13299 + /**
  13300 + * Paging start point - aiDisplay index
  13301 + * @type int
  13302 + * @default 0
  13303 + */
  13304 + "_iDisplayStart": 0,
  13305 +
  13306 + /**
  13307 + * Server-side processing - number of records in the result set
  13308 + * (i.e. before filtering), Use fnRecordsTotal rather than
  13309 + * this property to get the value of the number of records, regardless of
  13310 + * the server-side processing setting.
  13311 + * @type int
  13312 + * @default 0
  13313 + * @private
  13314 + */
  13315 + "_iRecordsTotal": 0,
  13316 +
  13317 + /**
  13318 + * Server-side processing - number of records in the current display set
  13319 + * (i.e. after filtering). Use fnRecordsDisplay rather than
  13320 + * this property to get the value of the number of records, regardless of
  13321 + * the server-side processing setting.
  13322 + * @type boolean
  13323 + * @default 0
  13324 + * @private
  13325 + */
  13326 + "_iRecordsDisplay": 0,
  13327 +
  13328 + /**
  13329 + * Flag to indicate if jQuery UI marking and classes should be used.
  13330 + * Note that this parameter will be set by the initialisation routine. To
  13331 + * set a default use {@link DataTable.defaults}.
  13332 + * @type boolean
  13333 + */
  13334 + "bJUI": null,
  13335 +
  13336 + /**
  13337 + * The classes to use for the table
  13338 + * @type object
  13339 + * @default {}
  13340 + */
  13341 + "oClasses": {},
  13342 +
  13343 + /**
  13344 + * Flag attached to the settings object so you can check in the draw
  13345 + * callback if filtering has been done in the draw. Deprecated in favour of
  13346 + * events.
  13347 + * @type boolean
  13348 + * @default false
  13349 + * @deprecated
  13350 + */
  13351 + "bFiltered": false,
  13352 +
  13353 + /**
  13354 + * Flag attached to the settings object so you can check in the draw
  13355 + * callback if sorting has been done in the draw. Deprecated in favour of
  13356 + * events.
  13357 + * @type boolean
  13358 + * @default false
  13359 + * @deprecated
  13360 + */
  13361 + "bSorted": false,
  13362 +
  13363 + /**
  13364 + * Indicate that if multiple rows are in the header and there is more than
  13365 + * one unique cell per column, if the top one (true) or bottom one (false)
  13366 + * should be used for sorting / title by DataTables.
  13367 + * Note that this parameter will be set by the initialisation routine. To
  13368 + * set a default use {@link DataTable.defaults}.
  13369 + * @type boolean
  13370 + */
  13371 + "bSortCellsTop": null,
  13372 +
  13373 + /**
  13374 + * Initialisation object that is used for the table
  13375 + * @type object
  13376 + * @default null
  13377 + */
  13378 + "oInit": null,
  13379 +
  13380 + /**
  13381 + * Destroy callback functions - for plug-ins to attach themselves to the
  13382 + * destroy so they can clean up markup and events.
  13383 + * @type array
  13384 + * @default []
  13385 + */
  13386 + "aoDestroyCallback": [],
  13387 +
  13388 +
  13389 + /**
  13390 + * Get the number of records in the current record set, before filtering
  13391 + * @type function
  13392 + */
  13393 + "fnRecordsTotal": function ()
  13394 + {
  13395 + return _fnDataSource( this ) == 'ssp' ?
  13396 + this._iRecordsTotal * 1 :
  13397 + this.aiDisplayMaster.length;
  13398 + },
  13399 +
  13400 + /**
  13401 + * Get the number of records in the current record set, after filtering
  13402 + * @type function
  13403 + */
  13404 + "fnRecordsDisplay": function ()
  13405 + {
  13406 + return _fnDataSource( this ) == 'ssp' ?
  13407 + this._iRecordsDisplay * 1 :
  13408 + this.aiDisplay.length;
  13409 + },
  13410 +
  13411 + /**
  13412 + * Get the display end point - aiDisplay index
  13413 + * @type function
  13414 + */
  13415 + "fnDisplayEnd": function ()
  13416 + {
  13417 + var
  13418 + len = this._iDisplayLength,
  13419 + start = this._iDisplayStart,
  13420 + calc = start + len,
  13421 + records = this.aiDisplay.length,
  13422 + features = this.oFeatures,
  13423 + paginate = features.bPaginate;
  13424 +
  13425 + if ( features.bServerSide ) {
  13426 + return paginate === false || len === -1 ?
  13427 + start + records :
  13428 + Math.min( start+len, this._iRecordsDisplay );
  13429 + }
  13430 + else {
  13431 + return ! paginate || calc>records || len===-1 ?
  13432 + records :
  13433 + calc;
  13434 + }
  13435 + },
  13436 +
  13437 + /**
  13438 + * The DataTables object for this table
  13439 + * @type object
  13440 + * @default null
  13441 + */
  13442 + "oInstance": null,
  13443 +
  13444 + /**
  13445 + * Unique identifier for each instance of the DataTables object. If there
  13446 + * is an ID on the table node, then it takes that value, otherwise an
  13447 + * incrementing internal counter is used.
  13448 + * @type string
  13449 + * @default null
  13450 + */
  13451 + "sInstance": null,
  13452 +
  13453 + /**
  13454 + * tabindex attribute value that is added to DataTables control elements, allowing
  13455 + * keyboard navigation of the table and its controls.
  13456 + */
  13457 + "iTabIndex": 0,
  13458 +
  13459 + /**
  13460 + * DIV container for the footer scrolling table if scrolling
  13461 + */
  13462 + "nScrollHead": null,
  13463 +
  13464 + /**
  13465 + * DIV container for the footer scrolling table if scrolling
  13466 + */
  13467 + "nScrollFoot": null,
  13468 +
  13469 + /**
  13470 + * Last applied sort
  13471 + * @type array
  13472 + * @default []
  13473 + */
  13474 + "aLastSort": [],
  13475 +
  13476 + /**
  13477 + * Stored plug-in instances
  13478 + * @type object
  13479 + * @default {}
  13480 + */
  13481 + "oPlugins": {}
  13482 + };
  13483 +
  13484 + /**
  13485 + * Extension object for DataTables that is used to provide all extension
  13486 + * options.
  13487 + *
  13488 + * Note that the `DataTable.ext` object is available through
  13489 + * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
  13490 + * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
  13491 + * @namespace
  13492 + * @extends DataTable.models.ext
  13493 + */
  13494 +
  13495 +
  13496 + /**
  13497 + * DataTables extensions
  13498 + *
  13499 + * This namespace acts as a collection area for plug-ins that can be used to
  13500 + * extend DataTables capabilities. Indeed many of the build in methods
  13501 + * use this method to provide their own capabilities (sorting methods for
  13502 + * example).
  13503 + *
  13504 + * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
  13505 + * reasons
  13506 + *
  13507 + * @namespace
  13508 + */
  13509 + DataTable.ext = _ext = {
  13510 + /**
  13511 + * Buttons. For use with the Buttons extension for DataTables. This is
  13512 + * defined here so other extensions can define buttons regardless of load
  13513 + * order. It is _not_ used by DataTables core.
  13514 + *
  13515 + * @type object
  13516 + * @default {}
  13517 + */
  13518 + buttons: {},
  13519 +
  13520 +
  13521 + /**
  13522 + * Element class names
  13523 + *
  13524 + * @type object
  13525 + * @default {}
  13526 + */
  13527 + classes: {},
  13528 +
  13529 +
  13530 + /**
  13531 + * Error reporting.
  13532 + *
  13533 + * How should DataTables report an error. Can take the value 'alert',
  13534 + * 'throw', 'none' or a function.
  13535 + *
  13536 + * @type string|function
  13537 + * @default alert
  13538 + */
  13539 + errMode: "alert",
  13540 +
  13541 +
  13542 + /**
  13543 + * Feature plug-ins.
  13544 + *
  13545 + * This is an array of objects which describe the feature plug-ins that are
  13546 + * available to DataTables. These feature plug-ins are then available for
  13547 + * use through the `dom` initialisation option.
  13548 + *
  13549 + * Each feature plug-in is described by an object which must have the
  13550 + * following properties:
  13551 + *
  13552 + * * `fnInit` - function that is used to initialise the plug-in,
  13553 + * * `cFeature` - a character so the feature can be enabled by the `dom`
  13554 + * instillation option. This is case sensitive.
  13555 + *
  13556 + * The `fnInit` function has the following input parameters:
  13557 + *
  13558 + * 1. `{object}` DataTables settings object: see
  13559 + * {@link DataTable.models.oSettings}
  13560 + *
  13561 + * And the following return is expected:
  13562 + *
  13563 + * * {node|null} The element which contains your feature. Note that the
  13564 + * return may also be void if your plug-in does not require to inject any
  13565 + * DOM elements into DataTables control (`dom`) - for example this might
  13566 + * be useful when developing a plug-in which allows table control via
  13567 + * keyboard entry
  13568 + *
  13569 + * @type array
  13570 + *
  13571 + * @example
  13572 + * $.fn.dataTable.ext.features.push( {
  13573 + * "fnInit": function( oSettings ) {
  13574 + * return new TableTools( { "oDTSettings": oSettings } );
  13575 + * },
  13576 + * "cFeature": "T"
  13577 + * } );
  13578 + */
  13579 + feature: [],
  13580 +
  13581 +
  13582 + /**
  13583 + * Row searching.
  13584 + *
  13585 + * This method of searching is complimentary to the default type based
  13586 + * searching, and a lot more comprehensive as it allows you complete control
  13587 + * over the searching logic. Each element in this array is a function
  13588 + * (parameters described below) that is called for every row in the table,
  13589 + * and your logic decides if it should be included in the searching data set
  13590 + * or not.
  13591 + *
  13592 + * Searching functions have the following input parameters:
  13593 + *
  13594 + * 1. `{object}` DataTables settings object: see
  13595 + * {@link DataTable.models.oSettings}
  13596 + * 2. `{array|object}` Data for the row to be processed (same as the
  13597 + * original format that was passed in as the data source, or an array
  13598 + * from a DOM data source
  13599 + * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
  13600 + * can be useful to retrieve the `TR` element if you need DOM interaction.
  13601 + *
  13602 + * And the following return is expected:
  13603 + *
  13604 + * * {boolean} Include the row in the searched result set (true) or not
  13605 + * (false)
  13606 + *
  13607 + * Note that as with the main search ability in DataTables, technically this
  13608 + * is "filtering", since it is subtractive. However, for consistency in
  13609 + * naming we call it searching here.
  13610 + *
  13611 + * @type array
  13612 + * @default []
  13613 + *
  13614 + * @example
  13615 + * // The following example shows custom search being applied to the
  13616 + * // fourth column (i.e. the data[3] index) based on two input values
  13617 + * // from the end-user, matching the data in a certain range.
  13618 + * $.fn.dataTable.ext.search.push(
  13619 + * function( settings, data, dataIndex ) {
  13620 + * var min = document.getElementById('min').value * 1;
  13621 + * var max = document.getElementById('max').value * 1;
  13622 + * var version = data[3] == "-" ? 0 : data[3]*1;
  13623 + *
  13624 + * if ( min == "" && max == "" ) {
  13625 + * return true;
  13626 + * }
  13627 + * else if ( min == "" && version < max ) {
  13628 + * return true;
  13629 + * }
  13630 + * else if ( min < version && "" == max ) {
  13631 + * return true;
  13632 + * }
  13633 + * else if ( min < version && version < max ) {
  13634 + * return true;
  13635 + * }
  13636 + * return false;
  13637 + * }
  13638 + * );
  13639 + */
  13640 + search: [],
  13641 +
  13642 +
  13643 + /**
  13644 + * Selector extensions
  13645 + *
  13646 + * The `selector` option can be used to extend the options available for the
  13647 + * selector modifier options (`selector-modifier` object data type) that
  13648 + * each of the three built in selector types offer (row, column and cell +
  13649 + * their plural counterparts). For example the Select extension uses this
  13650 + * mechanism to provide an option to select only rows, columns and cells
  13651 + * that have been marked as selected by the end user (`{selected: true}`),
  13652 + * which can be used in conjunction with the existing built in selector
  13653 + * options.
  13654 + *
  13655 + * Each property is an array to which functions can be pushed. The functions
  13656 + * take three attributes:
  13657 + *
  13658 + * * Settings object for the host table
  13659 + * * Options object (`selector-modifier` object type)
  13660 + * * Array of selected item indexes
  13661 + *
  13662 + * The return is an array of the resulting item indexes after the custom
  13663 + * selector has been applied.
  13664 + *
  13665 + * @type object
  13666 + */
  13667 + selector: {
  13668 + cell: [],
  13669 + column: [],
  13670 + row: []
  13671 + },
  13672 +
  13673 +
  13674 + /**
  13675 + * Internal functions, exposed for used in plug-ins.
  13676 + *
  13677 + * Please note that you should not need to use the internal methods for
  13678 + * anything other than a plug-in (and even then, try to avoid if possible).
  13679 + * The internal function may change between releases.
  13680 + *
  13681 + * @type object
  13682 + * @default {}
  13683 + */
  13684 + internal: {},
  13685 +
  13686 +
  13687 + /**
  13688 + * Legacy configuration options. Enable and disable legacy options that
  13689 + * are available in DataTables.
  13690 + *
  13691 + * @type object
  13692 + */
  13693 + legacy: {
  13694 + /**
  13695 + * Enable / disable DataTables 1.9 compatible server-side processing
  13696 + * requests
  13697 + *
  13698 + * @type boolean
  13699 + * @default null
  13700 + */
  13701 + ajax: null
  13702 + },
  13703 +
  13704 +
  13705 + /**
  13706 + * Pagination plug-in methods.
  13707 + *
  13708 + * Each entry in this object is a function and defines which buttons should
  13709 + * be shown by the pagination rendering method that is used for the table:
  13710 + * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
  13711 + * buttons are displayed in the document, while the functions here tell it
  13712 + * what buttons to display. This is done by returning an array of button
  13713 + * descriptions (what each button will do).
  13714 + *
  13715 + * Pagination types (the four built in options and any additional plug-in
  13716 + * options defined here) can be used through the `paginationType`
  13717 + * initialisation parameter.
  13718 + *
  13719 + * The functions defined take two parameters:
  13720 + *
  13721 + * 1. `{int} page` The current page index
  13722 + * 2. `{int} pages` The number of pages in the table
  13723 + *
  13724 + * Each function is expected to return an array where each element of the
  13725 + * array can be one of:
  13726 + *
  13727 + * * `first` - Jump to first page when activated
  13728 + * * `last` - Jump to last page when activated
  13729 + * * `previous` - Show previous page when activated
  13730 + * * `next` - Show next page when activated
  13731 + * * `{int}` - Show page of the index given
  13732 + * * `{array}` - A nested array containing the above elements to add a
  13733 + * containing 'DIV' element (might be useful for styling).
  13734 + *
  13735 + * Note that DataTables v1.9- used this object slightly differently whereby
  13736 + * an object with two functions would be defined for each plug-in. That
  13737 + * ability is still supported by DataTables 1.10+ to provide backwards
  13738 + * compatibility, but this option of use is now decremented and no longer
  13739 + * documented in DataTables 1.10+.
  13740 + *
  13741 + * @type object
  13742 + * @default {}
  13743 + *
  13744 + * @example
  13745 + * // Show previous, next and current page buttons only
  13746 + * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
  13747 + * return [ 'previous', page, 'next' ];
  13748 + * };
  13749 + */
  13750 + pager: {},
  13751 +
  13752 +
  13753 + renderer: {
  13754 + pageButton: {},
  13755 + header: {}
  13756 + },
  13757 +
  13758 +
  13759 + /**
  13760 + * Ordering plug-ins - custom data source
  13761 + *
  13762 + * The extension options for ordering of data available here is complimentary
  13763 + * to the default type based ordering that DataTables typically uses. It
  13764 + * allows much greater control over the the data that is being used to
  13765 + * order a column, but is necessarily therefore more complex.
  13766 + *
  13767 + * This type of ordering is useful if you want to do ordering based on data
  13768 + * live from the DOM (for example the contents of an 'input' element) rather
  13769 + * than just the static string that DataTables knows of.
  13770 + *
  13771 + * The way these plug-ins work is that you create an array of the values you
  13772 + * wish to be ordering for the column in question and then return that
  13773 + * array. The data in the array much be in the index order of the rows in
  13774 + * the table (not the currently ordering order!). Which order data gathering
  13775 + * function is run here depends on the `dt-init columns.orderDataType`
  13776 + * parameter that is used for the column (if any).
  13777 + *
  13778 + * The functions defined take two parameters:
  13779 + *
  13780 + * 1. `{object}` DataTables settings object: see
  13781 + * {@link DataTable.models.oSettings}
  13782 + * 2. `{int}` Target column index
  13783 + *
  13784 + * Each function is expected to return an array:
  13785 + *
  13786 + * * `{array}` Data for the column to be ordering upon
  13787 + *
  13788 + * @type array
  13789 + *
  13790 + * @example
  13791 + * // Ordering using `input` node values
  13792 + * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
  13793 + * {
  13794 + * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
  13795 + * return $('input', td).val();
  13796 + * } );
  13797 + * }
  13798 + */
  13799 + order: {},
  13800 +
  13801 +
  13802 + /**
  13803 + * Type based plug-ins.
  13804 + *
  13805 + * Each column in DataTables has a type assigned to it, either by automatic
  13806 + * detection or by direct assignment using the `type` option for the column.
  13807 + * The type of a column will effect how it is ordering and search (plug-ins
  13808 + * can also make use of the column type if required).
  13809 + *
  13810 + * @namespace
  13811 + */
  13812 + type: {
  13813 + /**
  13814 + * Type detection functions.
  13815 + *
  13816 + * The functions defined in this object are used to automatically detect
  13817 + * a column's type, making initialisation of DataTables super easy, even
  13818 + * when complex data is in the table.
  13819 + *
  13820 + * The functions defined take two parameters:
  13821 + *
  13822 + * 1. `{*}` Data from the column cell to be analysed
  13823 + * 2. `{settings}` DataTables settings object. This can be used to
  13824 + * perform context specific type detection - for example detection
  13825 + * based on language settings such as using a comma for a decimal
  13826 + * place. Generally speaking the options from the settings will not
  13827 + * be required
  13828 + *
  13829 + * Each function is expected to return:
  13830 + *
  13831 + * * `{string|null}` Data type detected, or null if unknown (and thus
  13832 + * pass it on to the other type detection functions.
  13833 + *
  13834 + * @type array
  13835 + *
  13836 + * @example
  13837 + * // Currency type detection plug-in:
  13838 + * $.fn.dataTable.ext.type.detect.push(
  13839 + * function ( data, settings ) {
  13840 + * // Check the numeric part
  13841 + * if ( ! $.isNumeric( data.substring(1) ) ) {
  13842 + * return null;
  13843 + * }
  13844 + *
  13845 + * // Check prefixed by currency
  13846 + * if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
  13847 + * return 'currency';
  13848 + * }
  13849 + * return null;
  13850 + * }
  13851 + * );
  13852 + */
  13853 + detect: [],
  13854 +
  13855 +
  13856 + /**
  13857 + * Type based search formatting.
  13858 + *
  13859 + * The type based searching functions can be used to pre-format the
  13860 + * data to be search on. For example, it can be used to strip HTML
  13861 + * tags or to de-format telephone numbers for numeric only searching.
  13862 + *
  13863 + * Note that is a search is not defined for a column of a given type,
  13864 + * no search formatting will be performed.
  13865 + *
  13866 + * Pre-processing of searching data plug-ins - When you assign the sType
  13867 + * for a column (or have it automatically detected for you by DataTables
  13868 + * or a type detection plug-in), you will typically be using this for
  13869 + * custom sorting, but it can also be used to provide custom searching
  13870 + * by allowing you to pre-processing the data and returning the data in
  13871 + * the format that should be searched upon. This is done by adding
  13872 + * functions this object with a parameter name which matches the sType
  13873 + * for that target column. This is the corollary of <i>afnSortData</i>
  13874 + * for searching data.
  13875 + *
  13876 + * The functions defined take a single parameter:
  13877 + *
  13878 + * 1. `{*}` Data from the column cell to be prepared for searching
  13879 + *
  13880 + * Each function is expected to return:
  13881 + *
  13882 + * * `{string|null}` Formatted string that will be used for the searching.
  13883 + *
  13884 + * @type object
  13885 + * @default {}
  13886 + *
  13887 + * @example
  13888 + * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
  13889 + * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
  13890 + * }
  13891 + */
  13892 + search: {},
  13893 +
  13894 +
  13895 + /**
  13896 + * Type based ordering.
  13897 + *
  13898 + * The column type tells DataTables what ordering to apply to the table
  13899 + * when a column is sorted upon. The order for each type that is defined,
  13900 + * is defined by the functions available in this object.
  13901 + *
  13902 + * Each ordering option can be described by three properties added to
  13903 + * this object:
  13904 + *
  13905 + * * `{type}-pre` - Pre-formatting function
  13906 + * * `{type}-asc` - Ascending order function
  13907 + * * `{type}-desc` - Descending order function
  13908 + *
  13909 + * All three can be used together, only `{type}-pre` or only
  13910 + * `{type}-asc` and `{type}-desc` together. It is generally recommended
  13911 + * that only `{type}-pre` is used, as this provides the optimal
  13912 + * implementation in terms of speed, although the others are provided
  13913 + * for compatibility with existing Javascript sort functions.
  13914 + *
  13915 + * `{type}-pre`: Functions defined take a single parameter:
  13916 + *
  13917 + * 1. `{*}` Data from the column cell to be prepared for ordering
  13918 + *
  13919 + * And return:
  13920 + *
  13921 + * * `{*}` Data to be sorted upon
  13922 + *
  13923 + * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
  13924 + * functions, taking two parameters:
  13925 + *
  13926 + * 1. `{*}` Data to compare to the second parameter
  13927 + * 2. `{*}` Data to compare to the first parameter
  13928 + *
  13929 + * And returning:
  13930 + *
  13931 + * * `{*}` Ordering match: <0 if first parameter should be sorted lower
  13932 + * than the second parameter, ===0 if the two parameters are equal and
  13933 + * >0 if the first parameter should be sorted height than the second
  13934 + * parameter.
  13935 + *
  13936 + * @type object
  13937 + * @default {}
  13938 + *
  13939 + * @example
  13940 + * // Numeric ordering of formatted numbers with a pre-formatter
  13941 + * $.extend( $.fn.dataTable.ext.type.order, {
  13942 + * "string-pre": function(x) {
  13943 + * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
  13944 + * return parseFloat( a );
  13945 + * }
  13946 + * } );
  13947 + *
  13948 + * @example
  13949 + * // Case-sensitive string ordering, with no pre-formatting method
  13950 + * $.extend( $.fn.dataTable.ext.order, {
  13951 + * "string-case-asc": function(x,y) {
  13952 + * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  13953 + * },
  13954 + * "string-case-desc": function(x,y) {
  13955 + * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  13956 + * }
  13957 + * } );
  13958 + */
  13959 + order: {}
  13960 + },
  13961 +
  13962 + /**
  13963 + * Unique DataTables instance counter
  13964 + *
  13965 + * @type int
  13966 + * @private
  13967 + */
  13968 + _unique: 0,
  13969 +
  13970 +
  13971 + //
  13972 + // Depreciated
  13973 + // The following properties are retained for backwards compatiblity only.
  13974 + // The should not be used in new projects and will be removed in a future
  13975 + // version
  13976 + //
  13977 +
  13978 + /**
  13979 + * Version check function.
  13980 + * @type function
  13981 + * @depreciated Since 1.10
  13982 + */
  13983 + fnVersionCheck: DataTable.fnVersionCheck,
  13984 +
  13985 +
  13986 + /**
  13987 + * Index for what 'this' index API functions should use
  13988 + * @type int
  13989 + * @deprecated Since v1.10
  13990 + */
  13991 + iApiIndex: 0,
  13992 +
  13993 +
  13994 + /**
  13995 + * jQuery UI class container
  13996 + * @type object
  13997 + * @deprecated Since v1.10
  13998 + */
  13999 + oJUIClasses: {},
  14000 +
  14001 +
  14002 + /**
  14003 + * Software version
  14004 + * @type string
  14005 + * @deprecated Since v1.10
  14006 + */
  14007 + sVersion: DataTable.version
  14008 + };
  14009 +
  14010 +
  14011 + //
  14012 + // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
  14013 + //
  14014 + $.extend( _ext, {
  14015 + afnFiltering: _ext.search,
  14016 + aTypes: _ext.type.detect,
  14017 + ofnSearch: _ext.type.search,
  14018 + oSort: _ext.type.order,
  14019 + afnSortData: _ext.order,
  14020 + aoFeatures: _ext.feature,
  14021 + oApi: _ext.internal,
  14022 + oStdClasses: _ext.classes,
  14023 + oPagination: _ext.pager
  14024 + } );
  14025 +
  14026 +
  14027 + $.extend( DataTable.ext.classes, {
  14028 + "sTable": "dataTable",
  14029 + "sNoFooter": "no-footer",
  14030 +
  14031 + /* Paging buttons */
  14032 + "sPageButton": "paginate_button",
  14033 + "sPageButtonActive": "current",
  14034 + "sPageButtonDisabled": "disabled",
  14035 +
  14036 + /* Striping classes */
  14037 + "sStripeOdd": "odd",
  14038 + "sStripeEven": "even",
  14039 +
  14040 + /* Empty row */
  14041 + "sRowEmpty": "dataTables_empty",
  14042 +
  14043 + /* Features */
  14044 + "sWrapper": "dataTables_wrapper",
  14045 + "sFilter": "dataTables_filter",
  14046 + "sInfo": "dataTables_info",
  14047 + "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
  14048 + "sLength": "dataTables_length",
  14049 + "sProcessing": "dataTables_processing",
  14050 +
  14051 + /* Sorting */
  14052 + "sSortAsc": "sorting_asc",
  14053 + "sSortDesc": "sorting_desc",
  14054 + "sSortable": "sorting", /* Sortable in both directions */
  14055 + "sSortableAsc": "sorting_asc_disabled",
  14056 + "sSortableDesc": "sorting_desc_disabled",
  14057 + "sSortableNone": "sorting_disabled",
  14058 + "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
  14059 +
  14060 + /* Filtering */
  14061 + "sFilterInput": "",
  14062 +
  14063 + /* Page length */
  14064 + "sLengthSelect": "",
  14065 +
  14066 + /* Scrolling */
  14067 + "sScrollWrapper": "dataTables_scroll",
  14068 + "sScrollHead": "dataTables_scrollHead",
  14069 + "sScrollHeadInner": "dataTables_scrollHeadInner",
  14070 + "sScrollBody": "dataTables_scrollBody",
  14071 + "sScrollFoot": "dataTables_scrollFoot",
  14072 + "sScrollFootInner": "dataTables_scrollFootInner",
  14073 +
  14074 + /* Misc */
  14075 + "sHeaderTH": "",
  14076 + "sFooterTH": "",
  14077 +
  14078 + // Deprecated
  14079 + "sSortJUIAsc": "",
  14080 + "sSortJUIDesc": "",
  14081 + "sSortJUI": "",
  14082 + "sSortJUIAscAllowed": "",
  14083 + "sSortJUIDescAllowed": "",
  14084 + "sSortJUIWrapper": "",
  14085 + "sSortIcon": "",
  14086 + "sJUIHeader": "",
  14087 + "sJUIFooter": ""
  14088 + } );
  14089 +
  14090 +
  14091 + (function() {
  14092 +
  14093 + // Reused strings for better compression. Closure compiler appears to have a
  14094 + // weird edge case where it is trying to expand strings rather than use the
  14095 + // variable version. This results in about 200 bytes being added, for very
  14096 + // little preference benefit since it this run on script load only.
  14097 + var _empty = '';
  14098 + _empty = '';
  14099 +
  14100 + var _stateDefault = _empty + 'ui-state-default';
  14101 + var _sortIcon = _empty + 'css_right ui-icon ui-icon-';
  14102 + var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
  14103 +
  14104 + $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
  14105 + /* Full numbers paging buttons */
  14106 + "sPageButton": "fg-button ui-button "+_stateDefault,
  14107 + "sPageButtonActive": "ui-state-disabled",
  14108 + "sPageButtonDisabled": "ui-state-disabled",
  14109 +
  14110 + /* Features */
  14111 + "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
  14112 + "ui-buttonset-multi paging_", /* Note that the type is postfixed */
  14113 +
  14114 + /* Sorting */
  14115 + "sSortAsc": _stateDefault+" sorting_asc",
  14116 + "sSortDesc": _stateDefault+" sorting_desc",
  14117 + "sSortable": _stateDefault+" sorting",
  14118 + "sSortableAsc": _stateDefault+" sorting_asc_disabled",
  14119 + "sSortableDesc": _stateDefault+" sorting_desc_disabled",
  14120 + "sSortableNone": _stateDefault+" sorting_disabled",
  14121 + "sSortJUIAsc": _sortIcon+"triangle-1-n",
  14122 + "sSortJUIDesc": _sortIcon+"triangle-1-s",
  14123 + "sSortJUI": _sortIcon+"carat-2-n-s",
  14124 + "sSortJUIAscAllowed": _sortIcon+"carat-1-n",
  14125 + "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
  14126 + "sSortJUIWrapper": "DataTables_sort_wrapper",
  14127 + "sSortIcon": "DataTables_sort_icon",
  14128 +
  14129 + /* Scrolling */
  14130 + "sScrollHead": "dataTables_scrollHead "+_stateDefault,
  14131 + "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
  14132 +
  14133 + /* Misc */
  14134 + "sHeaderTH": _stateDefault,
  14135 + "sFooterTH": _stateDefault,
  14136 + "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
  14137 + "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
  14138 + } );
  14139 +
  14140 + }());
  14141 +
  14142 +
  14143 +
  14144 + var extPagination = DataTable.ext.pager;
  14145 +
  14146 + function _numbers ( page, pages ) {
  14147 + var
  14148 + numbers = [],
  14149 + buttons = extPagination.numbers_length,
  14150 + half = Math.floor( buttons / 2 ),
  14151 + i = 1;
  14152 +
  14153 + if ( pages <= buttons ) {
  14154 + numbers = _range( 0, pages );
  14155 + }
  14156 + else if ( page <= half ) {
  14157 + numbers = _range( 0, buttons-2 );
  14158 + numbers.push( 'ellipsis' );
  14159 + numbers.push( pages-1 );
  14160 + }
  14161 + else if ( page >= pages - 1 - half ) {
  14162 + numbers = _range( pages-(buttons-2), pages );
  14163 + numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
  14164 + numbers.splice( 0, 0, 0 );
  14165 + }
  14166 + else {
  14167 + numbers = _range( page-half+2, page+half-1 );
  14168 + numbers.push( 'ellipsis' );
  14169 + numbers.push( pages-1 );
  14170 + numbers.splice( 0, 0, 'ellipsis' );
  14171 + numbers.splice( 0, 0, 0 );
  14172 + }
  14173 +
  14174 + numbers.DT_el = 'span';
  14175 + return numbers;
  14176 + }
  14177 +
  14178 +
  14179 + $.extend( extPagination, {
  14180 + simple: function ( page, pages ) {
  14181 + return [ 'previous', 'next' ];
  14182 + },
  14183 +
  14184 + full: function ( page, pages ) {
  14185 + return [ 'first', 'previous', 'next', 'last' ];
  14186 + },
  14187 +
  14188 + simple_numbers: function ( page, pages ) {
  14189 + return [ 'previous', _numbers(page, pages), 'next' ];
  14190 + },
  14191 +
  14192 + full_numbers: function ( page, pages ) {
  14193 + return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
  14194 + },
  14195 +
  14196 + // For testing and plug-ins to use
  14197 + _numbers: _numbers,
  14198 +
  14199 + // Number of number buttons (including ellipsis) to show. _Must be odd!_
  14200 + numbers_length: 7
  14201 + } );
  14202 +
  14203 +
  14204 + $.extend( true, DataTable.ext.renderer, {
  14205 + pageButton: {
  14206 + _: function ( settings, host, idx, buttons, page, pages ) {
  14207 + var classes = settings.oClasses;
  14208 + var lang = settings.oLanguage.oPaginate;
  14209 + var btnDisplay, btnClass, counter=0;
  14210 +
  14211 + var attach = function( container, buttons ) {
  14212 + var i, ien, node, button;
  14213 + var clickHandler = function ( e ) {
  14214 + _fnPageChange( settings, e.data.action, true );
  14215 + };
  14216 +
  14217 + for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
  14218 + button = buttons[i];
  14219 +
  14220 + if ( $.isArray( button ) ) {
  14221 + var inner = $( '<'+(button.DT_el || 'div')+'/>' )
  14222 + .appendTo( container );
  14223 + attach( inner, button );
  14224 + }
  14225 + else {
  14226 + btnDisplay = '';
  14227 + btnClass = '';
  14228 +
  14229 + switch ( button ) {
  14230 + case 'ellipsis':
  14231 + container.append('<span class="ellipsis">&#x2026;</span>');
  14232 + break;
  14233 +
  14234 + case 'first':
  14235 + btnDisplay = lang.sFirst;
  14236 + btnClass = button + (page > 0 ?
  14237 + '' : ' '+classes.sPageButtonDisabled);
  14238 + break;
  14239 +
  14240 + case 'previous':
  14241 + btnDisplay = lang.sPrevious;
  14242 + btnClass = button + (page > 0 ?
  14243 + '' : ' '+classes.sPageButtonDisabled);
  14244 + break;
  14245 +
  14246 + case 'next':
  14247 + btnDisplay = lang.sNext;
  14248 + btnClass = button + (page < pages-1 ?
  14249 + '' : ' '+classes.sPageButtonDisabled);
  14250 + break;
  14251 +
  14252 + case 'last':
  14253 + btnDisplay = lang.sLast;
  14254 + btnClass = button + (page < pages-1 ?
  14255 + '' : ' '+classes.sPageButtonDisabled);
  14256 + break;
  14257 +
  14258 + default:
  14259 + btnDisplay = button + 1;
  14260 + btnClass = page === button ?
  14261 + classes.sPageButtonActive : '';
  14262 + break;
  14263 + }
  14264 +
  14265 + if ( btnDisplay ) {
  14266 + node = $('<a>', {
  14267 + 'class': classes.sPageButton+' '+btnClass,
  14268 + 'aria-controls': settings.sTableId,
  14269 + 'data-dt-idx': counter,
  14270 + 'tabindex': settings.iTabIndex,
  14271 + 'id': idx === 0 && typeof button === 'string' ?
  14272 + settings.sTableId +'_'+ button :
  14273 + null
  14274 + } )
  14275 + .html( btnDisplay )
  14276 + .appendTo( container );
  14277 +
  14278 + _fnBindAction(
  14279 + node, {action: button}, clickHandler
  14280 + );
  14281 +
  14282 + counter++;
  14283 + }
  14284 + }
  14285 + }
  14286 + };
  14287 +
  14288 + // IE9 throws an 'unknown error' if document.activeElement is used
  14289 + // inside an iframe or frame. Try / catch the error. Not good for
  14290 + // accessibility, but neither are frames.
  14291 + var activeEl;
  14292 +
  14293 + try {
  14294 + // Because this approach is destroying and recreating the paging
  14295 + // elements, focus is lost on the select button which is bad for
  14296 + // accessibility. So we want to restore focus once the draw has
  14297 + // completed
  14298 + activeEl = $(document.activeElement).data('dt-idx');
  14299 + }
  14300 + catch (e) {}
  14301 +
  14302 + attach( $(host).empty(), buttons );
  14303 +
  14304 + if ( activeEl ) {
  14305 + $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
  14306 + }
  14307 + }
  14308 + }
  14309 + } );
  14310 +
  14311 +
  14312 +
  14313 + // Built in type detection. See model.ext.aTypes for information about
  14314 + // what is required from this methods.
  14315 + $.extend( DataTable.ext.type.detect, [
  14316 + // Plain numbers - first since V8 detects some plain numbers as dates
  14317 + // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
  14318 + function ( d, settings )
  14319 + {
  14320 + var decimal = settings.oLanguage.sDecimal;
  14321 + return _isNumber( d, decimal ) ? 'num'+decimal : null;
  14322 + },
  14323 +
  14324 + // Dates (only those recognised by the browser's Date.parse)
  14325 + function ( d, settings )
  14326 + {
  14327 + // V8 will remove any unknown characters at the start and end of the
  14328 + // expression, leading to false matches such as `$245.12` or `10%` being
  14329 + // a valid date. See forum thread 18941 for detail.
  14330 + if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
  14331 + return null;
  14332 + }
  14333 + var parsed = Date.parse(d);
  14334 + return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
  14335 + },
  14336 +
  14337 + // Formatted numbers
  14338 + function ( d, settings )
  14339 + {
  14340 + var decimal = settings.oLanguage.sDecimal;
  14341 + return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
  14342 + },
  14343 +
  14344 + // HTML numeric
  14345 + function ( d, settings )
  14346 + {
  14347 + var decimal = settings.oLanguage.sDecimal;
  14348 + return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
  14349 + },
  14350 +
  14351 + // HTML numeric, formatted
  14352 + function ( d, settings )
  14353 + {
  14354 + var decimal = settings.oLanguage.sDecimal;
  14355 + return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
  14356 + },
  14357 +
  14358 + // HTML (this is strict checking - there must be html)
  14359 + function ( d, settings )
  14360 + {
  14361 + return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
  14362 + 'html' : null;
  14363 + }
  14364 + ] );
  14365 +
  14366 +
  14367 +
  14368 + // Filter formatting functions. See model.ext.ofnSearch for information about
  14369 + // what is required from these methods.
  14370 + //
  14371 + // Note that additional search methods are added for the html numbers and
  14372 + // html formatted numbers by `_addNumericSort()` when we know what the decimal
  14373 + // place is
  14374 +
  14375 +
  14376 + $.extend( DataTable.ext.type.search, {
  14377 + html: function ( data ) {
  14378 + return _empty(data) ?
  14379 + data :
  14380 + typeof data === 'string' ?
  14381 + data
  14382 + .replace( _re_new_lines, " " )
  14383 + .replace( _re_html, "" ) :
  14384 + '';
  14385 + },
  14386 +
  14387 + string: function ( data ) {
  14388 + return _empty(data) ?
  14389 + data :
  14390 + typeof data === 'string' ?
  14391 + data.replace( _re_new_lines, " " ) :
  14392 + data;
  14393 + }
  14394 + } );
  14395 +
  14396 +
  14397 +
  14398 + var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
  14399 + if ( d !== 0 && (!d || d === '-') ) {
  14400 + return -Infinity;
  14401 + }
  14402 +
  14403 + // If a decimal place other than `.` is used, it needs to be given to the
  14404 + // function so we can detect it and replace with a `.` which is the only
  14405 + // decimal place Javascript recognises - it is not locale aware.
  14406 + if ( decimalPlace ) {
  14407 + d = _numToDecimal( d, decimalPlace );
  14408 + }
  14409 +
  14410 + if ( d.replace ) {
  14411 + if ( re1 ) {
  14412 + d = d.replace( re1, '' );
  14413 + }
  14414 +
  14415 + if ( re2 ) {
  14416 + d = d.replace( re2, '' );
  14417 + }
  14418 + }
  14419 +
  14420 + return d * 1;
  14421 + };
  14422 +
  14423 +
  14424 + // Add the numeric 'deformatting' functions for sorting and search. This is done
  14425 + // in a function to provide an easy ability for the language options to add
  14426 + // additional methods if a non-period decimal place is used.
  14427 + function _addNumericSort ( decimalPlace ) {
  14428 + $.each(
  14429 + {
  14430 + // Plain numbers
  14431 + "num": function ( d ) {
  14432 + return __numericReplace( d, decimalPlace );
  14433 + },
  14434 +
  14435 + // Formatted numbers
  14436 + "num-fmt": function ( d ) {
  14437 + return __numericReplace( d, decimalPlace, _re_formatted_numeric );
  14438 + },
  14439 +
  14440 + // HTML numeric
  14441 + "html-num": function ( d ) {
  14442 + return __numericReplace( d, decimalPlace, _re_html );
  14443 + },
  14444 +
  14445 + // HTML numeric, formatted
  14446 + "html-num-fmt": function ( d ) {
  14447 + return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
  14448 + }
  14449 + },
  14450 + function ( key, fn ) {
  14451 + // Add the ordering method
  14452 + _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
  14453 +
  14454 + // For HTML types add a search formatter that will strip the HTML
  14455 + if ( key.match(/^html\-/) ) {
  14456 + _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
  14457 + }
  14458 + }
  14459 + );
  14460 + }
  14461 +
  14462 +
  14463 + // Default sort methods
  14464 + $.extend( _ext.type.order, {
  14465 + // Dates
  14466 + "date-pre": function ( d ) {
  14467 + return Date.parse( d ) || 0;
  14468 + },
  14469 +
  14470 + // html
  14471 + "html-pre": function ( a ) {
  14472 + return _empty(a) ?
  14473 + '' :
  14474 + a.replace ?
  14475 + a.replace( /<.*?>/g, "" ).toLowerCase() :
  14476 + a+'';
  14477 + },
  14478 +
  14479 + // string
  14480 + "string-pre": function ( a ) {
  14481 + // This is a little complex, but faster than always calling toString,
  14482 + // http://jsperf.com/tostring-v-check
  14483 + return _empty(a) ?
  14484 + '' :
  14485 + typeof a === 'string' ?
  14486 + a.toLowerCase() :
  14487 + ! a.toString ?
  14488 + '' :
  14489 + a.toString();
  14490 + },
  14491 +
  14492 + // string-asc and -desc are retained only for compatibility with the old
  14493 + // sort methods
  14494 + "string-asc": function ( x, y ) {
  14495 + return ((x < y) ? -1 : ((x > y) ? 1 : 0));
  14496 + },
  14497 +
  14498 + "string-desc": function ( x, y ) {
  14499 + return ((x < y) ? 1 : ((x > y) ? -1 : 0));
  14500 + }
  14501 + } );
  14502 +
  14503 +
  14504 + // Numeric sorting types - order doesn't matter here
  14505 + _addNumericSort( '' );
  14506 +
  14507 +
  14508 + $.extend( true, DataTable.ext.renderer, {
  14509 + header: {
  14510 + _: function ( settings, cell, column, classes ) {
  14511 + // No additional mark-up required
  14512 + // Attach a sort listener to update on sort - note that using the
  14513 + // `DT` namespace will allow the event to be removed automatically
  14514 + // on destroy, while the `dt` namespaced event is the one we are
  14515 + // listening for
  14516 + $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
  14517 + if ( settings !== ctx ) { // need to check this this is the host
  14518 + return; // table, not a nested one
  14519 + }
  14520 +
  14521 + var colIdx = column.idx;
  14522 +
  14523 + cell
  14524 + .removeClass(
  14525 + column.sSortingClass +' '+
  14526 + classes.sSortAsc +' '+
  14527 + classes.sSortDesc
  14528 + )
  14529 + .addClass( columns[ colIdx ] == 'asc' ?
  14530 + classes.sSortAsc : columns[ colIdx ] == 'desc' ?
  14531 + classes.sSortDesc :
  14532 + column.sSortingClass
  14533 + );
  14534 + } );
  14535 + },
  14536 +
  14537 + jqueryui: function ( settings, cell, column, classes ) {
  14538 + $('<div/>')
  14539 + .addClass( classes.sSortJUIWrapper )
  14540 + .append( cell.contents() )
  14541 + .append( $('<span/>')
  14542 + .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
  14543 + )
  14544 + .appendTo( cell );
  14545 +
  14546 + // Attach a sort listener to update on sort
  14547 + $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
  14548 + if ( settings !== ctx ) {
  14549 + return;
  14550 + }
  14551 +
  14552 + var colIdx = column.idx;
  14553 +
  14554 + cell
  14555 + .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
  14556 + .addClass( columns[ colIdx ] == 'asc' ?
  14557 + classes.sSortAsc : columns[ colIdx ] == 'desc' ?
  14558 + classes.sSortDesc :
  14559 + column.sSortingClass
  14560 + );
  14561 +
  14562 + cell
  14563 + .find( 'span.'+classes.sSortIcon )
  14564 + .removeClass(
  14565 + classes.sSortJUIAsc +" "+
  14566 + classes.sSortJUIDesc +" "+
  14567 + classes.sSortJUI +" "+
  14568 + classes.sSortJUIAscAllowed +" "+
  14569 + classes.sSortJUIDescAllowed
  14570 + )
  14571 + .addClass( columns[ colIdx ] == 'asc' ?
  14572 + classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
  14573 + classes.sSortJUIDesc :
  14574 + column.sSortingClassJUI
  14575 + );
  14576 + } );
  14577 + }
  14578 + }
  14579 + } );
  14580 +
  14581 + /*
  14582 + * Public helper functions. These aren't used internally by DataTables, or
  14583 + * called by any of the options passed into DataTables, but they can be used
  14584 + * externally by developers working with DataTables. They are helper functions
  14585 + * to make working with DataTables a little bit easier.
  14586 + */
  14587 +
  14588 + /**
  14589 + * Helpers for `columns.render`.
  14590 + *
  14591 + * The options defined here can be used with the `columns.render` initialisation
  14592 + * option to provide a display renderer. The following functions are defined:
  14593 + *
  14594 + * * `number` - Will format numeric data (defined by `columns.data`) for
  14595 + * display, retaining the original unformatted data for sorting and filtering.
  14596 + * It takes 4 parameters:
  14597 + * * `string` - Thousands grouping separator
  14598 + * * `string` - Decimal point indicator
  14599 + * * `integer` - Number of decimal points to show
  14600 + * * `string` (optional) - Prefix.
  14601 + *
  14602 + * @example
  14603 + * // Column definition using the number renderer
  14604 + * {
  14605 + * data: "salary",
  14606 + * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
  14607 + * }
  14608 + *
  14609 + * @namespace
  14610 + */
  14611 + DataTable.render = {
  14612 + number: function ( thousands, decimal, precision, prefix ) {
  14613 + return {
  14614 + display: function ( d ) {
  14615 + if ( typeof d !== 'number' && typeof d !== 'string' ) {
  14616 + return d;
  14617 + }
  14618 +
  14619 + var negative = d < 0 ? '-' : '';
  14620 + d = Math.abs( parseFloat( d ) );
  14621 +
  14622 + var intPart = parseInt( d, 10 );
  14623 + var floatPart = precision ?
  14624 + decimal+(d - intPart).toFixed( precision ).substring( 2 ):
  14625 + '';
  14626 +
  14627 + return negative + (prefix||'') +
  14628 + intPart.toString().replace(
  14629 + /\B(?=(\d{3})+(?!\d))/g, thousands
  14630 + ) +
  14631 + floatPart;
  14632 + }
  14633 + };
  14634 + }
  14635 + };
  14636 +
  14637 +
  14638 + /*
  14639 + * This is really a good bit rubbish this method of exposing the internal methods
  14640 + * publicly... - To be fixed in 2.0 using methods on the prototype
  14641 + */
  14642 +
  14643 +
  14644 + /**
  14645 + * Create a wrapper function for exporting an internal functions to an external API.
  14646 + * @param {string} fn API function name
  14647 + * @returns {function} wrapped function
  14648 + * @memberof DataTable#internal
  14649 + */
  14650 + function _fnExternApiFunc (fn)
  14651 + {
  14652 + return function() {
  14653 + var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
  14654 + Array.prototype.slice.call(arguments)
  14655 + );
  14656 + return DataTable.ext.internal[fn].apply( this, args );
  14657 + };
  14658 + }
  14659 +
  14660 +
  14661 + /**
  14662 + * Reference to internal functions for use by plug-in developers. Note that
  14663 + * these methods are references to internal functions and are considered to be
  14664 + * private. If you use these methods, be aware that they are liable to change
  14665 + * between versions.
  14666 + * @namespace
  14667 + */
  14668 + $.extend( DataTable.ext.internal, {
  14669 + _fnExternApiFunc: _fnExternApiFunc,
  14670 + _fnBuildAjax: _fnBuildAjax,
  14671 + _fnAjaxUpdate: _fnAjaxUpdate,
  14672 + _fnAjaxParameters: _fnAjaxParameters,
  14673 + _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
  14674 + _fnAjaxDataSrc: _fnAjaxDataSrc,
  14675 + _fnAddColumn: _fnAddColumn,
  14676 + _fnColumnOptions: _fnColumnOptions,
  14677 + _fnAdjustColumnSizing: _fnAdjustColumnSizing,
  14678 + _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
  14679 + _fnColumnIndexToVisible: _fnColumnIndexToVisible,
  14680 + _fnVisbleColumns: _fnVisbleColumns,
  14681 + _fnGetColumns: _fnGetColumns,
  14682 + _fnColumnTypes: _fnColumnTypes,
  14683 + _fnApplyColumnDefs: _fnApplyColumnDefs,
  14684 + _fnHungarianMap: _fnHungarianMap,
  14685 + _fnCamelToHungarian: _fnCamelToHungarian,
  14686 + _fnLanguageCompat: _fnLanguageCompat,
  14687 + _fnBrowserDetect: _fnBrowserDetect,
  14688 + _fnAddData: _fnAddData,
  14689 + _fnAddTr: _fnAddTr,
  14690 + _fnNodeToDataIndex: _fnNodeToDataIndex,
  14691 + _fnNodeToColumnIndex: _fnNodeToColumnIndex,
  14692 + _fnGetCellData: _fnGetCellData,
  14693 + _fnSetCellData: _fnSetCellData,
  14694 + _fnSplitObjNotation: _fnSplitObjNotation,
  14695 + _fnGetObjectDataFn: _fnGetObjectDataFn,
  14696 + _fnSetObjectDataFn: _fnSetObjectDataFn,
  14697 + _fnGetDataMaster: _fnGetDataMaster,
  14698 + _fnClearTable: _fnClearTable,
  14699 + _fnDeleteIndex: _fnDeleteIndex,
  14700 + _fnInvalidate: _fnInvalidate,
  14701 + _fnGetRowElements: _fnGetRowElements,
  14702 + _fnCreateTr: _fnCreateTr,
  14703 + _fnBuildHead: _fnBuildHead,
  14704 + _fnDrawHead: _fnDrawHead,
  14705 + _fnDraw: _fnDraw,
  14706 + _fnReDraw: _fnReDraw,
  14707 + _fnAddOptionsHtml: _fnAddOptionsHtml,
  14708 + _fnDetectHeader: _fnDetectHeader,
  14709 + _fnGetUniqueThs: _fnGetUniqueThs,
  14710 + _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
  14711 + _fnFilterComplete: _fnFilterComplete,
  14712 + _fnFilterCustom: _fnFilterCustom,
  14713 + _fnFilterColumn: _fnFilterColumn,
  14714 + _fnFilter: _fnFilter,
  14715 + _fnFilterCreateSearch: _fnFilterCreateSearch,
  14716 + _fnEscapeRegex: _fnEscapeRegex,
  14717 + _fnFilterData: _fnFilterData,
  14718 + _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
  14719 + _fnUpdateInfo: _fnUpdateInfo,
  14720 + _fnInfoMacros: _fnInfoMacros,
  14721 + _fnInitialise: _fnInitialise,
  14722 + _fnInitComplete: _fnInitComplete,
  14723 + _fnLengthChange: _fnLengthChange,
  14724 + _fnFeatureHtmlLength: _fnFeatureHtmlLength,
  14725 + _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
  14726 + _fnPageChange: _fnPageChange,
  14727 + _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
  14728 + _fnProcessingDisplay: _fnProcessingDisplay,
  14729 + _fnFeatureHtmlTable: _fnFeatureHtmlTable,
  14730 + _fnScrollDraw: _fnScrollDraw,
  14731 + _fnApplyToChildren: _fnApplyToChildren,
  14732 + _fnCalculateColumnWidths: _fnCalculateColumnWidths,
  14733 + _fnThrottle: _fnThrottle,
  14734 + _fnConvertToWidth: _fnConvertToWidth,
  14735 + _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
  14736 + _fnGetWidestNode: _fnGetWidestNode,
  14737 + _fnGetMaxLenString: _fnGetMaxLenString,
  14738 + _fnStringToCss: _fnStringToCss,
  14739 + _fnScrollBarWidth: _fnScrollBarWidth,
  14740 + _fnSortFlatten: _fnSortFlatten,
  14741 + _fnSort: _fnSort,
  14742 + _fnSortAria: _fnSortAria,
  14743 + _fnSortListener: _fnSortListener,
  14744 + _fnSortAttachListener: _fnSortAttachListener,
  14745 + _fnSortingClasses: _fnSortingClasses,
  14746 + _fnSortData: _fnSortData,
  14747 + _fnSaveState: _fnSaveState,
  14748 + _fnLoadState: _fnLoadState,
  14749 + _fnSettingsFromNode: _fnSettingsFromNode,
  14750 + _fnLog: _fnLog,
  14751 + _fnMap: _fnMap,
  14752 + _fnBindAction: _fnBindAction,
  14753 + _fnCallbackReg: _fnCallbackReg,
  14754 + _fnCallbackFire: _fnCallbackFire,
  14755 + _fnLengthOverflow: _fnLengthOverflow,
  14756 + _fnRenderer: _fnRenderer,
  14757 + _fnDataSource: _fnDataSource,
  14758 + _fnRowAttributes: _fnRowAttributes,
  14759 + _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
  14760 + // in 1.10, so this dead-end function is
  14761 + // added to prevent errors
  14762 + } );
  14763 +
  14764 +
  14765 + // jQuery access
  14766 + $.fn.dataTable = DataTable;
  14767 +
  14768 + // Legacy aliases
  14769 + $.fn.dataTableSettings = DataTable.settings;
  14770 + $.fn.dataTableExt = DataTable.ext;
  14771 +
  14772 + // With a capital `D` we return a DataTables API instance rather than a
  14773 + // jQuery object
  14774 + $.fn.DataTable = function ( opts ) {
  14775 + return $(this).dataTable( opts ).api();
  14776 + };
  14777 +
  14778 + // All properties that are available to $.fn.dataTable should also be
  14779 + // available on $.fn.DataTable
  14780 + $.each( DataTable, function ( prop, val ) {
  14781 + $.fn.DataTable[ prop ] = val;
  14782 + } );
  14783 +
  14784 +
  14785 + // Information about events fired by DataTables - for documentation.
  14786 + /**
  14787 + * Draw event, fired whenever the table is redrawn on the page, at the same
  14788 + * point as fnDrawCallback. This may be useful for binding events or
  14789 + * performing calculations when the table is altered at all.
  14790 + * @name DataTable#draw.dt
  14791 + * @event
  14792 + * @param {event} e jQuery event object
  14793 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14794 + */
  14795 +
  14796 + /**
  14797 + * Search event, fired when the searching applied to the table (using the
  14798 + * built-in global search, or column filters) is altered.
  14799 + * @name DataTable#search.dt
  14800 + * @event
  14801 + * @param {event} e jQuery event object
  14802 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14803 + */
  14804 +
  14805 + /**
  14806 + * Page change event, fired when the paging of the table is altered.
  14807 + * @name DataTable#page.dt
  14808 + * @event
  14809 + * @param {event} e jQuery event object
  14810 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14811 + */
  14812 +
  14813 + /**
  14814 + * Order event, fired when the ordering applied to the table is altered.
  14815 + * @name DataTable#order.dt
  14816 + * @event
  14817 + * @param {event} e jQuery event object
  14818 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14819 + */
  14820 +
  14821 + /**
  14822 + * DataTables initialisation complete event, fired when the table is fully
  14823 + * drawn, including Ajax data loaded, if Ajax data is required.
  14824 + * @name DataTable#init.dt
  14825 + * @event
  14826 + * @param {event} e jQuery event object
  14827 + * @param {object} oSettings DataTables settings object
  14828 + * @param {object} json The JSON object request from the server - only
  14829 + * present if client-side Ajax sourced data is used</li></ol>
  14830 + */
  14831 +
  14832 + /**
  14833 + * State save event, fired when the table has changed state a new state save
  14834 + * is required. This event allows modification of the state saving object
  14835 + * prior to actually doing the save, including addition or other state
  14836 + * properties (for plug-ins) or modification of a DataTables core property.
  14837 + * @name DataTable#stateSaveParams.dt
  14838 + * @event
  14839 + * @param {event} e jQuery event object
  14840 + * @param {object} oSettings DataTables settings object
  14841 + * @param {object} json The state information to be saved
  14842 + */
  14843 +
  14844 + /**
  14845 + * State load event, fired when the table is loading state from the stored
  14846 + * data, but prior to the settings object being modified by the saved state
  14847 + * - allowing modification of the saved state is required or loading of
  14848 + * state for a plug-in.
  14849 + * @name DataTable#stateLoadParams.dt
  14850 + * @event
  14851 + * @param {event} e jQuery event object
  14852 + * @param {object} oSettings DataTables settings object
  14853 + * @param {object} json The saved state information
  14854 + */
  14855 +
  14856 + /**
  14857 + * State loaded event, fired when state has been loaded from stored data and
  14858 + * the settings object has been modified by the loaded data.
  14859 + * @name DataTable#stateLoaded.dt
  14860 + * @event
  14861 + * @param {event} e jQuery event object
  14862 + * @param {object} oSettings DataTables settings object
  14863 + * @param {object} json The saved state information
  14864 + */
  14865 +
  14866 + /**
  14867 + * Processing event, fired when DataTables is doing some kind of processing
  14868 + * (be it, order, searcg or anything else). It can be used to indicate to
  14869 + * the end user that there is something happening, or that something has
  14870 + * finished.
  14871 + * @name DataTable#processing.dt
  14872 + * @event
  14873 + * @param {event} e jQuery event object
  14874 + * @param {object} oSettings DataTables settings object
  14875 + * @param {boolean} bShow Flag for if DataTables is doing processing or not
  14876 + */
  14877 +
  14878 + /**
  14879 + * Ajax (XHR) event, fired whenever an Ajax request is completed from a
  14880 + * request to made to the server for new data. This event is called before
  14881 + * DataTables processed the returned data, so it can also be used to pre-
  14882 + * process the data returned from the server, if needed.
  14883 + *
  14884 + * Note that this trigger is called in `fnServerData`, if you override
  14885 + * `fnServerData` and which to use this event, you need to trigger it in you
  14886 + * success function.
  14887 + * @name DataTable#xhr.dt
  14888 + * @event
  14889 + * @param {event} e jQuery event object
  14890 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14891 + * @param {object} json JSON returned from the server
  14892 + *
  14893 + * @example
  14894 + * // Use a custom property returned from the server in another DOM element
  14895 + * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
  14896 + * $('#status').html( json.status );
  14897 + * } );
  14898 + *
  14899 + * @example
  14900 + * // Pre-process the data returned from the server
  14901 + * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
  14902 + * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
  14903 + * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
  14904 + * }
  14905 + * // Note no return - manipulate the data directly in the JSON object.
  14906 + * } );
  14907 + */
  14908 +
  14909 + /**
  14910 + * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
  14911 + * or passing the bDestroy:true parameter in the initialisation object. This
  14912 + * can be used to remove bound events, added DOM nodes, etc.
  14913 + * @name DataTable#destroy.dt
  14914 + * @event
  14915 + * @param {event} e jQuery event object
  14916 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14917 + */
  14918 +
  14919 + /**
  14920 + * Page length change event, fired when number of records to show on each
  14921 + * page (the length) is changed.
  14922 + * @name DataTable#length.dt
  14923 + * @event
  14924 + * @param {event} e jQuery event object
  14925 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14926 + * @param {integer} len New length
  14927 + */
  14928 +
  14929 + /**
  14930 + * Column sizing has changed.
  14931 + * @name DataTable#column-sizing.dt
  14932 + * @event
  14933 + * @param {event} e jQuery event object
  14934 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14935 + */
  14936 +
  14937 + /**
  14938 + * Column visibility has changed.
  14939 + * @name DataTable#column-visibility.dt
  14940 + * @event
  14941 + * @param {event} e jQuery event object
  14942 + * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
  14943 + * @param {int} column Column index
  14944 + * @param {bool} vis `false` if column now hidden, or `true` if visible
  14945 + */
  14946 +
  14947 + return $.fn.dataTable;
  14948 +}));
  14949 +
  14950 +}(window, document));
  14951 +
... ...
src/main/resources/static/pages/base/line/list.html
... ... @@ -30,16 +30,17 @@
30 30 <thead>
31 31 <tr role="row" class="heading">
32 32 <th width="3%">#</th>
33   - <th width="8%">线路编码</th>
  33 + <th width="7%">线路编码</th>
34 34 <th width="8%">线路名称</th>
35   - <th width="10%">所属公司</th>
36   - <th width="10%">所属分公司</th>
37   - <th width="10%">线路性质</th>
38   - <th width="10%">线路等级</th>
  35 + <th width="7%">所属公司</th>
  36 + <th width="8%">所属分公司</th>
  37 + <th width="8%">线路性质</th>
  38 + <th width="8%">线路等级</th>
39 39 <th width="7%">上海市线路编码</th>
40   - <th width="10%">是否撤销</th>
  40 + <th width="7%">是否撤销</th>
41 41 <th width="8%">线路标准</th>
42   - <th width="15%">操作</th>
  42 + <th width="8%">站点详情</th>
  43 + <th width="14%">操作</th>
43 44 </tr>
44 45 <tr role="row" class="filter">
45 46 <td></td>
... ... @@ -91,6 +92,8 @@
91 92 <td>
92 93 </td>
93 94 <td>
  95 + </td>
  96 + <td>
94 97 <button class="btn btn-sm green btn-outline filter-submit margin-bottom" >
95 98 <i class="fa fa-search"></i> 搜索
96 99 </button>
... ... @@ -145,6 +148,9 @@
145 148 <a href="/pages/base/lineinformation/list.html?lineId={{obj.id}}" class="btn default blue-stripe btn-sm" data-pjax> 查看 </a>
146 149 </td>
147 150 <td>
  151 + <a href="/pages/base/stationroute/list.html?lineId={{obj.id}}" class="btn default blue-stripe btn-sm" data-pjax> 查看 </a>
  152 + </td>
  153 + <td>
148 154 <a href="details.html?lineId={{obj.id}}" class="btn default blue-stripe btn-sm" data-pjax> 详细 </a>
149 155 <a href="edit.html?lineId={{obj.id}}" class="btn default blue-stripe btn-sm" data-pjax> 修改 </a>
150 156 </td>
... ...
src/main/resources/static/pages/base/section/list.html 0 → 100644
  1 +<div class="page-head">
  2 + <div class="page-title">
  3 + <h1>站点信息</h1>
  4 + </div>
  5 +</div>
  6 +
  7 +<ul class="page-breadcrumb breadcrumb">
  8 + <li><a href="/pages/home.html" data-pjax>首页</a> <i class="fa fa-circle"></i></li>
  9 + <li><span class="active">基础信息</span> <i class="fa fa-circle"></i></li>
  10 + <li><span class="active">站点信息</span></li>
  11 +</ul>
  12 +
  13 +<div class="row">
  14 + <div class="col-md-12">
  15 + <div class="portlet light porttlet-fit bordered">
  16 + <div class="portlet-title">
  17 + <div class="caption">
  18 + <i class="fa fa-info-circle font-dark"></i>
  19 + <span class="caption-subject font-dark sbold uppercase">站点信息</span>
  20 + </div>
  21 + <div class="actions">
  22 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  23 + <a class="btn btn-circle blue" href="add.html" data-pjax><i class="fa fa-plus"></i> 添加站点</a>
  24 + </div>
  25 + </div>
  26 + </div>
  27 + <div class="portlet-body">
  28 + <div class="table-container" style="margin-top: 10px">
  29 + <table class="table table-striped table-bordered table-hover table-checkable" id="datatable_line">
  30 + <thead>
  31 + <tr role="row" class="heading">
  32 + <th width="3%">#</th>
  33 + <th width="8%">线路编码</th>
  34 + <th width="8%">线路名称</th>
  35 + <th width="8%">站点名称</th>
  36 + <th width="8%">停车场编码</th>
  37 + <th width="8%">起始站名称</th>
  38 + <th width="8%">终点站名称</th>
  39 + <th width="8%">所属分公司</th>
  40 + <th width="8%">所属公司</th>
  41 + <th width="8%">运营状态</th>
  42 + <th width="15%">操作</th>
  43 + </tr>
  44 + <tr role="row" class="filter">
  45 + <td></td>
  46 + <td>
  47 + <input type="text" class="form-control form-filter input-sm" name="lineCode">
  48 + </td>
  49 + <td>
  50 + <input type="text" class="form-control form-filter input-sm" name="name">
  51 + </td>
  52 + <td>
  53 + <input type="text" class="form-control form-filter input-sm" name="carSumNumber">
  54 + </td>
  55 + <td>
  56 + <input type="text" class="form-control form-filter input-sm" name="carParkCode">
  57 + </td>
  58 + <td>
  59 + <input type="text" class="form-control form-filter input-sm" name="startStationName">
  60 + </td>
  61 + <td>
  62 + <input type="text" class="form-control form-filter input-sm" name="endStationName">
  63 + </td>
  64 + <td>
  65 + <input type="text" class="form-control form-filter input-sm" name="brancheCompany">
  66 + </td>
  67 + <td>
  68 + <input type="text" class="form-control form-filter input-sm" name="company">
  69 + </td>
  70 + <td>
  71 + <select class="form-control form-filter " name="destroy">
  72 + <option value="">请选择...</option>
  73 + <option value="1">运营</option>
  74 + <option value="0">撤销</option>
  75 + </select>
  76 + </td>
  77 + <td>
  78 + <button class="btn btn-sm green btn-outline filter-submit margin-bottom" >
  79 + <i class="fa fa-search"></i> 搜索
  80 + </button>
  81 +
  82 + <button class="btn btn-sm red btn-outline filter-cancel">
  83 + <i class="fa fa-times"></i> 重置
  84 + </button>
  85 + </td>
  86 + </tr>
  87 + </thead>
  88 + <tbody></tbody>
  89 + </table>
  90 + <div style="text-align: right;">
  91 + <ul id="pagination" class="pagination"></ul>
  92 + </div>
  93 + </div>
  94 + </div>
  95 + </div>
  96 + </div>
  97 +</div>
  98 +<script type="text/html" id="line_list_temp">
  99 + {{each list as obj i }}
  100 + <tr>
  101 + <td style="vertical-align: middle;">
  102 + <input type="checkbox" class="group-checkable icheck" data-id="{{obj.id}}">
  103 + </td>
  104 + <td>
  105 + {{obj.lineCode}}
  106 + </td>
  107 + <td>
  108 + {{obj.name}}
  109 + </td>
  110 + <td>
  111 + {{obj.carSumNumber}}
  112 + </td>
  113 + <td>
  114 + {{obj.carParkCode}}
  115 + </td>
  116 + <td>
  117 + {{obj.startStationName}}
  118 + </td>
  119 + <td>
  120 + {{obj.endStationName}}
  121 + </td>
  122 + <td>
  123 + {{obj.company}}
  124 + </td>
  125 + <td>
  126 + {{obj.brancheCompany}}
  127 + </td>
  128 + <td>
  129 + {{obj.destroy}}
  130 + </td>
  131 + <td>
  132 + <a href="edit.html?no={{obj.id}}" class="btn default blue-stripe btn-sm" data-pjax> 详细 </a>
  133 + </td>
  134 + </tr>
  135 + {{/each}}
  136 + {{if list.length == 0}}
  137 + <tr>
  138 + <td colspan=8><h6 class="muted">没有找到相关数据</h6></td>
  139 + </tr>
  140 + {{/if}}
  141 +</script>
  142 +<script src="/pages/base/line/js/list.js"></script>
0 143 \ No newline at end of file
... ...
src/main/resources/static/pages/base/station/list.html 0 → 100644
  1 +<div class="page-head">
  2 + <div class="page-title">
  3 + <h1>站点信息</h1>
  4 + </div>
  5 +</div>
  6 +
  7 +<ul class="page-breadcrumb breadcrumb">
  8 + <li><a href="/pages/home.html" data-pjax>首页</a> <i class="fa fa-circle"></i></li>
  9 + <li><span class="active">基础信息</span> <i class="fa fa-circle"></i></li>
  10 + <li><span class="active">站点信息</span></li>
  11 +</ul>
  12 +
  13 +<div class="row">
  14 + <div class="col-md-12">
  15 + <div class="portlet light porttlet-fit bordered">
  16 + <div class="portlet-title">
  17 + <div class="caption">
  18 + <i class="fa fa-info-circle font-dark"></i>
  19 + <span class="caption-subject font-dark sbold uppercase">站点信息</span>
  20 + </div>
  21 + <div class="actions">
  22 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  23 + <a class="btn btn-circle blue" href="add.html" data-pjax><i class="fa fa-plus"></i> 添加站点</a>
  24 + </div>
  25 + </div>
  26 + </div>
  27 + <div class="portlet-body">
  28 + <div class="table-container" style="margin-top: 10px">
  29 + <table class="table table-striped table-bordered table-hover table-checkable" id="datatable_line">
  30 + <thead>
  31 + <tr role="row" class="heading">
  32 + <th width="3%">#</th>
  33 + <th width="8%">站点编码</th>
  34 + <th width="8%">站点名称</th>
  35 + <th width="8%">图形类型</th>
  36 + <th width="8%">圆形半径</th>
  37 + <th width="8%">版本号</th>
  38 + <th width="8%">是否撤销</th>
  39 + <th width="15%">操作</th>
  40 + </tr>
  41 + <tr role="row" class="filter">
  42 + <td></td>
  43 + <td>
  44 + <input type="text" class="form-control form-filter input-sm" name="carParkCode">
  45 + </td>
  46 + <td>
  47 + <input type="text" class="form-control form-filter input-sm" name="startStationName">
  48 + </td>
  49 + <td>
  50 + <input type="text" class="form-control form-filter input-sm" name="endStationName">
  51 + </td>
  52 + <td>
  53 + <input type="text" class="form-control form-filter input-sm" name="brancheCompany">
  54 + </td>
  55 + <td>
  56 + <input type="text" class="form-control form-filter input-sm" name="company">
  57 + </td>
  58 + <td>
  59 + <select class="form-control form-filter " name="destroy">
  60 + <option value="">请选择...</option>
  61 + <option value="1">运营</option>
  62 + <option value="0">撤销</option>
  63 + </select>
  64 + </td>
  65 + <td>
  66 + <button class="btn btn-sm green btn-outline filter-submit margin-bottom" >
  67 + <i class="fa fa-search"></i> 搜索
  68 + </button>
  69 +
  70 + <button class="btn btn-sm red btn-outline filter-cancel">
  71 + <i class="fa fa-times"></i> 重置
  72 + </button>
  73 + </td>
  74 + </tr>
  75 + </thead>
  76 + <tbody></tbody>
  77 + </table>
  78 + <div style="text-align: right;">
  79 + <ul id="pagination" class="pagination"></ul>
  80 + </div>
  81 + </div>
  82 + </div>
  83 + </div>
  84 + </div>
  85 +</div>
  86 +<script type="text/html" id="line_list_temp">
  87 + {{each list as obj i }}
  88 + <tr>
  89 + <td style="vertical-align: middle;">
  90 + <input type="checkbox" class="group-checkable icheck" data-id="{{obj.id}}">
  91 + </td>
  92 + <td>
  93 + {{obj.lineCode}}
  94 + </td>
  95 + <td>
  96 + {{obj.name}}
  97 + </td>
  98 + <td>
  99 + {{obj.carSumNumber}}
  100 + </td>
  101 + <td>
  102 + {{obj.carParkCode}}
  103 + </td>
  104 + <td>
  105 + {{obj.startStationName}}
  106 + </td>
  107 + <td>
  108 + {{obj.endStationName}}
  109 + </td>
  110 + <td>
  111 + {{obj.company}}
  112 + </td>
  113 + <td>
  114 + {{obj.brancheCompany}}
  115 + </td>
  116 + <td>
  117 + {{obj.destroy}}
  118 + </td>
  119 + <td>
  120 + <a href="edit.html?no={{obj.id}}" class="btn default blue-stripe btn-sm" data-pjax> 详细 </a>
  121 + </td>
  122 + </tr>
  123 + {{/each}}
  124 + {{if list.length == 0}}
  125 + <tr>
  126 + <td colspan=8><h6 class="muted">没有找到相关数据</h6></td>
  127 + </tr>
  128 + {{/if}}
  129 +</script>
  130 +<script src="/pages/base/line/js/list.js"></script>
0 131 \ No newline at end of file
... ...
src/main/resources/static/pages/base/stationroute/css/bmap_base.css 0 → 100644
  1 +#bmap_basic{
  2 + min-width: 100%;
  3 + width: calc(100% + 26px);
  4 + margin-top: -28px;
  5 + border: 2px solid #fdfdfd;
  6 + height:800px;
  7 + overflow: hidden;
  8 +}
  9 +
  10 +body{
  11 + overflow:hidden;
  12 +}
  13 +
  14 +/* 隐藏百度地图logo */
  15 +.anchorBL,
  16 +.anchorBL,
  17 +.amap-logo,
  18 +.amap-copyright{
  19 + display: none;
  20 +}
0 21 \ No newline at end of file
... ...
src/main/resources/static/pages/base/stationroute/css/img/load_slow.gif 0 → 100644

3.42 KB

src/main/resources/static/pages/base/stationroute/js/stationroute-list-map.js 0 → 100644
  1 +var WorldsBMap = function () {
  2 +
  3 + function getBmapStationNames(lineNameValue,i,callback) {
  4 +
  5 + var busline = new BMap.BusLineSearch(map,{
  6 +
  7 + // 搜索结果呈现的配置
  8 + renderOptions:{map:map},
  9 +
  10 + // 设置公交列表查询后的回调函数。参数:rs: BusListResult类型
  11 + onGetBusListComplete:function(BusListResult) {
  12 +
  13 + // 如果不为空
  14 + if(BusListResult){
  15 +
  16 + //获取第一个公交列表显示到map上
  17 + var fstLine = BusListResult.getBusListItem(i);
  18 +
  19 + busline.getBusLine(fstLine);
  20 +
  21 + }
  22 +
  23 + },
  24 +
  25 + // 设置公交列表查询后的回调函数。参数:rs: BusListResult类型
  26 + onGetBusListComplete:function(BusListResult) {
  27 +
  28 + // 如果不为空
  29 + if(BusListResult){
  30 +
  31 + //获取第一个公交列表显示到map上
  32 + var fstLine = BusListResult.getBusListItem(i);
  33 +
  34 + busline.getBusLine(fstLine);
  35 +
  36 + }
  37 +
  38 + },
  39 +
  40 + //设置公交线路查询后的回调函数.参数:rs: BusLine类型
  41 + onGetBusLineComplete: function(BusLine){
  42 +
  43 + // 如果不为空
  44 + if(BusLine){
  45 +
  46 + callback && callback(BusLine);
  47 +
  48 + }
  49 +
  50 + }
  51 +
  52 + });
  53 +
  54 + busline.getBusList(lineNameValue);
  55 +
  56 + }
  57 +
  58 + var Bmap = {
  59 +
  60 + init : function() {
  61 +
  62 + // 关闭左侧栏
  63 + if (!$('body').hasClass('page-sidebar-closed')) {
  64 +
  65 + $('.menu-toggler.sidebar-toggler').click();
  66 +
  67 + }
  68 +
  69 + // 设置中心点,
  70 + var CENTER_POINT = {lng : 121.528733,lat : 31.237425};
  71 +
  72 + // 百度API Key
  73 + var bdKey = 'IGGrr4UjwIYzatoCRFKEL8sT';
  74 +
  75 + // 初始化百度地图
  76 + map = new BMap.Map("bmap_basic");
  77 +
  78 + //中心点和缩放级别
  79 + map.centerAndZoom(new BMap.Point(CENTER_POINT.lng,CENTER_POINT.lat), 13);
  80 +
  81 + map.enableScrollWheelZoom();
  82 +
  83 + },
  84 +
  85 + // 地图划出线路走向
  86 + lineInfoPanl : function(lineNameValue,i,cb) {
  87 +
  88 + getBmapStationNames(lineNameValue,i,function(BusLine){
  89 +
  90 + return cb && cb(BusLine);
  91 +
  92 + });
  93 +
  94 + }
  95 +
  96 + }
  97 +
  98 + return Bmap;
  99 +
  100 +}();
0 101 \ No newline at end of file
... ...
src/main/resources/static/pages/base/stationroute/js/stationroute-list-table.js 0 → 100644
  1 +$(function(){
  2 +
  3 + // 获取参数ID
  4 + //var id = $.url().param('lineId');
  5 +
  6 + var id= '972';
  7 +
  8 + function getIdLineName(id,callback) {
  9 +
  10 + $get('/line/' + id ,null, function(result){
  11 +
  12 + callback && callback(result);
  13 +
  14 + });
  15 +
  16 + }
  17 +
  18 + /**
  19 + *
  20 + * 百度站点坐标获取WGS坐标
  21 + *
  22 + * - - - - - - - - - - 》 站点坐标转换WGS坐标
  23 + *
  24 + */
  25 + function BpointsToWGS(points,callback) {
  26 +
  27 + var resultPoints = [];
  28 +
  29 + if(points) {
  30 +
  31 + // 获取长度
  32 + var len = points.length;
  33 +
  34 + (function(){
  35 +
  36 + if (!arguments.callee.count) {
  37 +
  38 + arguments.callee.count = 0;
  39 +
  40 + }
  41 +
  42 + arguments.callee.count++;
  43 +
  44 + var index = parseInt(arguments.callee.count) - 1;
  45 +
  46 + if (index >= len) {
  47 +
  48 + callback && callback(resultPoints);
  49 +
  50 + return;
  51 + }
  52 +
  53 + var f = arguments.callee;
  54 +
  55 + $.ajax({
  56 +
  57 + // 百度坐标获取WGS坐标
  58 + url: 'http://api.zdoz.net/bd2wgs.aspx',
  59 +
  60 + data: {lat: points[index].potion.lat , lng: points[index].potion.lng},
  61 +
  62 + dataType: 'jsonp',
  63 +
  64 + success: function(r){
  65 +
  66 + if(r) {
  67 +
  68 + var tempP = {};
  69 +
  70 + tempP.name = points[index].name;
  71 +
  72 + tempP.potion = r;
  73 +
  74 + resultPoints.push(tempP);
  75 +
  76 + }
  77 +
  78 + f();
  79 + }
  80 + });
  81 +
  82 + })();
  83 +
  84 + }else {
  85 +
  86 + callback && callback(false);
  87 +
  88 + }
  89 +
  90 + }
  91 +
  92 + /**
  93 + *
  94 + * 百度坐标获取WGS坐标
  95 + *
  96 + * - - - - - - - - 》百度图形坐标转换成WGS坐标
  97 + *
  98 + */
  99 + function BpolyGonArrayToWGS(polyGonArray,callback) {
  100 +
  101 + var resultpolyGonArray = [];
  102 +
  103 + if(polyGonArray) {
  104 +
  105 + // 获取长度
  106 + var len = polyGonArray.length;
  107 +
  108 + (function(){
  109 +
  110 + if (!arguments.callee.count) {
  111 +
  112 + arguments.callee.count = 0;
  113 +
  114 + }
  115 +
  116 + arguments.callee.count++;
  117 +
  118 + var index = parseInt(arguments.callee.count) - 1;
  119 +
  120 + if (index >= len) {
  121 +
  122 + callback && callback(resultpolyGonArray);
  123 +
  124 + return;
  125 + }
  126 +
  127 + var f = arguments.callee;
  128 +
  129 + $.ajax({
  130 +
  131 + // 百度坐标获取WGS坐标
  132 + url: 'http://api.zdoz.net/bd2wgs.aspx',
  133 +
  134 + data: {lat: polyGonArray[index].lat , lng: polyGonArray[index].lng},
  135 +
  136 + dataType: 'jsonp',
  137 +
  138 + success: function(r){
  139 +
  140 + if(r) {
  141 +
  142 + resultpolyGonArray[index] = r;
  143 +
  144 + }
  145 +
  146 + f();
  147 + }
  148 + });
  149 +
  150 + })();
  151 +
  152 + }else {
  153 +
  154 + callback && callback(false);
  155 +
  156 + }
  157 +
  158 + }
  159 +
  160 + if(id) {
  161 +
  162 + // 定义地图
  163 + var map;
  164 +
  165 + // 初始化地图和表格
  166 + setTimeout(function(){
  167 +
  168 + // 地图初始化
  169 + WorldsBMap.init();
  170 +
  171 + // 表格初始化
  172 + TableDatatablesEditable.init(id);
  173 +
  174 + },500);
  175 +
  176 +
  177 + // 系统规划点击事件
  178 + $('.system').on('click',function() {
  179 +
  180 + // 获取方向 (0:上行;1:下行)
  181 + var directionData = $('.system').data('direction');
  182 +
  183 + // 隐藏表格
  184 + $('#show_table').hide();
  185 +
  186 + // 弹出正在加载层
  187 + var i = layer.load(0,{offset:'200px'});
  188 +
  189 + // 根据线路ID获取线路名称
  190 + getIdLineName(id,function(data) {
  191 +
  192 + // 定义线路名称
  193 + var lineNameV = data.name;
  194 +
  195 + // 如果不为空
  196 + if(lineNameV) {
  197 +
  198 + // 从百度地图获取线路信息
  199 + WorldsBMap.lineInfoPanl(lineNameV,directionData,function(BusLine){
  200 +
  201 + // 如果线路信息不为空
  202 + if(BusLine) {
  203 +
  204 + // 获取公交线几何对象, 仅当结果自动添加到地图上时有效
  205 + var Polygon = BusLine.getPolyline();
  206 +
  207 + // 返回多边型的点数组(自1.2新增)
  208 + var polyGonArray = Polygon.getPath();
  209 +
  210 + // 获取公交站点个数(自 1.2 新增)
  211 + var stationNumber = BusLine.getNumBusStations();
  212 +
  213 + // 定义线路信息集合
  214 + var stationInfo = [];
  215 +
  216 + // 遍历
  217 + for(var k = 0 ; k < stationNumber; k++) {
  218 +
  219 + // 定义线路信息集合
  220 + var tempM = {};
  221 +
  222 + // 添加站点名称
  223 + tempM.name = BusLine.getBusStation(k).name;
  224 +
  225 + // 添加站点坐标
  226 + tempM.potion = BusLine.getBusStation(k).position;
  227 +
  228 + // 添加
  229 + stationInfo.push(tempM);
  230 +
  231 + };
  232 +
  233 + // 百度站点坐标获取WGS坐标
  234 + BpointsToWGS(stationInfo,function(result){
  235 +
  236 + if(result) {
  237 +
  238 + // 百度图形坐标转换成WGS坐标
  239 + BpolyGonArrayToWGS(polyGonArray,function(arraydata) {
  240 +
  241 + console.log(arraydata);
  242 +
  243 + });
  244 +
  245 + }
  246 +
  247 + });
  248 + }
  249 +
  250 + });
  251 +
  252 + }
  253 +
  254 + });
  255 +
  256 + });
  257 +
  258 + }else {
  259 +
  260 + // 缺少ID
  261 + layer.confirm('【ID缺失,请点击返回,重新进行操作】', {btn : [ '返回' ],icon: 3, title:'提示' }, function(index){
  262 +
  263 + layer.close(index);
  264 +
  265 + loadPage('/pages/base/line/list.html');
  266 +
  267 + });
  268 +
  269 + }
  270 +
  271 +});
0 272 \ No newline at end of file
... ...
src/main/resources/static/pages/base/stationroute/js/table-datatables-editable.js 0 → 100644
  1 +var TableDatatablesEditable = function () {
  2 +
  3 + var handleTable = function (id) {
  4 +
  5 + // 获取表格元素
  6 + var table = $('#station_list_table');
  7 +
  8 + // Jquery Table
  9 + var oTable = table.on('xhr.dt', function ( e, settings, json, xhr ) {
  10 +
  11 + var dataLen = json.content.length;
  12 +
  13 + if(dataLen>0) {
  14 +
  15 + $('#hide_table').show();
  16 +
  17 + $('#show_table').hide();
  18 +
  19 + }
  20 +
  21 + }).dataTable({
  22 +
  23 + //异步查询,在服务端对数据处理,前端统一显示
  24 + serverSide: true,
  25 +
  26 + //是否打开客户端状态记录功能,此功能在ajax刷新纪录的时候不会将个性化设定回复为初始化状态
  27 + 'bStateSave' : true,
  28 +
  29 + //异步查询,是否显示“正在处理”这个提示信息
  30 + processing: true,
  31 +
  32 + //是否开启垂直滚动,以及指定滚动区域大小
  33 + 'sScrollY': '60%',
  34 +
  35 + //是否开启水平滚动,以及指定滚动区域大小
  36 + 'sScrollX': '100%',
  37 +
  38 + //水平滚动
  39 + "sScrollXInner": "100%",
  40 +
  41 + // 从服务端获取数据
  42 + ajax: {
  43 +
  44 + //ajax请求URL路径
  45 + url:'/stationroute',
  46 +
  47 + // 填充表格的数据集合
  48 + dataSrc:'content',
  49 +
  50 + //请求方式
  51 + type:'GET',
  52 +
  53 + //发送到服务器的数据
  54 + data: function(d){
  55 +
  56 + //处理和后台接口的参数
  57 + d.page = d.start / d.length;//页号 从0开始
  58 + d.size = d.length;
  59 +
  60 + //删掉目前业务不需要的参数
  61 + delete d['draw'];
  62 +
  63 + //不需要默认搜索
  64 + delete d['search'];
  65 +
  66 + //目前后台查询所有字段
  67 + delete d['columns'];
  68 +
  69 + //不要排序
  70 + delete d['order'];
  71 +
  72 + //合并搜索条件
  73 + $.extend(d,{'line.id_eq':id});
  74 +
  75 + }
  76 + },
  77 +
  78 + // 自定义列
  79 + 'columns': [
  80 + {'data':null,'render': function(data, type, full) {return '<td style="width: 8%;"><label class="c-input c-checkbox"><input type="checkbox" value="'+data.id+'"><span class="c-indicator"></span></label></td>';}},
  81 + {'data': 'stationCode'},
  82 + {'data': 'stationName'},
  83 + {'data': 'directions' },
  84 + {'data': 'stationMark'}
  85 + ],
  86 +
  87 + //翻页功能
  88 + 'bPaginate': true,
  89 +
  90 + //改变每页显示数据数量
  91 + 'bLengthChange': false,
  92 +
  93 + //过滤功能
  94 + 'bFilter': false,
  95 +
  96 + //排序功能
  97 + 'bSort': false,
  98 +
  99 + //页脚信息
  100 + 'bInfo': true,
  101 +
  102 + //自动宽度
  103 + 'bAutoWidth': true,
  104 +
  105 + // 自定义语言
  106 + language: {url:'/pages/base/stationroute/js/table_language.json'},
  107 +
  108 + });
  109 +
  110 +
  111 + /**
  112 + *
  113 + * 新增事件
  114 + *
  115 + */
  116 + $('.add').on('click',function() {
  117 +
  118 + // 获取表格行数
  119 + var tabRowLen = $('#station_list_table >tbody >tr').length;
  120 +
  121 + // 获取选中行元素
  122 + var arrChk = $("input[type='checkbox']:checked");
  123 +
  124 + // 获取选中行个数
  125 + var checkLen = arrChk.length;
  126 +
  127 + /**
  128 + *
  129 + * 如果为零,提示请选择行...;
  130 + *
  131 + * 如果大于壹,提示不支持多选;
  132 + *
  133 + * 否则添加行。
  134 + */
  135 + if(checkLen == 0 && tabRowLen>0) {
  136 +
  137 + // 弹出框 (0:感叹号;1:对号;2:错号;3:问号;4:锁;5:苦脸;6:笑脸)
  138 + layer.confirm('【请选择行...】', {btn : [ '确定' ],icon: 0, title:'温馨提示'}, function(index) {
  139 +
  140 + // 关闭提示框
  141 + layer.close(index);
  142 +
  143 + });
  144 +
  145 + }else if(checkLen>1) {
  146 +
  147 + // 弹出框 (0:感叹号;1:对号;2:错号;3:问号;4:锁;5:苦脸;6:笑脸)
  148 + layer.confirm('【该功能不支持多选,请在添加指定站点位置勾选...】', {btn : [ '确定' ],icon: 0, title:'温馨提示'}, function(index) {
  149 +
  150 + // 关闭提示框
  151 + layer.close(index);
  152 +
  153 + });
  154 +
  155 + }else {
  156 +
  157 + // 定义html
  158 + var TabHtml = '<tr>'+
  159 + '<td><a class="save" href="javascript:;"> 保存 </a><a class="cancel" href="javascript:;"> 关闭 </a></td>'+
  160 + '<td><input type="text" class="form-control input-xsmall"></td>'+
  161 + '<td><input type="text" class="form-control input-xsmall"></td>'+
  162 + '<td><input type="text" class="form-control input-xsmall"></td>'+
  163 + '<td><input type="text" class="form-control input-xsmall"></td>'+
  164 + '</tr>';
  165 +
  166 + // 在选中行后添加html文本
  167 + $(arrChk).parents('tr').after(TabHtml);
  168 +
  169 + }
  170 +
  171 + })
  172 +
  173 + /**
  174 + *
  175 + * 修改
  176 + *
  177 + */
  178 + $('.edit').on('click',function(){
  179 +
  180 + // 获取复选框选中元素
  181 + var arrChk = $("input[type='checkbox']:checked");
  182 +
  183 + // 获取选中个数
  184 + var checkLen = arrChk.length;
  185 +
  186 + /**
  187 + *
  188 + * 如果为零,提示请选择行...;
  189 + *
  190 + * 如果大于壹,提示不支持多选;
  191 + *
  192 + * 否则编辑行。
  193 + */
  194 + if(checkLen == 0) {
  195 +
  196 + // 弹出提示框 icon参数(0:感叹号;1:对号;2:错号;3:问号;4:锁;5:苦脸;6:笑脸)
  197 + layer.confirm('【请选择行...】', {btn : [ '确定' ],icon: 0, title:'温馨提示'}, function(index) {
  198 +
  199 + // 关闭提示框
  200 + layer.close(index);
  201 +
  202 + });
  203 +
  204 + }else if(checkLen>1) {
  205 +
  206 + // 弹出提示框 icon参数(0:感叹号;1:对号;2:错号;3:问号;4:锁;5:苦脸;6:笑脸)
  207 + layer.confirm('【该功能不支持多选,请在需要修改的站点位置勾选...】', {btn : [ '确定' ],icon: 0, title:'温馨提示'}, function(index) {
  208 +
  209 + // 关闭提示框
  210 + layer.close(index);
  211 +
  212 + });
  213 +
  214 + }else {
  215 +
  216 + // 获取选中框元素
  217 + var trHtml = $(arrChk).parents('tr');
  218 +
  219 + // 编辑表格行
  220 + editRow(trHtml);
  221 +
  222 + }
  223 +
  224 + });
  225 +
  226 + // 编辑表格行
  227 + function editRow(trHtml) {
  228 +
  229 + // 获取选中行数据
  230 + var aData = oTable.fnGetData(trHtml);
  231 +
  232 + // 获取行数
  233 + var jqTds = $('>td', trHtml);
  234 +
  235 + // 重新设置行
  236 + jqTds[0].innerHTML = '<a class="save" href="javascript:;"> 保存 </a><a class="canceleditrow" href="javascript:;"> 关闭 </a>';
  237 +
  238 + jqTds[1].innerHTML = '<input type="text" class="form-control input-xsmall" value="' + aData.stationCode + '">';
  239 +
  240 + jqTds[2].innerHTML = '<input type="text" class="form-control input-xsmall" value="' + aData.stationName + '">';
  241 +
  242 + jqTds[3].innerHTML = '<input type="text" class="form-control input-xsmall" value="' + aData.directions + '">';
  243 +
  244 + jqTds[4].innerHTML = '<input type="text" class="form-control input-xsmall" value="' + aData.stationMark + '">';
  245 +
  246 + }
  247 +
  248 + /**
  249 + *
  250 + * 修改——》关闭事件
  251 + *
  252 + */
  253 + table.on('click','.canceleditrow',function(){
  254 +
  255 + // 获取修改行元素
  256 + var trHtml = $(this).parents('tr')
  257 +
  258 + // 编辑行
  259 + restoreRow(trHtml);
  260 +
  261 + });
  262 +
  263 + /**
  264 + *
  265 + * 修改——》行关闭事件
  266 + *
  267 + */
  268 + function restoreRow(nRow) {
  269 +
  270 + // 获取需改行数据
  271 + var aData = oTable.fnGetData(nRow);
  272 +
  273 + // 获取修改行td元素
  274 + var jqTds = $('>td', nRow);
  275 +
  276 + // 遍历
  277 + for (var i = 0, iLen = jqTds.length; i < iLen; i++) {
  278 +
  279 + // 更新行td元素
  280 + cellSwitch(aData,nRow,i);
  281 +
  282 + }
  283 +
  284 + }
  285 +
  286 + /**
  287 + *
  288 + * 修改——》更新行td元素
  289 + *
  290 + */
  291 + function cellSwitch(aData,nRow,i){
  292 +
  293 + /*
  294 + * 0:第一个td;1:第二个td...3:第四个td
  295 + *
  296 + */
  297 + switch(i){
  298 +
  299 + case 0:
  300 +
  301 + // 更新设置行
  302 + oTable.fnUpdate('<td style="width: 8%;"><label class="c-input c-checkbox"><input type="checkbox" value="'+aData.id+'"><span class="c-indicator"></span></label></td>', nRow, i, false);
  303 +
  304 + break;
  305 +
  306 + case 1:
  307 +
  308 + oTable.fnUpdate(aData.stationCode, nRow, i, false);
  309 +
  310 + break;
  311 +
  312 + case 2:
  313 +
  314 + oTable.fnUpdate(aData.stationName, nRow, i, false);
  315 +
  316 + break;
  317 +
  318 + case 3:
  319 +
  320 + oTable.fnUpdate(aData.directions, nRow, i, false);
  321 +
  322 + break;
  323 +
  324 + case 4:
  325 +
  326 + oTable.fnUpdate(aData.stationMark, nRow, i, false);
  327 +
  328 + break;
  329 +
  330 + default:
  331 +
  332 + oTable.fnUpdate(null, nRow, i, false);
  333 +
  334 + }
  335 + }
  336 +
  337 + /**
  338 + * 删除
  339 + *
  340 + */
  341 + $('.delete').on('click',function() {
  342 +
  343 + // 获取选中行
  344 + var arrChk = $("input[type='checkbox']:checked");
  345 +
  346 + // 选中行ID
  347 + var id = '';
  348 +
  349 + // 遍历选中行
  350 + $(arrChk).each(function(){
  351 +
  352 + id = this.value+";"+id;
  353 +
  354 + });
  355 +
  356 + // 弹出提示框 icon参数(0:感叹号;1:对号;2:错号;3:问号;4:锁;5:苦脸;6:笑脸)
  357 + layer.confirm('【确定删除...】', {btn : [ '确定','取消' ],icon: 2, title:'温馨提示'}, function(index) {
  358 +
  359 + // 删除选中行
  360 + $(arrChk).parents('tr').remove();
  361 +
  362 + // 关闭弹出提示框
  363 + layer.close(index);
  364 +
  365 + // 删除
  366 +
  367 + // 刷新表格数据,分页信息不会重置
  368 + //oTable.api().ajax.reload( null, false );
  369 + });
  370 +
  371 + });
  372 +
  373 + table.on('click','.save',function() {
  374 +
  375 + // 获取选中行
  376 + var nRow = $(this).parents('tr');
  377 +
  378 + // 获取选中行数据
  379 + var params = oTable.fnGetData(nRow);
  380 +
  381 + // 保存
  382 +
  383 + // 刷新表格数据,分页信息不会重置
  384 + //oTable.api().ajax.reload( null, false );
  385 +
  386 + });
  387 +
  388 + /**
  389 + * 新增——》关闭按钮事件
  390 + *
  391 + */
  392 + table.on('click', '.cancel', function () {
  393 +
  394 + // 关闭选中行
  395 + $(this).parents('tr').remove();
  396 +
  397 + });
  398 +
  399 + };
  400 +
  401 + return {
  402 +
  403 + // 初始化
  404 + init: function (id) {
  405 +
  406 + handleTable(id);
  407 +
  408 + }
  409 +
  410 + };
  411 +
  412 +}();
0 413 \ No newline at end of file
... ...
src/main/resources/static/pages/base/stationroute/js/table_language.json 0 → 100644
  1 +{"sLengthMenu" : "显示&nbsp;_MENU_&nbsp;条 ",
  2 +"sZeroRecords" : "没有您要搜索的内容",
  3 +"sInfo" : "<span class='help-block'>当前_START_ ~ _END_ 条 - 总记录数 _TOTAL_ 条</span>",
  4 +"sInfoEmpty" : "记录数为0",
  5 +"sInfoFiltered" : "(全部记录数 _MAX_ 条)",
  6 +"oPaginate" : {
  7 +"sFirst" : "第一页",
  8 +"sPrevious" : " 上一页 ",
  9 +"sNext" : " 下一页 ",
  10 +"sLast" : " 最后一页 "
  11 +}
  12 +}
0 13 \ No newline at end of file
... ...
src/main/resources/static/pages/base/stationroute/list.html 0 → 100644
  1 +<link href="/pages/base/stationroute/css/bmap_base.css" rel="stylesheet" type="text/css" />
  2 +<div class="portlet-body">
  3 + <div id="bmap_basic" class="bmaps"> </div>
  4 +
  5 + <div class="portlet box blue" style="position: absolute; top: 40px;margin-left: 10px;overflow: hidden;width: 1000px;height: 100%;background:transparent;border:0px solid;">
  6 + <div class="portlet-title" style="background-color:#3B3F51">
  7 + <div class="caption">
  8 + <i class="fa fa-gift"></i> 途径站点
  9 + </div>
  10 + <div class="tools">
  11 + <a href="javascript:;" class="collapse" data-original-title="" title=""> </a>
  12 + </div>
  13 + </div>
  14 + <div class="portlet-body" style="border: 1px solid rgb(255, 255, 255); display: block;">
  15 + <div class="row">
  16 + <div class="col-md-3 col-sm-3 col-xs-3">
  17 + <ul class="nav nav-tabs tabs-left">
  18 + <li class="active">
  19 + <a href="#tab_6_1" data-toggle="tab" aria-expanded="true"> 上行 </a>
  20 + </li>
  21 + <li class="">
  22 + <a href="#tab_6_2" data-toggle="tab" aria-expanded="false"> 下行 </a>
  23 + </li>
  24 + </ul>
  25 + </div>
  26 + <div class="col-md-9 col-sm-9 col-xs-9">
  27 + <div class="tab-content">
  28 + <div class="tab-pane active in" id="tab_6_1">
  29 + <div class="portlet-body" id="hide_table" style="display:none">
  30 + <div class="table-toolbar">
  31 + <div class="row">
  32 + <div class="col-md-6" style="float: right;">
  33 + <div class="btn-group" style="float: right;">
  34 + <div class="actions">
  35 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  36 + <a class="btn btn-circle blue add" href="javascript:;" style="background-color:#3B3F51;border-color:#FFFFFF" data-pjax><i class="fa fa-plus"></i> 新增</a>
  37 + </div>
  38 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  39 + <a class="btn btn-circle blue edit" href="javascript:;" style="background-color:#3B3F51;border-color:#FFFFFF" data-pjax><i class="fa fa-pencil"></i> 修改</a>
  40 + </div>
  41 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  42 + <a class="btn btn-circle blue delete" href="javascript:;" style="background-color:#3B3F51;border-color:#FFFFFF" data-pjax><i class="fa fa-close"></i> 删除</a>
  43 + </div>
  44 + </div>
  45 + </div>
  46 + </div>
  47 + </div>
  48 + </div>
  49 + <div id="sample_editable_1_wrapper" class="dataTables_wrapper no-footer">
  50 + <div class="table-scrollable" style="overflow: hidden;">
  51 + <!-- sample_editable_1_info -->
  52 + <table class="table table-striped table-hover table-bordered dataTable no-footer" id="station_list_table" role="grid" aria-describedby="sample_editable_1_info">
  53 + <thead>
  54 + <tr role="row">
  55 + <th tabindex="0" aria-controls="station_list_table" rowspan="1" colspan="1" style="width: 86px;"> #</th>
  56 + <th tabindex="0" aria-controls="station_list_table" rowspan="1" colspan="1" style="width: 120px;"> 站点编码 </th>
  57 + <th tabindex="0" aria-controls="station_list_table" rowspan="1" colspan="1" style="width: 120px;"> 站点名称 </th>
  58 + <th tabindex="0" aria-controls="station_list_table" rowspan="1" colspan="1" style="width: 116px;"> 站点方向 </th>
  59 + <th tabindex="0" aria-controls="station_list_table" rowspan="1" colspan="1" style="width: 122px;"> 站点类型 </th>
  60 + </tr>
  61 + </thead>
  62 + <tbody>
  63 + </tbody>
  64 + </table>
  65 + </div>
  66 + </div>
  67 + </div>
  68 + <div id="show_table" class="portlet-body">
  69 + <div class="col-md-6" style="float: right;">
  70 + <div class="btn-group" style="float: right;">
  71 + <div class="actions">
  72 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  73 + <a class="btn btn-circle blue system" href="javascript:;" style="background-color:#3B3F51;border-color:#FFFFFF" data-direction="0" data-pjax><i class="fa fa-wrench"></i> 系统规划</a>
  74 + </div>
  75 + <div class="btn-group btn-group-devided" data-toggle="buttons">
  76 + <a class="btn btn-circle blue manual" href="javascript:;" style="background-color:#3B3F51;border-color:#FFFFFF" data-direction="0" data-pjax><i class="fa fa-pencil"></i> 手动规划</a>
  77 + </div>
  78 + </div>
  79 + </div>
  80 + </div>
  81 +
  82 + <div class="col-md-6" style="float: right;">
  83 + <div class="btn-group" style="float: right;">
  84 + <!-- 提示 -->
  85 + <div class="alert alert-danger ">
  86 + <span class="help-block"> 请从右边选择任意一种方式规划线路上行站点 </span>
  87 + </div>
  88 + </div>
  89 + </div>
  90 +
  91 + </div>
  92 + </div>
  93 + <div class="tab-pane fade" id="tab_6_2"></div>
  94 + </div>
  95 + </div>
  96 + </div>
  97 + </div>
  98 + </div>
  99 +</div>
  100 +<script src="/pages/base/stationroute/js/stationroute-list-map.js"></script>
  101 +<script src="/pages/base/stationroute/js/table-datatables-editable.js"></script>
  102 +<script src="/pages/base/stationroute/js/stationroute-list-table.js"></script>
0 103 \ No newline at end of file
... ...