mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-09 20:52:56 +01:00
1 line
319 KiB
Plaintext
1 line
319 KiB
Plaintext
{"version":3,"sources":["jquery.tablesorter.combined.js","widget-grouping.min.js","widget-uitheme.min.js","widget-filter.min.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjtLA;AACA;ACDA;AACA;ACDA;AACA","file":"tablesorter.min.js","sourcesContent":["/*! tablesorter (FORK) - updated 01-28-2017 (v2.28.5)*/\n/* Includes widgets ( storage,uitheme,columns,filter,stickyHeaders,resizable,saveSort ) */\n(function(factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine(['jquery'], factory);\n\t} else if (typeof module === 'object' && typeof module.exports === 'object') {\n\t\tmodule.exports = factory(require('jquery'));\n\t} else {\n\t\tfactory(jQuery);\n\t}\n}(function(jQuery) {\n\n/*! TableSorter (FORK) v2.28.5 *//*\n* Client-side table sorting with ease!\n* @requires jQuery v1.2.6+\n*\n* Copyright (c) 2007 Christian Bach\n* fork maintained by Rob Garrison\n*\n* Examples and original docs at: http://tablesorter.com\n* Dual licensed under the MIT and GPL licenses:\n* http://www.opensource.org/licenses/mit-license.php\n* http://www.gnu.org/licenses/gpl.html\n*\n* @type jQuery\n* @name tablesorter (FORK)\n* @cat Plugins/Tablesorter\n* @author Christian Bach - christian.bach@polyester.se\n* @contributor Rob Garrison - https://github.com/Mottie/tablesorter\n* @docs (fork) - https://mottie.github.io/tablesorter/docs/\n*/\n/*jshint browser:true, jquery:true, unused:false, expr: true */\n;( function( $ ) {\n\t'use strict';\n\tvar ts = $.tablesorter = {\n\n\t\tversion : '2.28.5',\n\n\t\tparsers : [],\n\t\twidgets : [],\n\t\tdefaults : {\n\n\t\t\t// *** appearance\n\t\t\ttheme : 'default', // adds tablesorter-{theme} to the table for styling\n\t\t\twidthFixed : false, // adds colgroup to fix widths of columns\n\t\t\tshowProcessing : false, // show an indeterminate timer icon in the header when the table is sorted or filtered.\n\n\t\t\theaderTemplate : '{content}',// header layout template (HTML ok); {content} = innerHTML, {icon} = <i/> // class from cssIcon\n\t\t\tonRenderTemplate : null, // function( index, template ){ return template; }, // template is a string\n\t\t\tonRenderHeader : null, // function( index ){}, // nothing to return\n\n\t\t\t// *** functionality\n\t\t\tcancelSelection : true, // prevent text selection in the header\n\t\t\ttabIndex : true, // add tabindex to header for keyboard accessibility\n\t\t\tdateFormat : 'mmddyyyy', // other options: 'ddmmyyy' or 'yyyymmdd'\n\t\t\tsortMultiSortKey : 'shiftKey', // key used to select additional columns\n\t\t\tsortResetKey : 'ctrlKey', // key used to remove sorting on a column\n\t\t\tusNumberFormat : true, // false for German '1.234.567,89' or French '1 234 567,89'\n\t\t\tdelayInit : false, // if false, the parsed table contents will not update until the first sort\n\t\t\tserverSideSorting: false, // if true, server-side sorting should be performed because client-side sorting will be disabled, but the ui and events will still be used.\n\t\t\tresort : true, // default setting to trigger a resort after an 'update', 'addRows', 'updateCell', etc has completed\n\n\t\t\t// *** sort options\n\t\t\theaders : {}, // set sorter, string, empty, locked order, sortInitialOrder, filter, etc.\n\t\t\tignoreCase : true, // ignore case while sorting\n\t\t\tsortForce : null, // column(s) first sorted; always applied\n\t\t\tsortList : [], // Initial sort order; applied initially; updated when manually sorted\n\t\t\tsortAppend : null, // column(s) sorted last; always applied\n\t\t\tsortStable : false, // when sorting two rows with exactly the same content, the original sort order is maintained\n\n\t\t\tsortInitialOrder : 'asc', // sort direction on first click\n\t\t\tsortLocaleCompare: false, // replace equivalent character (accented characters)\n\t\t\tsortReset : false, // third click on the header will reset column to default - unsorted\n\t\t\tsortRestart : false, // restart sort to 'sortInitialOrder' when clicking on previously unsorted columns\n\n\t\t\temptyTo : 'bottom', // sort empty cell to bottom, top, none, zero, emptyMax, emptyMin\n\t\t\tstringTo : 'max', // sort strings in numerical column as max, min, top, bottom, zero\n\t\t\tduplicateSpan : true, // colspan cells in the tbody will have duplicated content in the cache for each spanned column\n\t\t\ttextExtraction : 'basic', // text extraction method/function - function( node, table, cellIndex ){}\n\t\t\ttextAttribute : 'data-text',// data-attribute that contains alternate cell text (used in default textExtraction function)\n\t\t\ttextSorter : null, // choose overall or specific column sorter function( a, b, direction, table, columnIndex ) [alt: ts.sortText]\n\t\t\tnumberSorter : null, // choose overall numeric sorter function( a, b, direction, maxColumnValue )\n\n\t\t\t// *** widget options\n\t\t\tinitWidgets : true, // apply widgets on tablesorter initialization\n\t\t\twidgetClass : 'widget-{name}', // table class name template to match to include a widget\n\t\t\twidgets : [], // method to add widgets, e.g. widgets: ['zebra']\n\t\t\twidgetOptions : {\n\t\t\t\tzebra : [ 'even', 'odd' ] // zebra widget alternating row class names\n\t\t\t},\n\n\t\t\t// *** callbacks\n\t\t\tinitialized : null, // function( table ){},\n\n\t\t\t// *** extra css class names\n\t\t\ttableClass : '',\n\t\t\tcssAsc : '',\n\t\t\tcssDesc : '',\n\t\t\tcssNone : '',\n\t\t\tcssHeader : '',\n\t\t\tcssHeaderRow : '',\n\t\t\tcssProcessing : '', // processing icon applied to header during sort/filter\n\n\t\t\tcssChildRow : 'tablesorter-childRow', // class name indiciating that a row is to be attached to its parent\n\t\t\tcssInfoBlock : 'tablesorter-infoOnly', // don't sort tbody with this class name (only one class name allowed here!)\n\t\t\tcssNoSort : 'tablesorter-noSort', // class name added to element inside header; clicking on it won't cause a sort\n\t\t\tcssIgnoreRow : 'tablesorter-ignoreRow',// header row to ignore; cells within this row will not be added to c.$headers\n\n\t\t\tcssIcon : 'tablesorter-icon', // if this class does not exist, the {icon} will not be added from the headerTemplate\n\t\t\tcssIconNone : '', // class name added to the icon when there is no column sort\n\t\t\tcssIconAsc : '', // class name added to the icon when the column has an ascending sort\n\t\t\tcssIconDesc : '', // class name added to the icon when the column has a descending sort\n\n\t\t\t// *** events\n\t\t\tpointerClick : 'click',\n\t\t\tpointerDown : 'mousedown',\n\t\t\tpointerUp : 'mouseup',\n\n\t\t\t// *** selectors\n\t\t\tselectorHeaders : '> thead th, > thead td',\n\t\t\tselectorSort : 'th, td', // jQuery selector of content within selectorHeaders that is clickable to trigger a sort\n\t\t\tselectorRemove : '.remove-me',\n\n\t\t\t// *** advanced\n\t\t\tdebug : false,\n\n\t\t\t// *** Internal variables\n\t\t\theaderList: [],\n\t\t\tempties: {},\n\t\t\tstrings: {},\n\t\t\tparsers: [],\n\n\t\t\t// *** parser options for validator; values must be falsy!\n\t\t\tglobalize: 0,\n\t\t\timgAttr: 0\n\n\t\t\t// removed: widgetZebra: { css: ['even', 'odd'] }\n\n\t\t},\n\n\t\t// internal css classes - these will ALWAYS be added to\n\t\t// the table and MUST only contain one class name - fixes #381\n\t\tcss : {\n\t\t\ttable : 'tablesorter',\n\t\t\tcssHasChild: 'tablesorter-hasChildRow',\n\t\t\tchildRow : 'tablesorter-childRow',\n\t\t\tcolgroup : 'tablesorter-colgroup',\n\t\t\theader : 'tablesorter-header',\n\t\t\theaderRow : 'tablesorter-headerRow',\n\t\t\theaderIn : 'tablesorter-header-inner',\n\t\t\ticon : 'tablesorter-icon',\n\t\t\tprocessing : 'tablesorter-processing',\n\t\t\tsortAsc : 'tablesorter-headerAsc',\n\t\t\tsortDesc : 'tablesorter-headerDesc',\n\t\t\tsortNone : 'tablesorter-headerUnSorted'\n\t\t},\n\n\t\t// labels applied to sortable headers for accessibility (aria) support\n\t\tlanguage : {\n\t\t\tsortAsc : 'Ascending sort applied, ',\n\t\t\tsortDesc : 'Descending sort applied, ',\n\t\t\tsortNone : 'No sort applied, ',\n\t\t\tsortDisabled : 'sorting is disabled',\n\t\t\tnextAsc : 'activate to apply an ascending sort',\n\t\t\tnextDesc : 'activate to apply a descending sort',\n\t\t\tnextNone : 'activate to remove the sort'\n\t\t},\n\n\t\tregex : {\n\t\t\ttemplateContent : /\\{content\\}/g,\n\t\t\ttemplateIcon : /\\{icon\\}/g,\n\t\t\ttemplateName : /\\{name\\}/i,\n\t\t\tspaces : /\\s+/g,\n\t\t\tnonWord : /\\W/g,\n\t\t\tformElements : /(input|select|button|textarea)/i,\n\n\t\t\t// *** sort functions ***\n\t\t\t// regex used in natural sort\n\t\t\t// chunk/tokenize numbers & letters\n\t\t\tchunk : /(^([+\\-]?(?:\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?)?$|^0x[0-9a-f]+$|\\d+)/gi,\n\t\t\t// replace chunks @ ends\n\t\t\tchunks : /(^\\\\0|\\\\0$)/,\n\t\t\thex : /^0x[0-9a-f]+$/i,\n\n\t\t\t// *** formatFloat ***\n\t\t\tcomma : /,/g,\n\t\t\tdigitNonUS : /[\\s|\\.]/g,\n\t\t\tdigitNegativeTest : /^\\s*\\([.\\d]+\\)/,\n\t\t\tdigitNegativeReplace : /^\\s*\\(([.\\d]+)\\)/,\n\n\t\t\t// *** isDigit ***\n\t\t\tdigitTest : /^[\\-+(]?\\d+[)]?$/,\n\t\t\tdigitReplace : /[,.'\"\\s]/g\n\n\t\t},\n\n\t\t// digit sort, text location\n\t\tstring : {\n\t\t\tmax : 1,\n\t\t\tmin : -1,\n\t\t\temptymin : 1,\n\t\t\temptymax : -1,\n\t\t\tzero : 0,\n\t\t\tnone : 0,\n\t\t\t'null' : 0,\n\t\t\ttop : true,\n\t\t\tbottom : false\n\t\t},\n\n\t\tkeyCodes : {\n\t\t\tenter : 13\n\t\t},\n\n\t\t// placeholder date parser data (globalize)\n\t\tdates : {},\n\n\t\t// These methods can be applied on table.config instance\n\t\tinstanceMethods : {},\n\n\t\t/*\n\t\t▄█████ ██████ ██████ ██ ██ █████▄\n\t\t▀█▄ ██▄▄ ██ ██ ██ ██▄▄██\n\t\t ▀█▄ ██▀▀ ██ ██ ██ ██▀▀▀\n\t\t█████▀ ██████ ██ ▀████▀ ██\n\t\t*/\n\n\t\tsetup : function( table, c ) {\n\t\t\t// if no thead or tbody, or tablesorter is already present, quit\n\t\t\tif ( !table || !table.tHead || table.tBodies.length === 0 || table.hasInitialized === true ) {\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tif ( table.hasInitialized ) {\n\t\t\t\t\t\tconsole.warn( 'Stopping initialization. Tablesorter has already been initialized' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.error( 'Stopping initialization! No table, thead or tbody', table );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar tmp = '',\n\t\t\t\t$table = $( table ),\n\t\t\t\tmeta = $.metadata;\n\t\t\t// initialization flag\n\t\t\ttable.hasInitialized = false;\n\t\t\t// table is being processed flag\n\t\t\ttable.isProcessing = true;\n\t\t\t// make sure to store the config object\n\t\t\ttable.config = c;\n\t\t\t// save the settings where they read\n\t\t\t$.data( table, 'tablesorter', c );\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole[ console.group ? 'group' : 'log' ]( 'Initializing tablesorter v' + ts.version );\n\t\t\t\t$.data( table, 'startoveralltimer', new Date() );\n\t\t\t}\n\n\t\t\t// removing this in version 3 (only supports jQuery 1.7+)\n\t\t\tc.supportsDataObject = ( function( version ) {\n\t\t\t\tversion[ 0 ] = parseInt( version[ 0 ], 10 );\n\t\t\t\treturn ( version[ 0 ] > 1 ) || ( version[ 0 ] === 1 && parseInt( version[ 1 ], 10 ) >= 4 );\n\t\t\t})( $.fn.jquery.split( '.' ) );\n\t\t\t// ensure case insensitivity\n\t\t\tc.emptyTo = c.emptyTo.toLowerCase();\n\t\t\tc.stringTo = c.stringTo.toLowerCase();\n\t\t\tc.last = { sortList : [], clickedIndex : -1 };\n\t\t\t// add table theme class only if there isn't already one there\n\t\t\tif ( !/tablesorter\\-/.test( $table.attr( 'class' ) ) ) {\n\t\t\t\ttmp = ( c.theme !== '' ? ' tablesorter-' + c.theme : '' );\n\t\t\t}\n\t\t\tc.table = table;\n\t\t\tc.$table = $table\n\t\t\t\t.addClass( ts.css.table + ' ' + c.tableClass + tmp )\n\t\t\t\t.attr( 'role', 'grid' );\n\t\t\tc.$headers = $table.find( c.selectorHeaders );\n\n\t\t\t// give the table a unique id, which will be used in namespace binding\n\t\t\tif ( !c.namespace ) {\n\t\t\t\tc.namespace = '.tablesorter' + Math.random().toString( 16 ).slice( 2 );\n\t\t\t} else {\n\t\t\t\t// make sure namespace starts with a period & doesn't have weird characters\n\t\t\t\tc.namespace = '.' + c.namespace.replace( ts.regex.nonWord, '' );\n\t\t\t}\n\n\t\t\tc.$table.children().children( 'tr' ).attr( 'role', 'row' );\n\t\t\tc.$tbodies = $table.children( 'tbody:not(.' + c.cssInfoBlock + ')' ).attr({\n\t\t\t\t'aria-live' : 'polite',\n\t\t\t\t'aria-relevant' : 'all'\n\t\t\t});\n\t\t\tif ( c.$table.children( 'caption' ).length ) {\n\t\t\t\ttmp = c.$table.children( 'caption' )[ 0 ];\n\t\t\t\tif ( !tmp.id ) { tmp.id = c.namespace.slice( 1 ) + 'caption'; }\n\t\t\t\tc.$table.attr( 'aria-labelledby', tmp.id );\n\t\t\t}\n\t\t\tc.widgetInit = {}; // keep a list of initialized widgets\n\t\t\t// change textExtraction via data-attribute\n\t\t\tc.textExtraction = c.$table.attr( 'data-text-extraction' ) || c.textExtraction || 'basic';\n\t\t\t// build headers\n\t\t\tts.buildHeaders( c );\n\t\t\t// fixate columns if the users supplies the fixedWidth option\n\t\t\t// do this after theme has been applied\n\t\t\tts.fixColumnWidth( table );\n\t\t\t// add widgets from class name\n\t\t\tts.addWidgetFromClass( table );\n\t\t\t// add widget options before parsing (e.g. grouping widget has parser settings)\n\t\t\tts.applyWidgetOptions( table );\n\t\t\t// try to auto detect column type, and store in tables config\n\t\t\tts.setupParsers( c );\n\t\t\t// start total row count at zero\n\t\t\tc.totalRows = 0;\n\t\t\tts.validateOptions( c );\n\t\t\t// build the cache for the tbody cells\n\t\t\t// delayInit will delay building the cache until the user starts a sort\n\t\t\tif ( !c.delayInit ) { ts.buildCache( c ); }\n\t\t\t// bind all header events and methods\n\t\t\tts.bindEvents( table, c.$headers, true );\n\t\t\tts.bindMethods( c );\n\t\t\t// get sort list from jQuery data or metadata\n\t\t\t// in jQuery < 1.4, an error occurs when calling $table.data()\n\t\t\tif ( c.supportsDataObject && typeof $table.data().sortlist !== 'undefined' ) {\n\t\t\t\tc.sortList = $table.data().sortlist;\n\t\t\t} else if ( meta && ( $table.metadata() && $table.metadata().sortlist ) ) {\n\t\t\t\tc.sortList = $table.metadata().sortlist;\n\t\t\t}\n\t\t\t// apply widget init code\n\t\t\tts.applyWidget( table, true );\n\t\t\t// if user has supplied a sort list to constructor\n\t\t\tif ( c.sortList.length > 0 ) {\n\t\t\t\tts.sortOn( c, c.sortList, {}, !c.initWidgets );\n\t\t\t} else {\n\t\t\t\tts.setHeadersCss( c );\n\t\t\t\tif ( c.initWidgets ) {\n\t\t\t\t\t// apply widget format\n\t\t\t\t\tts.applyWidget( table, false );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// show processesing icon\n\t\t\tif ( c.showProcessing ) {\n\t\t\t\t$table\n\t\t\t\t.unbind( 'sortBegin' + c.namespace + ' sortEnd' + c.namespace )\n\t\t\t\t.bind( 'sortBegin' + c.namespace + ' sortEnd' + c.namespace, function( e ) {\n\t\t\t\t\tclearTimeout( c.timerProcessing );\n\t\t\t\t\tts.isProcessing( table );\n\t\t\t\t\tif ( e.type === 'sortBegin' ) {\n\t\t\t\t\t\tc.timerProcessing = setTimeout( function() {\n\t\t\t\t\t\t\tts.isProcessing( table, true );\n\t\t\t\t\t\t}, 500 );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// initialized\n\t\t\ttable.hasInitialized = true;\n\t\t\ttable.isProcessing = false;\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole.log( 'Overall initialization time:' + ts.benchmark( $.data( table, 'startoveralltimer' ) ) );\n\t\t\t\tif ( c.debug && console.groupEnd ) { console.groupEnd(); }\n\t\t\t}\n\t\t\t$table.triggerHandler( 'tablesorter-initialized', table );\n\t\t\tif ( typeof c.initialized === 'function' ) {\n\t\t\t\tc.initialized( table );\n\t\t\t}\n\t\t},\n\n\t\tbindMethods : function( c ) {\n\t\t\tvar $table = c.$table,\n\t\t\t\tnamespace = c.namespace,\n\t\t\t\tevents = ( 'sortReset update updateRows updateAll updateHeaders addRows updateCell updateComplete ' +\n\t\t\t\t\t'sorton appendCache updateCache applyWidgetId applyWidgets refreshWidgets destroy mouseup ' +\n\t\t\t\t\t'mouseleave ' ).split( ' ' )\n\t\t\t\t\t.join( namespace + ' ' );\n\t\t\t// apply easy methods that trigger bound events\n\t\t\t$table\n\t\t\t.unbind( events.replace( ts.regex.spaces, ' ' ) )\n\t\t\t.bind( 'sortReset' + namespace, function( e, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\t// using this.config to ensure functions are getting a non-cached version of the config\n\t\t\t\tts.sortReset( this.config, callback );\n\t\t\t})\n\t\t\t.bind( 'updateAll' + namespace, function( e, resort, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.updateAll( this.config, resort, callback );\n\t\t\t})\n\t\t\t.bind( 'update' + namespace + ' updateRows' + namespace, function( e, resort, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.update( this.config, resort, callback );\n\t\t\t})\n\t\t\t.bind( 'updateHeaders' + namespace, function( e, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.updateHeaders( this.config, callback );\n\t\t\t})\n\t\t\t.bind( 'updateCell' + namespace, function( e, cell, resort, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.updateCell( this.config, cell, resort, callback );\n\t\t\t})\n\t\t\t.bind( 'addRows' + namespace, function( e, $row, resort, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.addRows( this.config, $row, resort, callback );\n\t\t\t})\n\t\t\t.bind( 'updateComplete' + namespace, function() {\n\t\t\t\tthis.isUpdating = false;\n\t\t\t})\n\t\t\t.bind( 'sorton' + namespace, function( e, list, callback, init ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.sortOn( this.config, list, callback, init );\n\t\t\t})\n\t\t\t.bind( 'appendCache' + namespace, function( e, callback, init ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.appendCache( this.config, init );\n\t\t\t\tif ( $.isFunction( callback ) ) {\n\t\t\t\t\tcallback( this );\n\t\t\t\t}\n\t\t\t})\n\t\t\t// $tbodies variable is used by the tbody sorting widget\n\t\t\t.bind( 'updateCache' + namespace, function( e, callback, $tbodies ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.updateCache( this.config, callback, $tbodies );\n\t\t\t})\n\t\t\t.bind( 'applyWidgetId' + namespace, function( e, id ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.applyWidgetId( this, id );\n\t\t\t})\n\t\t\t.bind( 'applyWidgets' + namespace, function( e, init ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\t// apply widgets\n\t\t\t\tts.applyWidget( this, init );\n\t\t\t})\n\t\t\t.bind( 'refreshWidgets' + namespace, function( e, all, dontapply ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.refreshWidgets( this, all, dontapply );\n\t\t\t})\n\t\t\t.bind( 'removeWidget' + namespace, function( e, name, refreshing ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.removeWidget( this, name, refreshing );\n\t\t\t})\n\t\t\t.bind( 'destroy' + namespace, function( e, removeClasses, callback ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\tts.destroy( this, removeClasses, callback );\n\t\t\t})\n\t\t\t.bind( 'resetToLoadState' + namespace, function( e ) {\n\t\t\t\te.stopPropagation();\n\t\t\t\t// remove all widgets\n\t\t\t\tts.removeWidget( this, true, false );\n\t\t\t\tvar tmp = $.extend( true, {}, c.originalSettings );\n\t\t\t\t// restore original settings; this clears out current settings, but does not clear\n\t\t\t\t// values saved to storage.\n\t\t\t\tc = $.extend( true, ts.defaults, tmp );\n\t\t\t\tc.originalSettings = tmp;\n\t\t\t\tthis.hasInitialized = false;\n\t\t\t\t// setup the entire table again\n\t\t\t\tts.setup( this, c );\n\t\t\t});\n\t\t},\n\n\t\tbindEvents : function( table, $headers, core ) {\n\t\t\ttable = $( table )[ 0 ];\n\t\t\tvar tmp,\n\t\t\t\tc = table.config,\n\t\t\t\tnamespace = c.namespace,\n\t\t\t\tdownTarget = null;\n\t\t\tif ( core !== true ) {\n\t\t\t\t$headers.addClass( namespace.slice( 1 ) + '_extra_headers' );\n\t\t\t\ttmp = $.fn.closest ? $headers.closest( 'table' )[ 0 ] : $headers.parents( 'table' )[ 0 ];\n\t\t\t\tif ( tmp && tmp.nodeName === 'TABLE' && tmp !== table ) {\n\t\t\t\t\t$( tmp ).addClass( namespace.slice( 1 ) + '_extra_table' );\n\t\t\t\t}\n\t\t\t}\n\t\t\ttmp = ( c.pointerDown + ' ' + c.pointerUp + ' ' + c.pointerClick + ' sort keyup ' )\n\t\t\t\t.replace( ts.regex.spaces, ' ' )\n\t\t\t\t.split( ' ' )\n\t\t\t\t.join( namespace + ' ' );\n\t\t\t// apply event handling to headers and/or additional headers (stickyheaders, scroller, etc)\n\t\t\t$headers\n\t\t\t// http://stackoverflow.com/questions/5312849/jquery-find-self;\n\t\t\t.find( c.selectorSort )\n\t\t\t.add( $headers.filter( c.selectorSort ) )\n\t\t\t.unbind( tmp )\n\t\t\t.bind( tmp, function( e, external ) {\n\t\t\t\tvar $cell, cell, temp,\n\t\t\t\t\t$target = $( e.target ),\n\t\t\t\t\t// wrap event type in spaces, so the match doesn't trigger on inner words\n\t\t\t\t\ttype = ' ' + e.type + ' ';\n\t\t\t\t// only recognize left clicks\n\t\t\t\tif ( ( ( e.which || e.button ) !== 1 && !type.match( ' ' + c.pointerClick + ' | sort | keyup ' ) ) ||\n\t\t\t\t\t// allow pressing enter\n\t\t\t\t\t( type === ' keyup ' && e.which !== ts.keyCodes.enter ) ||\n\t\t\t\t\t// allow triggering a click event (e.which is undefined) & ignore physical clicks\n\t\t\t\t\t( type.match( ' ' + c.pointerClick + ' ' ) && typeof e.which !== 'undefined' ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// ignore mouseup if mousedown wasn't on the same target\n\t\t\t\tif ( type.match( ' ' + c.pointerUp + ' ' ) && downTarget !== e.target && external !== true ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// set target on mousedown\n\t\t\t\tif ( type.match( ' ' + c.pointerDown + ' ' ) ) {\n\t\t\t\t\tdownTarget = e.target;\n\t\t\t\t\t// preventDefault needed or jQuery v1.3.2 and older throws an\n\t\t\t\t\t// \"Uncaught TypeError: handler.apply is not a function\" error\n\t\t\t\t\ttemp = $target.jquery.split( '.' );\n\t\t\t\t\tif ( temp[ 0 ] === '1' && temp[ 1 ] < 4 ) { e.preventDefault(); }\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tdownTarget = null;\n\t\t\t\t// prevent sort being triggered on form elements\n\t\t\t\tif ( ts.regex.formElements.test( e.target.nodeName ) ||\n\t\t\t\t\t// nosort class name, or elements within a nosort container\n\t\t\t\t\t$target.hasClass( c.cssNoSort ) || $target.parents( '.' + c.cssNoSort ).length > 0 ||\n\t\t\t\t\t// elements within a button\n\t\t\t\t\t$target.parents( 'button' ).length > 0 ) {\n\t\t\t\t\treturn !c.cancelSelection;\n\t\t\t\t}\n\t\t\t\tif ( c.delayInit && ts.isEmptyObject( c.cache ) ) {\n\t\t\t\t\tts.buildCache( c );\n\t\t\t\t}\n\t\t\t\t// jQuery v1.2.6 doesn't have closest()\n\t\t\t\t$cell = $.fn.closest ? $( this ).closest( 'th, td' ) :\n\t\t\t\t\t/TH|TD/.test( this.nodeName ) ? $( this ) : $( this ).parents( 'th, td' );\n\t\t\t\t// reference original table headers and find the same cell\n\t\t\t\t// don't use $headers or IE8 throws an error - see #987\n\t\t\t\ttemp = $headers.index( $cell );\n\t\t\t\tc.last.clickedIndex = ( temp < 0 ) ? $cell.attr( 'data-column' ) : temp;\n\t\t\t\t// use column index if $headers is undefined\n\t\t\t\tcell = c.$headers[ c.last.clickedIndex ];\n\t\t\t\tif ( cell && !cell.sortDisabled ) {\n\t\t\t\t\tts.initSort( c, cell, e );\n\t\t\t\t}\n\t\t\t});\n\t\t\tif ( c.cancelSelection ) {\n\t\t\t\t// cancel selection\n\t\t\t\t$headers\n\t\t\t\t\t.attr( 'unselectable', 'on' )\n\t\t\t\t\t.bind( 'selectstart', false )\n\t\t\t\t\t.css({\n\t\t\t\t\t\t'user-select' : 'none',\n\t\t\t\t\t\t'MozUserSelect' : 'none' // not needed for jQuery 1.8+\n\t\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tbuildHeaders : function( c ) {\n\t\t\tvar $temp, icon, timer, indx;\n\t\t\tc.headerList = [];\n\t\t\tc.headerContent = [];\n\t\t\tc.sortVars = [];\n\t\t\tif ( c.debug ) {\n\t\t\t\ttimer = new Date();\n\t\t\t}\n\t\t\t// children tr in tfoot - see issue #196 & #547\n\t\t\t// don't pass table.config to computeColumnIndex here - widgets (math) pass it to \"quickly\" index tbody cells\n\t\t\tc.columns = ts.computeColumnIndex( c.$table.children( 'thead, tfoot' ).children( 'tr' ) );\n\t\t\t// add icon if cssIcon option exists\n\t\t\ticon = c.cssIcon ?\n\t\t\t\t'<i class=\"' + ( c.cssIcon === ts.css.icon ? ts.css.icon : c.cssIcon + ' ' + ts.css.icon ) + '\"></i>' :\n\t\t\t\t'';\n\t\t\t// redefine c.$headers here in case of an updateAll that replaces or adds an entire header cell - see #683\n\t\t\tc.$headers = $( $.map( c.$table.find( c.selectorHeaders ), function( elem, index ) {\n\t\t\t\tvar configHeaders, header, column, template, tmp,\n\t\t\t\t\t$elem = $( elem );\n\t\t\t\t// ignore cell (don't add it to c.$headers) if row has ignoreRow class\n\t\t\t\tif ( $elem.parent().hasClass( c.cssIgnoreRow ) ) { return; }\n\t\t\t\t// make sure to get header cell & not column indexed cell\n\t\t\t\tconfigHeaders = ts.getColumnData( c.table, c.headers, index, true );\n\t\t\t\t// save original header content\n\t\t\t\tc.headerContent[ index ] = $elem.html();\n\t\t\t\t// if headerTemplate is empty, don't reformat the header cell\n\t\t\t\tif ( c.headerTemplate !== '' && !$elem.find( '.' + ts.css.headerIn ).length ) {\n\t\t\t\t\t// set up header template\n\t\t\t\t\ttemplate = c.headerTemplate\n\t\t\t\t\t\t.replace( ts.regex.templateContent, $elem.html() )\n\t\t\t\t\t\t.replace( ts.regex.templateIcon, $elem.find( '.' + ts.css.icon ).length ? '' : icon );\n\t\t\t\t\tif ( c.onRenderTemplate ) {\n\t\t\t\t\t\theader = c.onRenderTemplate.apply( $elem, [ index, template ] );\n\t\t\t\t\t\t// only change t if something is returned\n\t\t\t\t\t\tif ( header && typeof header === 'string' ) {\n\t\t\t\t\t\t\ttemplate = header;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$elem.html( '<div class=\"' + ts.css.headerIn + '\">' + template + '</div>' ); // faster than wrapInner\n\t\t\t\t}\n\t\t\t\tif ( c.onRenderHeader ) {\n\t\t\t\t\tc.onRenderHeader.apply( $elem, [ index, c, c.$table ] );\n\t\t\t\t}\n\t\t\t\tcolumn = parseInt( $elem.attr( 'data-column' ), 10 );\n\t\t\t\telem.column = column;\n\t\t\t\ttmp = ts.getOrder( ts.getData( $elem, configHeaders, 'sortInitialOrder' ) || c.sortInitialOrder );\n\t\t\t\t// this may get updated numerous times if there are multiple rows\n\t\t\t\tc.sortVars[ column ] = {\n\t\t\t\t\tcount : -1, // set to -1 because clicking on the header automatically adds one\n\t\t\t\t\torder: tmp ?\n\t\t\t\t\t\t( c.sortReset ? [ 1, 0, 2 ] : [ 1, 0 ] ) : // desc, asc, unsorted\n\t\t\t\t\t\t( c.sortReset ? [ 0, 1, 2 ] : [ 0, 1 ] ), // asc, desc, unsorted\n\t\t\t\t\tlockedOrder : false\n\t\t\t\t};\n\t\t\t\ttmp = ts.getData( $elem, configHeaders, 'lockedOrder' ) || false;\n\t\t\t\tif ( typeof tmp !== 'undefined' && tmp !== false ) {\n\t\t\t\t\tc.sortVars[ column ].lockedOrder = true;\n\t\t\t\t\tc.sortVars[ column ].order = ts.getOrder( tmp ) ? [ 1, 1 ] : [ 0, 0 ];\n\t\t\t\t}\n\t\t\t\t// add cell to headerList\n\t\t\t\tc.headerList[ index ] = elem;\n\t\t\t\t// add to parent in case there are multiple rows\n\t\t\t\t$elem\n\t\t\t\t\t.addClass( ts.css.header + ' ' + c.cssHeader )\n\t\t\t\t\t.parent()\n\t\t\t\t\t.addClass( ts.css.headerRow + ' ' + c.cssHeaderRow )\n\t\t\t\t\t.attr( 'role', 'row' );\n\t\t\t\t// allow keyboard cursor to focus on element\n\t\t\t\tif ( c.tabIndex ) {\n\t\t\t\t\t$elem.attr( 'tabindex', 0 );\n\t\t\t\t}\n\t\t\t\treturn elem;\n\t\t\t}) );\n\t\t\t// cache headers per column\n\t\t\tc.$headerIndexed = [];\n\t\t\tfor ( indx = 0; indx < c.columns; indx++ ) {\n\t\t\t\t// colspan in header making a column undefined\n\t\t\t\tif ( ts.isEmptyObject( c.sortVars[ indx ] ) ) {\n\t\t\t\t\tc.sortVars[ indx ] = {};\n\t\t\t\t}\n\t\t\t\t$temp = c.$headers.filter( '[data-column=\"' + indx + '\"]' );\n\t\t\t\t// target sortable column cells, unless there are none, then use non-sortable cells\n\t\t\t\t// .last() added in jQuery 1.4; use .filter(':last') to maintain compatibility with jQuery v1.2.6\n\t\t\t\tc.$headerIndexed[ indx ] = $temp.length ?\n\t\t\t\t\t$temp.not( '.sorter-false' ).length ?\n\t\t\t\t\t\t$temp.not( '.sorter-false' ).filter( ':last' ) :\n\t\t\t\t\t\t$temp.filter( ':last' ) :\n\t\t\t\t\t$();\n\t\t\t}\n\t\t\tc.$table.find( c.selectorHeaders ).attr({\n\t\t\t\tscope: 'col',\n\t\t\t\trole : 'columnheader'\n\t\t\t});\n\t\t\t// enable/disable sorting\n\t\t\tts.updateHeader( c );\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole.log( 'Built headers:' + ts.benchmark( timer ) );\n\t\t\t\tconsole.log( c.$headers );\n\t\t\t}\n\t\t},\n\n\t\t// Use it to add a set of methods to table.config which will be available for all tables.\n\t\t// This should be done before table initialization\n\t\taddInstanceMethods : function( methods ) {\n\t\t\t$.extend( ts.instanceMethods, methods );\n\t\t},\n\n\t\t/*\n\t\t█████▄ ▄████▄ █████▄ ▄█████ ██████ █████▄ ▄█████\n\t\t██▄▄██ ██▄▄██ ██▄▄██ ▀█▄ ██▄▄ ██▄▄██ ▀█▄\n\t\t██▀▀▀ ██▀▀██ ██▀██ ▀█▄ ██▀▀ ██▀██ ▀█▄\n\t\t██ ██ ██ ██ ██ █████▀ ██████ ██ ██ █████▀\n\t\t*/\n\t\tsetupParsers : function( c, $tbodies ) {\n\t\t\tvar rows, list, span, max, colIndex, indx, header, configHeaders,\n\t\t\t\tnoParser, parser, extractor, time, tbody, len,\n\t\t\t\ttable = c.table,\n\t\t\t\ttbodyIndex = 0,\n\t\t\t\tdebug = {};\n\t\t\t// update table bodies in case we start with an empty table\n\t\t\tc.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );\n\t\t\ttbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies;\n\t\t\tlen = tbody.length;\n\t\t\tif ( len === 0 ) {\n\t\t\t\treturn c.debug ? console.warn( 'Warning: *Empty table!* Not building a parser cache' ) : '';\n\t\t\t} else if ( c.debug ) {\n\t\t\t\ttime = new Date();\n\t\t\t\tconsole[ console.group ? 'group' : 'log' ]( 'Detecting parsers for each column' );\n\t\t\t}\n\t\t\tlist = {\n\t\t\t\textractors: [],\n\t\t\t\tparsers: []\n\t\t\t};\n\t\t\twhile ( tbodyIndex < len ) {\n\t\t\t\trows = tbody[ tbodyIndex ].rows;\n\t\t\t\tif ( rows.length ) {\n\t\t\t\t\tcolIndex = 0;\n\t\t\t\t\tmax = c.columns;\n\t\t\t\t\tfor ( indx = 0; indx < max; indx++ ) {\n\t\t\t\t\t\theader = c.$headerIndexed[ colIndex ];\n\t\t\t\t\t\tif ( header && header.length ) {\n\t\t\t\t\t\t\t// get column indexed table cell\n\t\t\t\t\t\t\tconfigHeaders = ts.getColumnData( table, c.headers, colIndex );\n\t\t\t\t\t\t\t// get column parser/extractor\n\t\t\t\t\t\t\textractor = ts.getParserById( ts.getData( header, configHeaders, 'extractor' ) );\n\t\t\t\t\t\t\tparser = ts.getParserById( ts.getData( header, configHeaders, 'sorter' ) );\n\t\t\t\t\t\t\tnoParser = ts.getData( header, configHeaders, 'parser' ) === 'false';\n\t\t\t\t\t\t\t// empty cells behaviour - keeping emptyToBottom for backwards compatibility\n\t\t\t\t\t\t\tc.empties[colIndex] = (\n\t\t\t\t\t\t\t\tts.getData( header, configHeaders, 'empty' ) ||\n\t\t\t\t\t\t\t\tc.emptyTo || ( c.emptyToBottom ? 'bottom' : 'top' ) ).toLowerCase();\n\t\t\t\t\t\t\t// text strings behaviour in numerical sorts\n\t\t\t\t\t\t\tc.strings[colIndex] = (\n\t\t\t\t\t\t\t\tts.getData( header, configHeaders, 'string' ) ||\n\t\t\t\t\t\t\t\tc.stringTo ||\n\t\t\t\t\t\t\t\t'max' ).toLowerCase();\n\t\t\t\t\t\t\tif ( noParser ) {\n\t\t\t\t\t\t\t\tparser = ts.getParserById( 'no-parser' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( !extractor ) {\n\t\t\t\t\t\t\t\t// For now, maybe detect someday\n\t\t\t\t\t\t\t\textractor = false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( !parser ) {\n\t\t\t\t\t\t\t\tparser = ts.detectParserForColumn( c, rows, -1, colIndex );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( c.debug ) {\n\t\t\t\t\t\t\t\tdebug[ '(' + colIndex + ') ' + header.text() ] = {\n\t\t\t\t\t\t\t\t\tparser : parser.id,\n\t\t\t\t\t\t\t\t\textractor : extractor ? extractor.id : 'none',\n\t\t\t\t\t\t\t\t\tstring : c.strings[ colIndex ],\n\t\t\t\t\t\t\t\t\tempty : c.empties[ colIndex ]\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tlist.parsers[ colIndex ] = parser;\n\t\t\t\t\t\t\tlist.extractors[ colIndex ] = extractor;\n\t\t\t\t\t\t\tspan = header[ 0 ].colSpan - 1;\n\t\t\t\t\t\t\tif ( span > 0 ) {\n\t\t\t\t\t\t\t\tcolIndex += span;\n\t\t\t\t\t\t\t\tmax += span;\n\t\t\t\t\t\t\t\twhile ( span + 1 > 0 ) {\n\t\t\t\t\t\t\t\t\t// set colspan columns to use the same parsers & extractors\n\t\t\t\t\t\t\t\t\tlist.parsers[ colIndex - span ] = parser;\n\t\t\t\t\t\t\t\t\tlist.extractors[ colIndex - span ] = extractor;\n\t\t\t\t\t\t\t\t\tspan--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcolIndex++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\ttbodyIndex += ( list.parsers.length ) ? len : 1;\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tif ( !ts.isEmptyObject( debug ) ) {\n\t\t\t\t\tconsole[ console.table ? 'table' : 'log' ]( debug );\n\t\t\t\t} else {\n\t\t\t\t\tconsole.warn( ' No parsers detected!' );\n\t\t\t\t}\n\t\t\t\tconsole.log( 'Completed detecting parsers' + ts.benchmark( time ) );\n\t\t\t\tif ( console.groupEnd ) { console.groupEnd(); }\n\t\t\t}\n\t\t\tc.parsers = list.parsers;\n\t\t\tc.extractors = list.extractors;\n\t\t},\n\n\t\taddParser : function( parser ) {\n\t\t\tvar indx,\n\t\t\t\tlen = ts.parsers.length,\n\t\t\t\tadd = true;\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\tif ( ts.parsers[ indx ].id.toLowerCase() === parser.id.toLowerCase() ) {\n\t\t\t\t\tadd = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( add ) {\n\t\t\t\tts.parsers[ ts.parsers.length ] = parser;\n\t\t\t}\n\t\t},\n\n\t\tgetParserById : function( name ) {\n\t\t\t/*jshint eqeqeq:false */\n\t\t\tif ( name == 'false' ) { return false; }\n\t\t\tvar indx,\n\t\t\t\tlen = ts.parsers.length;\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\tif ( ts.parsers[ indx ].id.toLowerCase() === ( name.toString() ).toLowerCase() ) {\n\t\t\t\t\treturn ts.parsers[ indx ];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\n\t\tdetectParserForColumn : function( c, rows, rowIndex, cellIndex ) {\n\t\t\tvar cur, $node, row,\n\t\t\t\tindx = ts.parsers.length,\n\t\t\t\tnode = false,\n\t\t\t\tnodeValue = '',\n\t\t\t\tkeepLooking = true;\n\t\t\twhile ( nodeValue === '' && keepLooking ) {\n\t\t\t\trowIndex++;\n\t\t\t\trow = rows[ rowIndex ];\n\t\t\t\t// stop looking after 50 empty rows\n\t\t\t\tif ( row && rowIndex < 50 ) {\n\t\t\t\t\tif ( row.className.indexOf( ts.cssIgnoreRow ) < 0 ) {\n\t\t\t\t\t\tnode = rows[ rowIndex ].cells[ cellIndex ];\n\t\t\t\t\t\tnodeValue = ts.getElementText( c, node, cellIndex );\n\t\t\t\t\t\t$node = $( node );\n\t\t\t\t\t\tif ( c.debug ) {\n\t\t\t\t\t\t\tconsole.log( 'Checking if value was empty on row ' + rowIndex + ', column: ' +\n\t\t\t\t\t\t\t\tcellIndex + ': \"' + nodeValue + '\"' );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tkeepLooking = false;\n\t\t\t\t}\n\t\t\t}\n\t\t\twhile ( --indx >= 0 ) {\n\t\t\t\tcur = ts.parsers[ indx ];\n\t\t\t\t// ignore the default text parser because it will always be true\n\t\t\t\tif ( cur && cur.id !== 'text' && cur.is && cur.is( nodeValue, c.table, node, $node ) ) {\n\t\t\t\t\treturn cur;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// nothing found, return the generic parser (text)\n\t\t\treturn ts.getParserById( 'text' );\n\t\t},\n\n\t\tgetElementText : function( c, node, cellIndex ) {\n\t\t\tif ( !node ) { return ''; }\n\t\t\tvar tmp,\n\t\t\t\textract = c.textExtraction || '',\n\t\t\t\t// node could be a jquery object\n\t\t\t\t// http://jsperf.com/jquery-vs-instanceof-jquery/2\n\t\t\t\t$node = node.jquery ? node : $( node );\n\t\t\tif ( typeof extract === 'string' ) {\n\t\t\t\t// check data-attribute first when set to 'basic'; don't use node.innerText - it's really slow!\n\t\t\t\t// http://www.kellegous.com/j/2013/02/27/innertext-vs-textcontent/\n\t\t\t\tif ( extract === 'basic' && typeof ( tmp = $node.attr( c.textAttribute ) ) !== 'undefined' ) {\n\t\t\t\t\treturn $.trim( tmp );\n\t\t\t\t}\n\t\t\t\treturn $.trim( node.textContent || $node.text() );\n\t\t\t} else {\n\t\t\t\tif ( typeof extract === 'function' ) {\n\t\t\t\t\treturn $.trim( extract( $node[ 0 ], c.table, cellIndex ) );\n\t\t\t\t} else if ( typeof ( tmp = ts.getColumnData( c.table, extract, cellIndex ) ) === 'function' ) {\n\t\t\t\t\treturn $.trim( tmp( $node[ 0 ], c.table, cellIndex ) );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// fallback\n\t\t\treturn $.trim( $node[ 0 ].textContent || $node.text() );\n\t\t},\n\n\t\t// centralized function to extract/parse cell contents\n\t\tgetParsedText : function( c, cell, colIndex, txt ) {\n\t\t\tif ( typeof txt === 'undefined' ) {\n\t\t\t\ttxt = ts.getElementText( c, cell, colIndex );\n\t\t\t}\n\t\t\t// if no parser, make sure to return the txt\n\t\t\tvar val = '' + txt,\n\t\t\t\tparser = c.parsers[ colIndex ],\n\t\t\t\textractor = c.extractors[ colIndex ];\n\t\t\tif ( parser ) {\n\t\t\t\t// do extract before parsing, if there is one\n\t\t\t\tif ( extractor && typeof extractor.format === 'function' ) {\n\t\t\t\t\ttxt = extractor.format( txt, c.table, cell, colIndex );\n\t\t\t\t}\n\t\t\t\t// allow parsing if the string is empty, previously parsing would change it to zero,\n\t\t\t\t// in case the parser needs to extract data from the table cell attributes\n\t\t\t\tval = parser.id === 'no-parser' ? '' :\n\t\t\t\t\t// make sure txt is a string (extractor may have converted it)\n\t\t\t\t\tparser.format( '' + txt, c.table, cell, colIndex );\n\t\t\t\tif ( c.ignoreCase && typeof val === 'string' ) {\n\t\t\t\t\tval = val.toLowerCase();\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn val;\n\t\t},\n\n\t\t/*\n\t\t▄████▄ ▄████▄ ▄████▄ ██ ██ ██████\n\t\t██ ▀▀ ██▄▄██ ██ ▀▀ ██▄▄██ ██▄▄\n\t\t██ ▄▄ ██▀▀██ ██ ▄▄ ██▀▀██ ██▀▀\n\t\t▀████▀ ██ ██ ▀████▀ ██ ██ ██████\n\t\t*/\n\t\tbuildCache : function( c, callback, $tbodies ) {\n\t\t\tvar cache, val, txt, rowIndex, colIndex, tbodyIndex, $tbody, $row,\n\t\t\t\tcols, $cells, cell, cacheTime, totalRows, rowData, prevRowData,\n\t\t\t\tcolMax, span, cacheIndex, hasParser, max, len, index,\n\t\t\t\ttable = c.table,\n\t\t\t\tparsers = c.parsers;\n\t\t\t// update tbody variable\n\t\t\tc.$tbodies = c.$table.children( 'tbody:not(.' + c.cssInfoBlock + ')' );\n\t\t\t$tbody = typeof $tbodies === 'undefined' ? c.$tbodies : $tbodies,\n\t\t\tc.cache = {};\n\t\t\tc.totalRows = 0;\n\t\t\t// if no parsers found, return - it's an empty table.\n\t\t\tif ( !parsers ) {\n\t\t\t\treturn c.debug ? console.warn( 'Warning: *Empty table!* Not building a cache' ) : '';\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tcacheTime = new Date();\n\t\t\t}\n\t\t\t// processing icon\n\t\t\tif ( c.showProcessing ) {\n\t\t\t\tts.isProcessing( table, true );\n\t\t\t}\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < $tbody.length; tbodyIndex++ ) {\n\t\t\t\tcolMax = []; // column max value per tbody\n\t\t\t\tcache = c.cache[ tbodyIndex ] = {\n\t\t\t\t\tnormalized: [] // array of normalized row data; last entry contains 'rowData' above\n\t\t\t\t\t// colMax: # // added at the end\n\t\t\t\t};\n\n\t\t\t\ttotalRows = ( $tbody[ tbodyIndex ] && $tbody[ tbodyIndex ].rows.length ) || 0;\n\t\t\t\tfor ( rowIndex = 0; rowIndex < totalRows; ++rowIndex ) {\n\t\t\t\t\trowData = {\n\t\t\t\t\t\t// order: original row order #\n\t\t\t\t\t\t// $row : jQuery Object[]\n\t\t\t\t\t\tchild: [], // child row text (filter widget)\n\t\t\t\t\t\traw: [] // original row text\n\t\t\t\t\t};\n\t\t\t\t\t/** Add the table data to main data array */\n\t\t\t\t\t$row = $( $tbody[ tbodyIndex ].rows[ rowIndex ] );\n\t\t\t\t\tcols = [];\n\t\t\t\t\t// ignore \"remove-me\" rows\n\t\t\t\t\tif ( $row.hasClass( c.selectorRemove.slice(1) ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// if this is a child row, add it to the last row's children and continue to the next row\n\t\t\t\t\t// ignore child row class, if it is the first row\n\t\t\t\t\tif ( $row.hasClass( c.cssChildRow ) && rowIndex !== 0 ) {\n\t\t\t\t\t\tlen = cache.normalized.length - 1;\n\t\t\t\t\t\tprevRowData = cache.normalized[ len ][ c.columns ];\n\t\t\t\t\t\tprevRowData.$row = prevRowData.$row.add( $row );\n\t\t\t\t\t\t// add 'hasChild' class name to parent row\n\t\t\t\t\t\tif ( !$row.prev().hasClass( c.cssChildRow ) ) {\n\t\t\t\t\t\t\t$row.prev().addClass( ts.css.cssHasChild );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// save child row content (un-parsed!)\n\t\t\t\t\t\t$cells = $row.children( 'th, td' );\n\t\t\t\t\t\tlen = prevRowData.child.length;\n\t\t\t\t\t\tprevRowData.child[ len ] = [];\n\t\t\t\t\t\t// child row content does not account for colspans/rowspans; so indexing may be off\n\t\t\t\t\t\tcacheIndex = 0;\n\t\t\t\t\t\tmax = c.columns;\n\t\t\t\t\t\tfor ( colIndex = 0; colIndex < max; colIndex++ ) {\n\t\t\t\t\t\t\tcell = $cells[ colIndex ];\n\t\t\t\t\t\t\tif ( cell ) {\n\t\t\t\t\t\t\t\tprevRowData.child[ len ][ colIndex ] = ts.getParsedText( c, cell, colIndex );\n\t\t\t\t\t\t\t\tspan = $cells[ colIndex ].colSpan - 1;\n\t\t\t\t\t\t\t\tif ( span > 0 ) {\n\t\t\t\t\t\t\t\t\tcacheIndex += span;\n\t\t\t\t\t\t\t\t\tmax += span;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcacheIndex++;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// go to the next for loop\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\trowData.$row = $row;\n\t\t\t\t\trowData.order = rowIndex; // add original row position to rowCache\n\t\t\t\t\tcacheIndex = 0;\n\t\t\t\t\tmax = c.columns;\n\t\t\t\t\tfor ( colIndex = 0; colIndex < max; ++colIndex ) {\n\t\t\t\t\t\tcell = $row[ 0 ].cells[ colIndex ];\n\t\t\t\t\t\tif ( cell && cacheIndex < c.columns ) {\n\t\t\t\t\t\t\thasParser = typeof parsers[ cacheIndex ] !== 'undefined';\n\t\t\t\t\t\t\tif ( !hasParser && c.debug ) {\n\t\t\t\t\t\t\t\tconsole.warn( 'No parser found for row: ' + rowIndex + ', column: ' + colIndex +\n\t\t\t\t\t\t\t\t\t'; cell containing: \"' + $(cell).text() + '\"; does it have a header?' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tval = ts.getElementText( c, cell, cacheIndex );\n\t\t\t\t\t\t\trowData.raw[ cacheIndex ] = val; // save original row text\n\t\t\t\t\t\t\t// save raw column text even if there is no parser set\n\t\t\t\t\t\t\ttxt = ts.getParsedText( c, cell, cacheIndex, val );\n\t\t\t\t\t\t\tcols[ cacheIndex ] = txt;\n\t\t\t\t\t\t\tif ( hasParser && ( parsers[ cacheIndex ].type || '' ).toLowerCase() === 'numeric' ) {\n\t\t\t\t\t\t\t\t// determine column max value (ignore sign)\n\t\t\t\t\t\t\t\tcolMax[ cacheIndex ] = Math.max( Math.abs( txt ) || 0, colMax[ cacheIndex ] || 0 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// allow colSpan in tbody\n\t\t\t\t\t\t\tspan = cell.colSpan - 1;\n\t\t\t\t\t\t\tif ( span > 0 ) {\n\t\t\t\t\t\t\t\tindex = 0;\n\t\t\t\t\t\t\t\twhile ( index <= span ) {\n\t\t\t\t\t\t\t\t\t// duplicate text (or not) to spanned columns\n\t\t\t\t\t\t\t\t\t// instead of setting duplicate span to empty string, use textExtraction to try to get a value\n\t\t\t\t\t\t\t\t\t// see http://stackoverflow.com/q/36449711/145346\n\t\t\t\t\t\t\t\t\ttxt = c.duplicateSpan || index === 0 ?\n\t\t\t\t\t\t\t\t\t\tval :\n\t\t\t\t\t\t\t\t\t\ttypeof c.textExtraction !== 'string' ?\n\t\t\t\t\t\t\t\t\t\t\tts.getElementText( c, cell, cacheIndex + index ) || '' :\n\t\t\t\t\t\t\t\t\t\t\t'';\n\t\t\t\t\t\t\t\t\trowData.raw[ cacheIndex + index ] = txt;\n\t\t\t\t\t\t\t\t\tcols[ cacheIndex + index ] = txt;\n\t\t\t\t\t\t\t\t\tindex++;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcacheIndex += span;\n\t\t\t\t\t\t\t\tmax += span;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcacheIndex++;\n\t\t\t\t\t}\n\t\t\t\t\t// ensure rowData is always in the same location (after the last column)\n\t\t\t\t\tcols[ c.columns ] = rowData;\n\t\t\t\t\tcache.normalized[ cache.normalized.length ] = cols;\n\t\t\t\t}\n\t\t\t\tcache.colMax = colMax;\n\t\t\t\t// total up rows, not including child rows\n\t\t\t\tc.totalRows += cache.normalized.length;\n\n\t\t\t}\n\t\t\tif ( c.showProcessing ) {\n\t\t\t\tts.isProcessing( table ); // remove processing icon\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tlen = Math.min( 5, c.cache[ 0 ].normalized.length );\n\t\t\t\tconsole[ console.group ? 'group' : 'log' ]( 'Building cache for ' + c.totalRows +\n\t\t\t\t\t' rows (showing ' + len + ' rows in log) and ' + c.columns + ' columns' +\n\t\t\t\t\tts.benchmark( cacheTime ) );\n\t\t\t\tval = {};\n\t\t\t\tfor ( colIndex = 0; colIndex < c.columns; colIndex++ ) {\n\t\t\t\t\tfor ( cacheIndex = 0; cacheIndex < len; cacheIndex++ ) {\n\t\t\t\t\t\tif ( !val[ 'row: ' + cacheIndex ] ) {\n\t\t\t\t\t\t\tval[ 'row: ' + cacheIndex ] = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tval[ 'row: ' + cacheIndex ][ c.$headerIndexed[ colIndex ].text() ] =\n\t\t\t\t\t\t\tc.cache[ 0 ].normalized[ cacheIndex ][ colIndex ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconsole[ console.table ? 'table' : 'log' ]( val );\n\t\t\t\tif ( console.groupEnd ) { console.groupEnd(); }\n\t\t\t}\n\t\t\tif ( $.isFunction( callback ) ) {\n\t\t\t\tcallback( table );\n\t\t\t}\n\t\t},\n\n\t\tgetColumnText : function( table, column, callback, rowFilter ) {\n\t\t\ttable = $( table )[0];\n\t\t\tvar tbodyIndex, rowIndex, cache, row, tbodyLen, rowLen, raw, parsed, $cell, result,\n\t\t\t\thasCallback = typeof callback === 'function',\n\t\t\t\tallColumns = column === 'all',\n\t\t\t\tdata = { raw : [], parsed: [], $cell: [] },\n\t\t\t\tc = table.config;\n\t\t\tif ( ts.isEmptyObject( c ) ) {\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tconsole.warn( 'No cache found - aborting getColumnText function!' );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttbodyLen = c.$tbodies.length;\n\t\t\t\tfor ( tbodyIndex = 0; tbodyIndex < tbodyLen; tbodyIndex++ ) {\n\t\t\t\t\tcache = c.cache[ tbodyIndex ].normalized;\n\t\t\t\t\trowLen = cache.length;\n\t\t\t\t\tfor ( rowIndex = 0; rowIndex < rowLen; rowIndex++ ) {\n\t\t\t\t\t\trow = cache[ rowIndex ];\n\t\t\t\t\t\tif ( rowFilter && !row[ c.columns ].$row.is( rowFilter ) ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult = true;\n\t\t\t\t\t\tparsed = ( allColumns ) ? row.slice( 0, c.columns ) : row[ column ];\n\t\t\t\t\t\trow = row[ c.columns ];\n\t\t\t\t\t\traw = ( allColumns ) ? row.raw : row.raw[ column ];\n\t\t\t\t\t\t$cell = ( allColumns ) ? row.$row.children() : row.$row.children().eq( column );\n\t\t\t\t\t\tif ( hasCallback ) {\n\t\t\t\t\t\t\tresult = callback({\n\t\t\t\t\t\t\t\ttbodyIndex : tbodyIndex,\n\t\t\t\t\t\t\t\trowIndex : rowIndex,\n\t\t\t\t\t\t\t\tparsed : parsed,\n\t\t\t\t\t\t\t\traw : raw,\n\t\t\t\t\t\t\t\t$row : row.$row,\n\t\t\t\t\t\t\t\t$cell : $cell\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( result !== false ) {\n\t\t\t\t\t\t\tdata.parsed[ data.parsed.length ] = parsed;\n\t\t\t\t\t\t\tdata.raw[ data.raw.length ] = raw;\n\t\t\t\t\t\t\tdata.$cell[ data.$cell.length ] = $cell;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// return everything\n\t\t\t\treturn data;\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t██ ██ █████▄ █████▄ ▄████▄ ██████ ██████\n\t\t██ ██ ██▄▄██ ██ ██ ██▄▄██ ██ ██▄▄\n\t\t██ ██ ██▀▀▀ ██ ██ ██▀▀██ ██ ██▀▀\n\t\t▀████▀ ██ █████▀ ██ ██ ██ ██████\n\t\t*/\n\t\tsetHeadersCss : function( c ) {\n\t\t\tvar $sorted, indx, column,\n\t\t\t\tlist = c.sortList,\n\t\t\t\tlen = list.length,\n\t\t\t\tnone = ts.css.sortNone + ' ' + c.cssNone,\n\t\t\t\tcss = [ ts.css.sortAsc + ' ' + c.cssAsc, ts.css.sortDesc + ' ' + c.cssDesc ],\n\t\t\t\tcssIcon = [ c.cssIconAsc, c.cssIconDesc, c.cssIconNone ],\n\t\t\t\taria = [ 'ascending', 'descending' ],\n\t\t\t\t// find the footer\n\t\t\t\t$headers = c.$table\n\t\t\t\t\t.find( 'tfoot tr' )\n\t\t\t\t\t.children( 'td, th' )\n\t\t\t\t\t.add( $( c.namespace + '_extra_headers' ) )\n\t\t\t\t\t.removeClass( css.join( ' ' ) );\n\t\t\t// remove all header information\n\t\t\tc.$headers\n\t\t\t\t.add( $( 'thead ' + c.namespace + '_extra_headers' ) )\n\t\t\t\t.removeClass( css.join( ' ' ) )\n\t\t\t\t.addClass( none )\n\t\t\t\t.attr( 'aria-sort', 'none' )\n\t\t\t\t.find( '.' + ts.css.icon )\n\t\t\t\t.removeClass( cssIcon.join( ' ' ) )\n\t\t\t\t.addClass( cssIcon[ 2 ] );\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t// direction = 2 means reset!\n\t\t\t\tif ( list[ indx ][ 1 ] !== 2 ) {\n\t\t\t\t\t// multicolumn sorting updating - see #1005\n\t\t\t\t\t// .not(function(){}) needs jQuery 1.4\n\t\t\t\t\t// filter(function(i, el){}) <- el is undefined in jQuery v1.2.6\n\t\t\t\t\t$sorted = c.$headers.filter( function( i ) {\n\t\t\t\t\t\t// only include headers that are in the sortList (this includes colspans)\n\t\t\t\t\t\tvar include = true,\n\t\t\t\t\t\t\t$el = c.$headers.eq( i ),\n\t\t\t\t\t\t\tcol = parseInt( $el.attr( 'data-column' ), 10 ),\n\t\t\t\t\t\t\tend = col + c.$headers[ i ].colSpan;\n\t\t\t\t\t\tfor ( ; col < end; col++ ) {\n\t\t\t\t\t\t\tinclude = include ? include || ts.isValueInArray( col, c.sortList ) > -1 : false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn include;\n\t\t\t\t\t});\n\n\t\t\t\t\t// choose the :last in case there are nested columns\n\t\t\t\t\t$sorted = $sorted\n\t\t\t\t\t\t.not( '.sorter-false' )\n\t\t\t\t\t\t.filter( '[data-column=\"' + list[ indx ][ 0 ] + '\"]' + ( len === 1 ? ':last' : '' ) );\n\t\t\t\t\tif ( $sorted.length ) {\n\t\t\t\t\t\tfor ( column = 0; column < $sorted.length; column++ ) {\n\t\t\t\t\t\t\tif ( !$sorted[ column ].sortDisabled ) {\n\t\t\t\t\t\t\t\t$sorted\n\t\t\t\t\t\t\t\t\t.eq( column )\n\t\t\t\t\t\t\t\t\t.removeClass( none )\n\t\t\t\t\t\t\t\t\t.addClass( css[ list[ indx ][ 1 ] ] )\n\t\t\t\t\t\t\t\t\t.attr( 'aria-sort', aria[ list[ indx ][ 1 ] ] )\n\t\t\t\t\t\t\t\t\t.find( '.' + ts.css.icon )\n\t\t\t\t\t\t\t\t\t.removeClass( cssIcon[ 2 ] )\n\t\t\t\t\t\t\t\t\t.addClass( cssIcon[ list[ indx ][ 1 ] ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// add sorted class to footer & extra headers, if they exist\n\t\t\t\t\t\tif ( $headers.length ) {\n\t\t\t\t\t\t\t$headers\n\t\t\t\t\t\t\t\t.filter( '[data-column=\"' + list[ indx ][ 0 ] + '\"]' )\n\t\t\t\t\t\t\t\t.removeClass( none )\n\t\t\t\t\t\t\t\t.addClass( css[ list[ indx ][ 1 ] ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// add verbose aria labels\n\t\t\tlen = c.$headers.length;\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\tts.setColumnAriaLabel( c, c.$headers.eq( indx ) );\n\t\t\t}\n\t\t},\n\n\t\t// nextSort (optional), lets you disable next sort text\n\t\tsetColumnAriaLabel : function( c, $header, nextSort ) {\n\t\t\tif ( $header.length ) {\n\t\t\t\tvar column = parseInt( $header.attr( 'data-column' ), 10 ),\n\t\t\t\t\tvars = c.sortVars[ column ],\n\t\t\t\t\ttmp = $header.hasClass( ts.css.sortAsc ) ?\n\t\t\t\t\t\t'sortAsc' :\n\t\t\t\t\t\t$header.hasClass( ts.css.sortDesc ) ? 'sortDesc' : 'sortNone',\n\t\t\t\t\ttxt = $.trim( $header.text() ) + ': ' + ts.language[ tmp ];\n\t\t\t\tif ( $header.hasClass( 'sorter-false' ) || nextSort === false ) {\n\t\t\t\t\ttxt += ts.language.sortDisabled;\n\t\t\t\t} else {\n\t\t\t\t\ttmp = ( vars.count + 1 ) % vars.order.length;\n\t\t\t\t\tnextSort = vars.order[ tmp ];\n\t\t\t\t\t// if nextSort\n\t\t\t\t\ttxt += ts.language[ nextSort === 0 ? 'nextAsc' : nextSort === 1 ? 'nextDesc' : 'nextNone' ];\n\t\t\t\t}\n\t\t\t\t$header.attr( 'aria-label', txt );\n\t\t\t}\n\t\t},\n\n\t\tupdateHeader : function( c ) {\n\t\t\tvar index, isDisabled, $header, col,\n\t\t\t\ttable = c.table,\n\t\t\t\tlen = c.$headers.length;\n\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\t$header = c.$headers.eq( index );\n\t\t\t\tcol = ts.getColumnData( table, c.headers, index, true );\n\t\t\t\t// add 'sorter-false' class if 'parser-false' is set\n\t\t\t\tisDisabled = ts.getData( $header, col, 'sorter' ) === 'false' || ts.getData( $header, col, 'parser' ) === 'false';\n\t\t\t\tts.setColumnSort( c, $header, isDisabled );\n\t\t\t}\n\t\t},\n\n\t\tsetColumnSort : function( c, $header, isDisabled ) {\n\t\t\tvar id = c.table.id;\n\t\t\t$header[ 0 ].sortDisabled = isDisabled;\n\t\t\t$header[ isDisabled ? 'addClass' : 'removeClass' ]( 'sorter-false' )\n\t\t\t\t.attr( 'aria-disabled', '' + isDisabled );\n\t\t\t// disable tab index on disabled cells\n\t\t\tif ( c.tabIndex ) {\n\t\t\t\tif ( isDisabled ) {\n\t\t\t\t\t$header.removeAttr( 'tabindex' );\n\t\t\t\t} else {\n\t\t\t\t\t$header.attr( 'tabindex', '0' );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// aria-controls - requires table ID\n\t\t\tif ( id ) {\n\t\t\t\tif ( isDisabled ) {\n\t\t\t\t\t$header.removeAttr( 'aria-controls' );\n\t\t\t\t} else {\n\t\t\t\t\t$header.attr( 'aria-controls', id );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tupdateHeaderSortCount : function( c, list ) {\n\t\t\tvar col, dir, group, indx, primary, temp, val, order,\n\t\t\t\tsortList = list || c.sortList,\n\t\t\t\tlen = sortList.length;\n\t\t\tc.sortList = [];\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\tval = sortList[ indx ];\n\t\t\t\t// ensure all sortList values are numeric - fixes #127\n\t\t\t\tcol = parseInt( val[ 0 ], 10 );\n\t\t\t\t// prevents error if sorton array is wrong\n\t\t\t\tif ( col < c.columns ) {\n\n\t\t\t\t\t// set order if not already defined - due to colspan header without associated header cell\n\t\t\t\t\t// adding this check prevents a javascript error\n\t\t\t\t\tif ( !c.sortVars[ col ].order ) {\n\t\t\t\t\t\tif ( ts.getOrder( c.sortInitialOrder ) ) {\n\t\t\t\t\t\t\torder = c.sortReset ? [ 1, 0, 2 ] : [ 1, 0 ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\torder = c.sortReset ? [ 0, 1, 2 ] : [ 0, 1 ];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tc.sortVars[ col ].order = order;\n\t\t\t\t\t\tc.sortVars[ col ].count = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\torder = c.sortVars[ col ].order;\n\t\t\t\t\tdir = ( '' + val[ 1 ] ).match( /^(1|d|s|o|n)/ );\n\t\t\t\t\tdir = dir ? dir[ 0 ] : '';\n\t\t\t\t\t// 0/(a)sc (default), 1/(d)esc, (s)ame, (o)pposite, (n)ext\n\t\t\t\t\tswitch ( dir ) {\n\t\t\t\t\t\tcase '1' : case 'd' : // descending\n\t\t\t\t\t\t\tdir = 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 's' : // same direction (as primary column)\n\t\t\t\t\t\t\t// if primary sort is set to 's', make it ascending\n\t\t\t\t\t\t\tdir = primary || 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'o' :\n\t\t\t\t\t\t\ttemp = order[ ( primary || 0 ) % order.length ];\n\t\t\t\t\t\t\t// opposite of primary column; but resets if primary resets\n\t\t\t\t\t\t\tdir = temp === 0 ? 1 : temp === 1 ? 0 : 2;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'n' :\n\t\t\t\t\t\t\tdir = order[ ( ++c.sortVars[ col ].count ) % order.length ];\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault : // ascending\n\t\t\t\t\t\t\tdir = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tprimary = indx === 0 ? dir : primary;\n\t\t\t\t\tgroup = [ col, parseInt( dir, 10 ) || 0 ];\n\t\t\t\t\tc.sortList[ c.sortList.length ] = group;\n\t\t\t\t\tdir = $.inArray( group[ 1 ], order ); // fixes issue #167\n\t\t\t\t\tc.sortVars[ col ].count = dir >= 0 ? dir : group[ 1 ] % order.length;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tupdateAll : function( c, resort, callback ) {\n\t\t\tvar table = c.table;\n\t\t\ttable.isUpdating = true;\n\t\t\tts.refreshWidgets( table, true, true );\n\t\t\tts.buildHeaders( c );\n\t\t\tts.bindEvents( table, c.$headers, true );\n\t\t\tts.bindMethods( c );\n\t\t\tts.commonUpdate( c, resort, callback );\n\t\t},\n\n\t\tupdate : function( c, resort, callback ) {\n\t\t\tvar table = c.table;\n\t\t\ttable.isUpdating = true;\n\t\t\t// update sorting (if enabled/disabled)\n\t\t\tts.updateHeader( c );\n\t\t\tts.commonUpdate( c, resort, callback );\n\t\t},\n\n\t\t// simple header update - see #989\n\t\tupdateHeaders : function( c, callback ) {\n\t\t\tc.table.isUpdating = true;\n\t\t\tts.buildHeaders( c );\n\t\t\tts.bindEvents( c.table, c.$headers, true );\n\t\t\tts.resortComplete( c, callback );\n\t\t},\n\n\t\tupdateCell : function( c, cell, resort, callback ) {\n\t\t\tif ( ts.isEmptyObject( c.cache ) ) {\n\t\t\t\t// empty table, do an update instead - fixes #1099\n\t\t\t\tts.updateHeader( c );\n\t\t\t\tts.commonUpdate( c, resort, callback );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tc.table.isUpdating = true;\n\t\t\tc.$table.find( c.selectorRemove ).remove();\n\t\t\t// get position from the dom\n\t\t\tvar tmp, indx, row, icell, cache, len,\n\t\t\t\t$tbodies = c.$tbodies,\n\t\t\t\t$cell = $( cell ),\n\t\t\t\t// update cache - format: function( s, table, cell, cellIndex )\n\t\t\t\t// no closest in jQuery v1.2.6\n\t\t\t\ttbodyIndex = $tbodies\n\t\t\t\t\t.index( $.fn.closest ? $cell.closest( 'tbody' ) : $cell.parents( 'tbody' ).filter( ':first' ) ),\n\t\t\t\ttbcache = c.cache[ tbodyIndex ],\n\t\t\t\t$row = $.fn.closest ? $cell.closest( 'tr' ) : $cell.parents( 'tr' ).filter( ':first' );\n\t\t\tcell = $cell[ 0 ]; // in case cell is a jQuery object\n\t\t\t// tbody may not exist if update is initialized while tbody is removed for processing\n\t\t\tif ( $tbodies.length && tbodyIndex >= 0 ) {\n\t\t\t\trow = $tbodies.eq( tbodyIndex ).find( 'tr' ).index( $row );\n\t\t\t\tcache = tbcache.normalized[ row ];\n\t\t\t\tlen = $row[ 0 ].cells.length;\n\t\t\t\tif ( len !== c.columns ) {\n\t\t\t\t\t// colspan in here somewhere!\n\t\t\t\t\ticell = 0;\n\t\t\t\t\ttmp = false;\n\t\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\t\tif ( !tmp && $row[ 0 ].cells[ indx ] !== cell ) {\n\t\t\t\t\t\t\ticell += $row[ 0 ].cells[ indx ].colSpan;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmp = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ticell = $cell.index();\n\t\t\t\t}\n\t\t\t\ttmp = ts.getElementText( c, cell, icell ); // raw\n\t\t\t\tcache[ c.columns ].raw[ icell ] = tmp;\n\t\t\t\ttmp = ts.getParsedText( c, cell, icell, tmp );\n\t\t\t\tcache[ icell ] = tmp; // parsed\n\t\t\t\tcache[ c.columns ].$row = $row;\n\t\t\t\tif ( ( c.parsers[ icell ].type || '' ).toLowerCase() === 'numeric' ) {\n\t\t\t\t\t// update column max value (ignore sign)\n\t\t\t\t\ttbcache.colMax[ icell ] = Math.max( Math.abs( tmp ) || 0, tbcache.colMax[ icell ] || 0 );\n\t\t\t\t}\n\t\t\t\ttmp = resort !== 'undefined' ? resort : c.resort;\n\t\t\t\tif ( tmp !== false ) {\n\t\t\t\t\t// widgets will be reapplied\n\t\t\t\t\tts.checkResort( c, tmp, callback );\n\t\t\t\t} else {\n\t\t\t\t\t// don't reapply widgets is resort is false, just in case it causes\n\t\t\t\t\t// problems with element focus\n\t\t\t\t\tts.resortComplete( c, callback );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tconsole.error( 'updateCell aborted, tbody missing or not within the indicated table' );\n\t\t\t\t}\n\t\t\t\tc.table.isUpdating = false;\n\t\t\t}\n\t\t},\n\n\t\taddRows : function( c, $row, resort, callback ) {\n\t\t\tvar txt, val, tbodyIndex, rowIndex, rows, cellIndex, len, order,\n\t\t\t\tcacheIndex, rowData, cells, cell, span,\n\t\t\t\t// allow passing a row string if only one non-info tbody exists in the table\n\t\t\t\tvalid = typeof $row === 'string' && c.$tbodies.length === 1 && /<tr/.test( $row || '' ),\n\t\t\t\ttable = c.table;\n\t\t\tif ( valid ) {\n\t\t\t\t$row = $( $row );\n\t\t\t\tc.$tbodies.append( $row );\n\t\t\t} else if ( !$row ||\n\t\t\t\t// row is a jQuery object?\n\t\t\t\t!( $row instanceof jQuery ) ||\n\t\t\t\t// row contained in the table?\n\t\t\t\t( $.fn.closest ? $row.closest( 'table' )[ 0 ] : $row.parents( 'table' )[ 0 ] ) !== c.table ) {\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tconsole.error( 'addRows method requires (1) a jQuery selector reference to rows that have already ' +\n\t\t\t\t\t\t'been added to the table, or (2) row HTML string to be added to a table with only one tbody' );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttable.isUpdating = true;\n\t\t\tif ( ts.isEmptyObject( c.cache ) ) {\n\t\t\t\t// empty table, do an update instead - fixes #450\n\t\t\t\tts.updateHeader( c );\n\t\t\t\tts.commonUpdate( c, resort, callback );\n\t\t\t} else {\n\t\t\t\trows = $row.filter( 'tr' ).attr( 'role', 'row' ).length;\n\t\t\t\ttbodyIndex = c.$tbodies.index( $row.parents( 'tbody' ).filter( ':first' ) );\n\t\t\t\t// fixes adding rows to an empty table - see issue #179\n\t\t\t\tif ( !( c.parsers && c.parsers.length ) ) {\n\t\t\t\t\tts.setupParsers( c );\n\t\t\t\t}\n\t\t\t\t// add each row\n\t\t\t\tfor ( rowIndex = 0; rowIndex < rows; rowIndex++ ) {\n\t\t\t\t\tcacheIndex = 0;\n\t\t\t\t\tlen = $row[ rowIndex ].cells.length;\n\t\t\t\t\torder = c.cache[ tbodyIndex ].normalized.length;\n\t\t\t\t\tcells = [];\n\t\t\t\t\trowData = {\n\t\t\t\t\t\tchild : [],\n\t\t\t\t\t\traw : [],\n\t\t\t\t\t\t$row : $row.eq( rowIndex ),\n\t\t\t\t\t\torder : order\n\t\t\t\t\t};\n\t\t\t\t\t// add each cell\n\t\t\t\t\tfor ( cellIndex = 0; cellIndex < len; cellIndex++ ) {\n\t\t\t\t\t\tcell = $row[ rowIndex ].cells[ cellIndex ];\n\t\t\t\t\t\ttxt = ts.getElementText( c, cell, cacheIndex );\n\t\t\t\t\t\trowData.raw[ cacheIndex ] = txt;\n\t\t\t\t\t\tval = ts.getParsedText( c, cell, cacheIndex, txt );\n\t\t\t\t\t\tcells[ cacheIndex ] = val;\n\t\t\t\t\t\tif ( ( c.parsers[ cacheIndex ].type || '' ).toLowerCase() === 'numeric' ) {\n\t\t\t\t\t\t\t// update column max value (ignore sign)\n\t\t\t\t\t\t\tc.cache[ tbodyIndex ].colMax[ cacheIndex ] =\n\t\t\t\t\t\t\t\tMath.max( Math.abs( val ) || 0, c.cache[ tbodyIndex ].colMax[ cacheIndex ] || 0 );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tspan = cell.colSpan - 1;\n\t\t\t\t\t\tif ( span > 0 ) {\n\t\t\t\t\t\t\tcacheIndex += span;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcacheIndex++;\n\t\t\t\t\t}\n\t\t\t\t\t// add the row data to the end\n\t\t\t\t\tcells[ c.columns ] = rowData;\n\t\t\t\t\t// update cache\n\t\t\t\t\tc.cache[ tbodyIndex ].normalized[ order ] = cells;\n\t\t\t\t}\n\t\t\t\t// resort using current settings\n\t\t\t\tts.checkResort( c, resort, callback );\n\t\t\t}\n\t\t},\n\n\t\tupdateCache : function( c, callback, $tbodies ) {\n\t\t\t// rebuild parsers\n\t\t\tif ( !( c.parsers && c.parsers.length ) ) {\n\t\t\t\tts.setupParsers( c, $tbodies );\n\t\t\t}\n\t\t\t// rebuild the cache map\n\t\t\tts.buildCache( c, callback, $tbodies );\n\t\t},\n\n\t\t// init flag (true) used by pager plugin to prevent widget application\n\t\t// renamed from appendToTable\n\t\tappendCache : function( c, init ) {\n\t\t\tvar parsed, totalRows, $tbody, $curTbody, rowIndex, tbodyIndex, appendTime,\n\t\t\t\ttable = c.table,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\t$tbodies = c.$tbodies,\n\t\t\t\trows = [],\n\t\t\t\tcache = c.cache;\n\t\t\t// empty table - fixes #206/#346\n\t\t\tif ( ts.isEmptyObject( cache ) ) {\n\t\t\t\t// run pager appender in case the table was just emptied\n\t\t\t\treturn c.appender ? c.appender( table, rows ) :\n\t\t\t\t\ttable.isUpdating ? c.$table.triggerHandler( 'updateComplete', table ) : ''; // Fixes #532\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tappendTime = new Date();\n\t\t\t}\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {\n\t\t\t\t$tbody = $tbodies.eq( tbodyIndex );\n\t\t\t\tif ( $tbody.length ) {\n\t\t\t\t\t// detach tbody for manipulation\n\t\t\t\t\t$curTbody = ts.processTbody( table, $tbody, true );\n\t\t\t\t\tparsed = cache[ tbodyIndex ].normalized;\n\t\t\t\t\ttotalRows = parsed.length;\n\t\t\t\t\tfor ( rowIndex = 0; rowIndex < totalRows; rowIndex++ ) {\n\t\t\t\t\t\trows[rows.length] = parsed[ rowIndex ][ c.columns ].$row;\n\t\t\t\t\t\t// removeRows used by the pager plugin; don't render if using ajax - fixes #411\n\t\t\t\t\t\tif ( !c.appender || ( c.pager && ( !c.pager.removeRows || !wo.pager_removeRows ) && !c.pager.ajax ) ) {\n\t\t\t\t\t\t\t$curTbody.append( parsed[ rowIndex ][ c.columns ].$row );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// restore tbody\n\t\t\t\t\tts.processTbody( table, $curTbody, false );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( c.appender ) {\n\t\t\t\tc.appender( table, rows );\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole.log( 'Rebuilt table' + ts.benchmark( appendTime ) );\n\t\t\t}\n\t\t\t// apply table widgets; but not before ajax completes\n\t\t\tif ( !init && !c.appender ) {\n\t\t\t\tts.applyWidget( table );\n\t\t\t}\n\t\t\tif ( table.isUpdating ) {\n\t\t\t\tc.$table.triggerHandler( 'updateComplete', table );\n\t\t\t}\n\t\t},\n\n\t\tcommonUpdate : function( c, resort, callback ) {\n\t\t\t// remove rows/elements before update\n\t\t\tc.$table.find( c.selectorRemove ).remove();\n\t\t\t// rebuild parsers\n\t\t\tts.setupParsers( c );\n\t\t\t// rebuild the cache map\n\t\t\tts.buildCache( c );\n\t\t\tts.checkResort( c, resort, callback );\n\t\t},\n\n\t\t/*\n\t\t▄█████ ▄████▄ █████▄ ██████ ██ █████▄ ▄████▄\n\t\t▀█▄ ██ ██ ██▄▄██ ██ ██ ██ ██ ██ ▄▄▄\n\t\t ▀█▄ ██ ██ ██▀██ ██ ██ ██ ██ ██ ▀██\n\t\t█████▀ ▀████▀ ██ ██ ██ ██ ██ ██ ▀████▀\n\t\t*/\n\t\tinitSort : function( c, cell, event ) {\n\t\t\tif ( c.table.isUpdating ) {\n\t\t\t\t// let any updates complete before initializing a sort\n\t\t\t\treturn setTimeout( function(){\n\t\t\t\t\tts.initSort( c, cell, event );\n\t\t\t\t}, 50 );\n\t\t\t}\n\n\t\t\tvar arry, indx, headerIndx, dir, temp, tmp, $header,\n\t\t\t\tnotMultiSort = !event[ c.sortMultiSortKey ],\n\t\t\t\ttable = c.table,\n\t\t\t\tlen = c.$headers.length,\n\t\t\t\t// get current column index\n\t\t\t\tcol = parseInt( $( cell ).attr( 'data-column' ), 10 ),\n\t\t\t\torder = c.sortVars[ col ].order;\n\n\t\t\t// Only call sortStart if sorting is enabled\n\t\t\tc.$table.triggerHandler( 'sortStart', table );\n\t\t\t// get current column sort order\n\t\t\ttmp = ( c.sortVars[ col ].count + 1 ) % order.length;\n\t\t\tc.sortVars[ col ].count = event[ c.sortResetKey ] ? 2 : tmp;\n\t\t\t// reset all sorts on non-current column - issue #30\n\t\t\tif ( c.sortRestart ) {\n\t\t\t\tfor ( headerIndx = 0; headerIndx < len; headerIndx++ ) {\n\t\t\t\t\t$header = c.$headers.eq( headerIndx );\n\t\t\t\t\ttmp = parseInt( $header.attr( 'data-column' ), 10 );\n\t\t\t\t\t// only reset counts on columns that weren't just clicked on and if not included in a multisort\n\t\t\t\t\tif ( col !== tmp && ( notMultiSort || $header.hasClass( ts.css.sortNone ) ) ) {\n\t\t\t\t\t\tc.sortVars[ tmp ].count = -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// user only wants to sort on one column\n\t\t\tif ( notMultiSort ) {\n\t\t\t\t// flush the sort list\n\t\t\t\tc.sortList = [];\n\t\t\t\tc.last.sortList = [];\n\t\t\t\tif ( c.sortForce !== null ) {\n\t\t\t\t\tarry = c.sortForce;\n\t\t\t\t\tfor ( indx = 0; indx < arry.length; indx++ ) {\n\t\t\t\t\t\tif ( arry[ indx ][ 0 ] !== col ) {\n\t\t\t\t\t\t\tc.sortList[ c.sortList.length ] = arry[ indx ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// add column to sort list\n\t\t\t\tdir = order[ c.sortVars[ col ].count ];\n\t\t\t\tif ( dir < 2 ) {\n\t\t\t\t\tc.sortList[ c.sortList.length ] = [ col, dir ];\n\t\t\t\t\t// add other columns if header spans across multiple\n\t\t\t\t\tif ( cell.colSpan > 1 ) {\n\t\t\t\t\t\tfor ( indx = 1; indx < cell.colSpan; indx++ ) {\n\t\t\t\t\t\t\tc.sortList[ c.sortList.length ] = [ col + indx, dir ];\n\t\t\t\t\t\t\t// update count on columns in colSpan\n\t\t\t\t\t\t\tc.sortVars[ col + indx ].count = $.inArray( dir, order );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// multi column sorting\n\t\t\t} else {\n\t\t\t\t// get rid of the sortAppend before adding more - fixes issue #115 & #523\n\t\t\t\tc.sortList = $.extend( [], c.last.sortList );\n\n\t\t\t\t// the user has clicked on an already sorted column\n\t\t\t\tif ( ts.isValueInArray( col, c.sortList ) >= 0 ) {\n\t\t\t\t\t// reverse the sorting direction\n\t\t\t\t\tfor ( indx = 0; indx < c.sortList.length; indx++ ) {\n\t\t\t\t\t\ttmp = c.sortList[ indx ];\n\t\t\t\t\t\tif ( tmp[ 0 ] === col ) {\n\t\t\t\t\t\t\t// order.count seems to be incorrect when compared to cell.count\n\t\t\t\t\t\t\ttmp[ 1 ] = order[ c.sortVars[ col ].count ];\n\t\t\t\t\t\t\tif ( tmp[1] === 2 ) {\n\t\t\t\t\t\t\t\tc.sortList.splice( indx, 1 );\n\t\t\t\t\t\t\t\tc.sortVars[ col ].count = -1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// add column to sort list array\n\t\t\t\t\tdir = order[ c.sortVars[ col ].count ];\n\t\t\t\t\tif ( dir < 2 ) {\n\t\t\t\t\t\tc.sortList[ c.sortList.length ] = [ col, dir ];\n\t\t\t\t\t\t// add other columns if header spans across multiple\n\t\t\t\t\t\tif ( cell.colSpan > 1 ) {\n\t\t\t\t\t\t\tfor ( indx = 1; indx < cell.colSpan; indx++ ) {\n\t\t\t\t\t\t\t\tc.sortList[ c.sortList.length ] = [ col + indx, dir ];\n\t\t\t\t\t\t\t\t// update count on columns in colSpan\n\t\t\t\t\t\t\t\tc.sortVars[ col + indx ].count = $.inArray( dir, order );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// save sort before applying sortAppend\n\t\t\tc.last.sortList = $.extend( [], c.sortList );\n\t\t\tif ( c.sortList.length && c.sortAppend ) {\n\t\t\t\tarry = $.isArray( c.sortAppend ) ? c.sortAppend : c.sortAppend[ c.sortList[ 0 ][ 0 ] ];\n\t\t\t\tif ( !ts.isEmptyObject( arry ) ) {\n\t\t\t\t\tfor ( indx = 0; indx < arry.length; indx++ ) {\n\t\t\t\t\t\tif ( arry[ indx ][ 0 ] !== col && ts.isValueInArray( arry[ indx ][ 0 ], c.sortList ) < 0 ) {\n\t\t\t\t\t\t\tdir = arry[ indx ][ 1 ];\n\t\t\t\t\t\t\ttemp = ( '' + dir ).match( /^(a|d|s|o|n)/ );\n\t\t\t\t\t\t\tif ( temp ) {\n\t\t\t\t\t\t\t\ttmp = c.sortList[ 0 ][ 1 ];\n\t\t\t\t\t\t\t\tswitch ( temp[ 0 ] ) {\n\t\t\t\t\t\t\t\t\tcase 'd' :\n\t\t\t\t\t\t\t\t\t\tdir = 1;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 's' :\n\t\t\t\t\t\t\t\t\t\tdir = tmp;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 'o' :\n\t\t\t\t\t\t\t\t\t\tdir = tmp === 0 ? 1 : 0;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 'n' :\n\t\t\t\t\t\t\t\t\t\tdir = ( tmp + 1 ) % order.length;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tdir = 0;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tc.sortList[ c.sortList.length ] = [ arry[ indx ][ 0 ], dir ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// sortBegin event triggered immediately before the sort\n\t\t\tc.$table.triggerHandler( 'sortBegin', table );\n\t\t\t// setTimeout needed so the processing icon shows up\n\t\t\tsetTimeout( function() {\n\t\t\t\t// set css for headers\n\t\t\t\tts.setHeadersCss( c );\n\t\t\t\tts.multisort( c );\n\t\t\t\tts.appendCache( c );\n\t\t\t\tc.$table.triggerHandler( 'sortBeforeEnd', table );\n\t\t\t\tc.$table.triggerHandler( 'sortEnd', table );\n\t\t\t}, 1 );\n\t\t},\n\n\t\t// sort multiple columns\n\t\tmultisort : function( c ) { /*jshint loopfunc:true */\n\t\t\tvar tbodyIndex, sortTime, colMax, rows, tmp,\n\t\t\t\ttable = c.table,\n\t\t\t\tsorter = [],\n\t\t\t\tdir = 0,\n\t\t\t\ttextSorter = c.textSorter || '',\n\t\t\t\tsortList = c.sortList,\n\t\t\t\tsortLen = sortList.length,\n\t\t\t\tlen = c.$tbodies.length;\n\t\t\tif ( c.serverSideSorting || ts.isEmptyObject( c.cache ) ) {\n\t\t\t\t// empty table - fixes #206/#346\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( c.debug ) { sortTime = new Date(); }\n\t\t\t// cache textSorter to optimize speed\n\t\t\tif ( typeof textSorter === 'object' ) {\n\t\t\t\tcolMax = c.columns;\n\t\t\t\twhile ( colMax-- ) {\n\t\t\t\t\ttmp = ts.getColumnData( table, textSorter, colMax );\n\t\t\t\t\tif ( typeof tmp === 'function' ) {\n\t\t\t\t\t\tsorter[ colMax ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < len; tbodyIndex++ ) {\n\t\t\t\tcolMax = c.cache[ tbodyIndex ].colMax;\n\t\t\t\trows = c.cache[ tbodyIndex ].normalized;\n\n\t\t\t\trows.sort( function( a, b ) {\n\t\t\t\t\tvar sortIndex, num, col, order, sort, x, y;\n\t\t\t\t\t// rows is undefined here in IE, so don't use it!\n\t\t\t\t\tfor ( sortIndex = 0; sortIndex < sortLen; sortIndex++ ) {\n\t\t\t\t\t\tcol = sortList[ sortIndex ][ 0 ];\n\t\t\t\t\t\torder = sortList[ sortIndex ][ 1 ];\n\t\t\t\t\t\t// sort direction, true = asc, false = desc\n\t\t\t\t\t\tdir = order === 0;\n\n\t\t\t\t\t\tif ( c.sortStable && a[ col ] === b[ col ] && sortLen === 1 ) {\n\t\t\t\t\t\t\treturn a[ c.columns ].order - b[ c.columns ].order;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// fallback to natural sort since it is more robust\n\t\t\t\t\t\tnum = /n/i.test( ts.getSortType( c.parsers, col ) );\n\t\t\t\t\t\tif ( num && c.strings[ col ] ) {\n\t\t\t\t\t\t\t// sort strings in numerical columns\n\t\t\t\t\t\t\tif ( typeof ( ts.string[ c.strings[ col ] ] ) === 'boolean' ) {\n\t\t\t\t\t\t\t\tnum = ( dir ? 1 : -1 ) * ( ts.string[ c.strings[ col ] ] ? -1 : 1 );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnum = ( c.strings[ col ] ) ? ts.string[ c.strings[ col ] ] || 0 : 0;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// fall back to built-in numeric sort\n\t\t\t\t\t\t\t// var sort = $.tablesorter['sort' + s]( a[col], b[col], dir, colMax[col], table );\n\t\t\t\t\t\t\tsort = c.numberSorter ? c.numberSorter( a[ col ], b[ col ], dir, colMax[ col ], table ) :\n\t\t\t\t\t\t\t\tts[ 'sortNumeric' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], num, colMax[ col ], col, c );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// set a & b depending on sort direction\n\t\t\t\t\t\t\tx = dir ? a : b;\n\t\t\t\t\t\t\ty = dir ? b : a;\n\t\t\t\t\t\t\t// text sort function\n\t\t\t\t\t\t\tif ( typeof textSorter === 'function' ) {\n\t\t\t\t\t\t\t\t// custom OVERALL text sorter\n\t\t\t\t\t\t\t\tsort = textSorter( x[ col ], y[ col ], dir, col, table );\n\t\t\t\t\t\t\t} else if ( typeof sorter[ col ] === 'function' ) {\n\t\t\t\t\t\t\t\t// custom text sorter for a SPECIFIC COLUMN\n\t\t\t\t\t\t\t\tsort = sorter[ col ]( x[ col ], y[ col ], dir, col, table );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// fall back to natural sort\n\t\t\t\t\t\t\t\tsort = ts[ 'sortNatural' + ( dir ? 'Asc' : 'Desc' ) ]( a[ col ], b[ col ], col, c );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( sort ) { return sort; }\n\t\t\t\t\t}\n\t\t\t\t\treturn a[ c.columns ].order - b[ c.columns ].order;\n\t\t\t\t});\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole.log( 'Applying sort ' + sortList.toString() + ts.benchmark( sortTime ) );\n\t\t\t}\n\t\t},\n\n\t\tresortComplete : function( c, callback ) {\n\t\t\tif ( c.table.isUpdating ) {\n\t\t\t\tc.$table.triggerHandler( 'updateComplete', c.table );\n\t\t\t}\n\t\t\tif ( $.isFunction( callback ) ) {\n\t\t\t\tcallback( c.table );\n\t\t\t}\n\t\t},\n\n\t\tcheckResort : function( c, resort, callback ) {\n\t\t\tvar sortList = $.isArray( resort ) ? resort : c.sortList,\n\t\t\t\t// if no resort parameter is passed, fallback to config.resort (true by default)\n\t\t\t\tresrt = typeof resort === 'undefined' ? c.resort : resort;\n\t\t\t// don't try to resort if the table is still processing\n\t\t\t// this will catch spamming of the updateCell method\n\t\t\tif ( resrt !== false && !c.serverSideSorting && !c.table.isProcessing ) {\n\t\t\t\tif ( sortList.length ) {\n\t\t\t\t\tts.sortOn( c, sortList, function() {\n\t\t\t\t\t\tts.resortComplete( c, callback );\n\t\t\t\t\t}, true );\n\t\t\t\t} else {\n\t\t\t\t\tts.sortReset( c, function() {\n\t\t\t\t\t\tts.resortComplete( c, callback );\n\t\t\t\t\t\tts.applyWidget( c.table, false );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tts.resortComplete( c, callback );\n\t\t\t\tts.applyWidget( c.table, false );\n\t\t\t}\n\t\t},\n\n\t\tsortOn : function( c, list, callback, init ) {\n\t\t\tvar table = c.table;\n\t\t\tc.$table.triggerHandler( 'sortStart', table );\n\t\t\t// update header count index\n\t\t\tts.updateHeaderSortCount( c, list );\n\t\t\t// set css for headers\n\t\t\tts.setHeadersCss( c );\n\t\t\t// fixes #346\n\t\t\tif ( c.delayInit && ts.isEmptyObject( c.cache ) ) {\n\t\t\t\tts.buildCache( c );\n\t\t\t}\n\t\t\tc.$table.triggerHandler( 'sortBegin', table );\n\t\t\t// sort the table and append it to the dom\n\t\t\tts.multisort( c );\n\t\t\tts.appendCache( c, init );\n\t\t\tc.$table.triggerHandler( 'sortBeforeEnd', table );\n\t\t\tc.$table.triggerHandler( 'sortEnd', table );\n\t\t\tts.applyWidget( table );\n\t\t\tif ( $.isFunction( callback ) ) {\n\t\t\t\tcallback( table );\n\t\t\t}\n\t\t},\n\n\t\tsortReset : function( c, callback ) {\n\t\t\tc.sortList = [];\n\t\t\tts.setHeadersCss( c );\n\t\t\tts.multisort( c );\n\t\t\tts.appendCache( c );\n\t\t\tif ( $.isFunction( callback ) ) {\n\t\t\t\tcallback( c.table );\n\t\t\t}\n\t\t},\n\n\t\tgetSortType : function( parsers, column ) {\n\t\t\treturn ( parsers && parsers[ column ] ) ? parsers[ column ].type || '' : '';\n\t\t},\n\n\t\tgetOrder : function( val ) {\n\t\t\t// look for 'd' in 'desc' order; return true\n\t\t\treturn ( /^d/i.test( val ) || val === 1 );\n\t\t},\n\n\t\t// Natural sort - https://github.com/overset/javascript-natural-sort (date sorting removed)\n\t\t// this function will only accept strings, or you'll see 'TypeError: undefined is not a function'\n\t\t// I could add a = a.toString(); b = b.toString(); but it'll slow down the sort overall\n\t\tsortNatural : function( a, b ) {\n\t\t\tif ( a === b ) { return 0; }\n\t\t\tvar aNum, bNum, aFloat, bFloat, indx, max,\n\t\t\t\tregex = ts.regex;\n\t\t\t// first try and sort Hex codes\n\t\t\tif ( regex.hex.test( b ) ) {\n\t\t\t\taNum = parseInt( ( a || '' ).match( regex.hex ), 16 );\n\t\t\t\tbNum = parseInt( ( b || '' ).match( regex.hex ), 16 );\n\t\t\t\tif ( aNum < bNum ) { return -1; }\n\t\t\t\tif ( aNum > bNum ) { return 1; }\n\t\t\t}\n\t\t\t// chunk/tokenize\n\t\t\taNum = ( a || '' ).replace( regex.chunk, '\\\\0$1\\\\0' ).replace( regex.chunks, '' ).split( '\\\\0' );\n\t\t\tbNum = ( b || '' ).replace( regex.chunk, '\\\\0$1\\\\0' ).replace( regex.chunks, '' ).split( '\\\\0' );\n\t\t\tmax = Math.max( aNum.length, bNum.length );\n\t\t\t// natural sorting through split numeric strings and default strings\n\t\t\tfor ( indx = 0; indx < max; indx++ ) {\n\t\t\t\t// find floats not starting with '0', string or 0 if not defined\n\t\t\t\taFloat = isNaN( aNum[ indx ] ) ? aNum[ indx ] || 0 : parseFloat( aNum[ indx ] ) || 0;\n\t\t\t\tbFloat = isNaN( bNum[ indx ] ) ? bNum[ indx ] || 0 : parseFloat( bNum[ indx ] ) || 0;\n\t\t\t\t// handle numeric vs string comparison - number < string - (Kyle Adams)\n\t\t\t\tif ( isNaN( aFloat ) !== isNaN( bFloat ) ) { return isNaN( aFloat ) ? 1 : -1; }\n\t\t\t\t// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'\n\t\t\t\tif ( typeof aFloat !== typeof bFloat ) {\n\t\t\t\t\taFloat += '';\n\t\t\t\t\tbFloat += '';\n\t\t\t\t}\n\t\t\t\tif ( aFloat < bFloat ) { return -1; }\n\t\t\t\tif ( aFloat > bFloat ) { return 1; }\n\t\t\t}\n\t\t\treturn 0;\n\t\t},\n\n\t\tsortNaturalAsc : function( a, b, col, c ) {\n\t\t\tif ( a === b ) { return 0; }\n\t\t\tvar empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];\n\t\t\tif ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : -empty || -1; }\n\t\t\tif ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : empty || 1; }\n\t\t\treturn ts.sortNatural( a, b );\n\t\t},\n\n\t\tsortNaturalDesc : function( a, b, col, c ) {\n\t\t\tif ( a === b ) { return 0; }\n\t\t\tvar empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];\n\t\t\tif ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : empty || 1; }\n\t\t\tif ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : -empty || -1; }\n\t\t\treturn ts.sortNatural( b, a );\n\t\t},\n\n\t\t// basic alphabetical sort\n\t\tsortText : function( a, b ) {\n\t\t\treturn a > b ? 1 : ( a < b ? -1 : 0 );\n\t\t},\n\n\t\t// return text string value by adding up ascii value\n\t\t// so the text is somewhat sorted when using a digital sort\n\t\t// this is NOT an alphanumeric sort\n\t\tgetTextValue : function( val, num, max ) {\n\t\t\tif ( max ) {\n\t\t\t\t// make sure the text value is greater than the max numerical value (max)\n\t\t\t\tvar indx,\n\t\t\t\t\tlen = val ? val.length : 0,\n\t\t\t\t\tn = max + num;\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\tn += val.charCodeAt( indx );\n\t\t\t\t}\n\t\t\t\treturn num * n;\n\t\t\t}\n\t\t\treturn 0;\n\t\t},\n\n\t\tsortNumericAsc : function( a, b, num, max, col, c ) {\n\t\t\tif ( a === b ) { return 0; }\n\t\t\tvar empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];\n\t\t\tif ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : -empty || -1; }\n\t\t\tif ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : empty || 1; }\n\t\t\tif ( isNaN( a ) ) { a = ts.getTextValue( a, num, max ); }\n\t\t\tif ( isNaN( b ) ) { b = ts.getTextValue( b, num, max ); }\n\t\t\treturn a - b;\n\t\t},\n\n\t\tsortNumericDesc : function( a, b, num, max, col, c ) {\n\t\t\tif ( a === b ) { return 0; }\n\t\t\tvar empty = ts.string[ ( c.empties[ col ] || c.emptyTo ) ];\n\t\t\tif ( a === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? -1 : 1 ) : empty || 1; }\n\t\t\tif ( b === '' && empty !== 0 ) { return typeof empty === 'boolean' ? ( empty ? 1 : -1 ) : -empty || -1; }\n\t\t\tif ( isNaN( a ) ) { a = ts.getTextValue( a, num, max ); }\n\t\t\tif ( isNaN( b ) ) { b = ts.getTextValue( b, num, max ); }\n\t\t\treturn b - a;\n\t\t},\n\n\t\tsortNumeric : function( a, b ) {\n\t\t\treturn a - b;\n\t\t},\n\n\t\t/*\n\t\t██ ██ ██ ██ █████▄ ▄████▄ ██████ ██████ ▄█████\n\t\t██ ██ ██ ██ ██ ██ ██ ▄▄▄ ██▄▄ ██ ▀█▄\n\t\t██ ██ ██ ██ ██ ██ ██ ▀██ ██▀▀ ██ ▀█▄\n\t\t███████▀ ██ █████▀ ▀████▀ ██████ ██ █████▀\n\t\t*/\n\t\taddWidget : function( widget ) {\n\t\t\tif ( widget.id && !ts.isEmptyObject( ts.getWidgetById( widget.id ) ) ) {\n\t\t\t\tconsole.warn( '\"' + widget.id + '\" widget was loaded more than once!' );\n\t\t\t}\n\t\t\tts.widgets[ ts.widgets.length ] = widget;\n\t\t},\n\n\t\thasWidget : function( $table, name ) {\n\t\t\t$table = $( $table );\n\t\t\treturn $table.length && $table[ 0 ].config && $table[ 0 ].config.widgetInit[ name ] || false;\n\t\t},\n\n\t\tgetWidgetById : function( name ) {\n\t\t\tvar indx, widget,\n\t\t\t\tlen = ts.widgets.length;\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\twidget = ts.widgets[ indx ];\n\t\t\t\tif ( widget && widget.id && widget.id.toLowerCase() === name.toLowerCase() ) {\n\t\t\t\t\treturn widget;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tapplyWidgetOptions : function( table ) {\n\t\t\tvar indx, widget,\n\t\t\t\tc = table.config,\n\t\t\t\tlen = c.widgets.length;\n\t\t\tif ( len ) {\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\twidget = ts.getWidgetById( c.widgets[ indx ] );\n\t\t\t\t\tif ( widget && widget.options ) {\n\t\t\t\t\t\tc.widgetOptions = $.extend( true, {}, widget.options, c.widgetOptions );\n\t\t\t\t\t\t// add widgetOptions to defaults for option validator\n\t\t\t\t\t\t$.extend( true, ts.defaults.widgetOptions, widget.options );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\taddWidgetFromClass : function( table ) {\n\t\t\tvar len, indx,\n\t\t\t\tc = table.config,\n\t\t\t\t// look for widgets to apply from table class\n\t\t\t\t// don't match from 'ui-widget-content'; use \\S instead of \\w to include widgets\n\t\t\t\t// with dashes in the name, e.g. \"widget-test-2\" extracts out \"test-2\"\n\t\t\t\tregex = '^' + c.widgetClass.replace( ts.regex.templateName, '(\\\\S+)+' ) + '$',\n\t\t\t\twidgetClass = new RegExp( regex, 'g' ),\n\t\t\t\t// split up table class (widget id's can include dashes) - stop using match\n\t\t\t\t// otherwise only one widget gets extracted, see #1109\n\t\t\t\twidgets = ( table.className || '' ).split( ts.regex.spaces );\n\t\t\tif ( widgets.length ) {\n\t\t\t\tlen = widgets.length;\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\tif ( widgets[ indx ].match( widgetClass ) ) {\n\t\t\t\t\t\tc.widgets[ c.widgets.length ] = widgets[ indx ].replace( widgetClass, '$1' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tapplyWidgetId : function( table, id, init ) {\n\t\t\ttable = $(table)[0];\n\t\t\tvar applied, time, name,\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\twidget = ts.getWidgetById( id );\n\t\t\tif ( widget ) {\n\t\t\t\tname = widget.id;\n\t\t\t\tapplied = false;\n\t\t\t\t// add widget name to option list so it gets reapplied after sorting, filtering, etc\n\t\t\t\tif ( $.inArray( name, c.widgets ) < 0 ) {\n\t\t\t\t\tc.widgets[ c.widgets.length ] = name;\n\t\t\t\t}\n\t\t\t\tif ( c.debug ) { time = new Date(); }\n\n\t\t\t\tif ( init || !( c.widgetInit[ name ] ) ) {\n\t\t\t\t\t// set init flag first to prevent calling init more than once (e.g. pager)\n\t\t\t\t\tc.widgetInit[ name ] = true;\n\t\t\t\t\tif ( table.hasInitialized ) {\n\t\t\t\t\t\t// don't reapply widget options on tablesorter init\n\t\t\t\t\t\tts.applyWidgetOptions( table );\n\t\t\t\t\t}\n\t\t\t\t\tif ( typeof widget.init === 'function' ) {\n\t\t\t\t\t\tapplied = true;\n\t\t\t\t\t\tif ( c.debug ) {\n\t\t\t\t\t\t\tconsole[ console.group ? 'group' : 'log' ]( 'Initializing ' + name + ' widget' );\n\t\t\t\t\t\t}\n\t\t\t\t\t\twidget.init( table, widget, c, wo );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( !init && typeof widget.format === 'function' ) {\n\t\t\t\t\tapplied = true;\n\t\t\t\t\tif ( c.debug ) {\n\t\t\t\t\t\tconsole[ console.group ? 'group' : 'log' ]( 'Updating ' + name + ' widget' );\n\t\t\t\t\t}\n\t\t\t\t\twidget.format( table, c, wo, false );\n\t\t\t\t}\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tif ( applied ) {\n\t\t\t\t\t\tconsole.log( 'Completed ' + ( init ? 'initializing ' : 'applying ' ) + name + ' widget' + ts.benchmark( time ) );\n\t\t\t\t\t\tif ( console.groupEnd ) { console.groupEnd(); }\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tapplyWidget : function( table, init, callback ) {\n\t\t\ttable = $( table )[ 0 ]; // in case this is called externally\n\t\t\tvar indx, len, names, widget, time,\n\t\t\t\tc = table.config,\n\t\t\t\twidgets = [];\n\t\t\t// prevent numerous consecutive widget applications\n\t\t\tif ( init !== false && table.hasInitialized && ( table.isApplyingWidgets || table.isUpdating ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( c.debug ) { time = new Date(); }\n\t\t\tts.addWidgetFromClass( table );\n\t\t\t// prevent \"tablesorter-ready\" from firing multiple times in a row\n\t\t\tclearTimeout( c.timerReady );\n\t\t\tif ( c.widgets.length ) {\n\t\t\t\ttable.isApplyingWidgets = true;\n\t\t\t\t// ensure unique widget ids\n\t\t\t\tc.widgets = $.grep( c.widgets, function( val, index ) {\n\t\t\t\t\treturn $.inArray( val, c.widgets ) === index;\n\t\t\t\t});\n\t\t\t\tnames = c.widgets || [];\n\t\t\t\tlen = names.length;\n\t\t\t\t// build widget array & add priority as needed\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\twidget = ts.getWidgetById( names[ indx ] );\n\t\t\t\t\tif ( widget && widget.id ) {\n\t\t\t\t\t\t// set priority to 10 if not defined\n\t\t\t\t\t\tif ( !widget.priority ) { widget.priority = 10; }\n\t\t\t\t\t\twidgets[ indx ] = widget;\n\t\t\t\t\t} else if ( c.debug ) {\n\t\t\t\t\t\tconsole.warn( '\"' + names[ indx ] + '\" widget code does not exist!' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// sort widgets by priority\n\t\t\t\twidgets.sort( function( a, b ) {\n\t\t\t\t\treturn a.priority < b.priority ? -1 : a.priority === b.priority ? 0 : 1;\n\t\t\t\t});\n\t\t\t\t// add/update selected widgets\n\t\t\t\tlen = widgets.length;\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tconsole[ console.group ? 'group' : 'log' ]( 'Start ' + ( init ? 'initializing' : 'applying' ) + ' widgets' );\n\t\t\t\t}\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\twidget = widgets[ indx ];\n\t\t\t\t\tif ( widget && widget.id ) {\n\t\t\t\t\t\tts.applyWidgetId( table, widget.id, init );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( c.debug && console.groupEnd ) { console.groupEnd(); }\n\t\t\t\t// callback executed on init only\n\t\t\t\tif ( !init && typeof callback === 'function' ) {\n\t\t\t\t\tcallback( table );\n\t\t\t\t}\n\t\t\t}\n\t\t\tc.timerReady = setTimeout( function() {\n\t\t\t\ttable.isApplyingWidgets = false;\n\t\t\t\t$.data( table, 'lastWidgetApplication', new Date() );\n\t\t\t\tc.$table.triggerHandler( 'tablesorter-ready' );\n\t\t\t}, 10 );\n\t\t\tif ( c.debug ) {\n\t\t\t\twidget = c.widgets.length;\n\t\t\t\tconsole.log( 'Completed ' +\n\t\t\t\t\t( init === true ? 'initializing ' : 'applying ' ) + widget +\n\t\t\t\t\t' widget' + ( widget !== 1 ? 's' : '' ) + ts.benchmark( time ) );\n\t\t\t}\n\t\t},\n\n\t\tremoveWidget : function( table, name, refreshing ) {\n\t\t\ttable = $( table )[ 0 ];\n\t\t\tvar index, widget, indx, len,\n\t\t\t\tc = table.config;\n\t\t\t// if name === true, add all widgets from $.tablesorter.widgets\n\t\t\tif ( name === true ) {\n\t\t\t\tname = [];\n\t\t\t\tlen = ts.widgets.length;\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\twidget = ts.widgets[ indx ];\n\t\t\t\t\tif ( widget && widget.id ) {\n\t\t\t\t\t\tname[ name.length ] = widget.id;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// name can be either an array of widgets names,\n\t\t\t\t// or a space/comma separated list of widget names\n\t\t\t\tname = ( $.isArray( name ) ? name.join( ',' ) : name || '' ).toLowerCase().split( /[\\s,]+/ );\n\t\t\t}\n\t\t\tlen = name.length;\n\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\twidget = ts.getWidgetById( name[ index ] );\n\t\t\t\tindx = $.inArray( name[ index ], c.widgets );\n\t\t\t\t// don't remove the widget from config.widget if refreshing\n\t\t\t\tif ( indx >= 0 && refreshing !== true ) {\n\t\t\t\t\tc.widgets.splice( indx, 1 );\n\t\t\t\t}\n\t\t\t\tif ( widget && widget.remove ) {\n\t\t\t\t\tif ( c.debug ) {\n\t\t\t\t\t\tconsole.log( ( refreshing ? 'Refreshing' : 'Removing' ) + ' \"' + name[ index ] + '\" widget' );\n\t\t\t\t\t}\n\t\t\t\t\twidget.remove( table, c, c.widgetOptions, refreshing );\n\t\t\t\t\tc.widgetInit[ name[ index ] ] = false;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\trefreshWidgets : function( table, doAll, dontapply ) {\n\t\t\ttable = $( table )[ 0 ]; // see issue #243\n\t\t\tvar indx, widget,\n\t\t\t\tc = table.config,\n\t\t\t\tcurWidgets = c.widgets,\n\t\t\t\twidgets = ts.widgets,\n\t\t\t\tlen = widgets.length,\n\t\t\t\tlist = [],\n\t\t\t\tcallback = function( table ) {\n\t\t\t\t\t$( table ).triggerHandler( 'refreshComplete' );\n\t\t\t\t};\n\t\t\t// remove widgets not defined in config.widgets, unless doAll is true\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\twidget = widgets[ indx ];\n\t\t\t\tif ( widget && widget.id && ( doAll || $.inArray( widget.id, curWidgets ) < 0 ) ) {\n\t\t\t\t\tlist[ list.length ] = widget.id;\n\t\t\t\t}\n\t\t\t}\n\t\t\tts.removeWidget( table, list.join( ',' ), true );\n\t\t\tif ( dontapply !== true ) {\n\t\t\t\t// call widget init if\n\t\t\t\tts.applyWidget( table, doAll || false, callback );\n\t\t\t\tif ( doAll ) {\n\t\t\t\t\t// apply widget format\n\t\t\t\t\tts.applyWidget( table, false, callback );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcallback( table );\n\t\t\t}\n\t\t},\n\n\t\t/*\n\t\t██ ██ ██████ ██ ██ ██ ██████ ██ ██████ ▄█████\n\t\t██ ██ ██ ██ ██ ██ ██ ██ ██▄▄ ▀█▄\n\t\t██ ██ ██ ██ ██ ██ ██ ██ ██▀▀ ▀█▄\n\t\t▀████▀ ██ ██ ██████ ██ ██ ██ ██████ █████▀\n\t\t*/\n\t\tbenchmark : function( diff ) {\n\t\t\treturn ( ' (' + ( new Date().getTime() - diff.getTime() ) + ' ms)' );\n\t\t},\n\t\t// deprecated ts.log\n\t\tlog : function() {\n\t\t\tconsole.log( arguments );\n\t\t},\n\n\t\t// $.isEmptyObject from jQuery v1.4\n\t\tisEmptyObject : function( obj ) {\n\t\t\t/*jshint forin: false */\n\t\t\tfor ( var name in obj ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\tisValueInArray : function( column, arry ) {\n\t\t\tvar indx,\n\t\t\t\tlen = arry && arry.length || 0;\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\tif ( arry[ indx ][ 0 ] === column ) {\n\t\t\t\t\treturn indx;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn -1;\n\t\t},\n\n\t\tformatFloat : function( str, table ) {\n\t\t\tif ( typeof str !== 'string' || str === '' ) { return str; }\n\t\t\t// allow using formatFloat without a table; defaults to US number format\n\t\t\tvar num,\n\t\t\t\tusFormat = table && table.config ? table.config.usNumberFormat !== false :\n\t\t\t\t\ttypeof table !== 'undefined' ? table : true;\n\t\t\tif ( usFormat ) {\n\t\t\t\t// US Format - 1,234,567.89 -> 1234567.89\n\t\t\t\tstr = str.replace( ts.regex.comma, '' );\n\t\t\t} else {\n\t\t\t\t// German Format = 1.234.567,89 -> 1234567.89\n\t\t\t\t// French Format = 1 234 567,89 -> 1234567.89\n\t\t\t\tstr = str.replace( ts.regex.digitNonUS, '' ).replace( ts.regex.comma, '.' );\n\t\t\t}\n\t\t\tif ( ts.regex.digitNegativeTest.test( str ) ) {\n\t\t\t\t// make (#) into a negative number -> (10) = -10\n\t\t\t\tstr = str.replace( ts.regex.digitNegativeReplace, '-$1' );\n\t\t\t}\n\t\t\tnum = parseFloat( str );\n\t\t\t// return the text instead of zero\n\t\t\treturn isNaN( num ) ? $.trim( str ) : num;\n\t\t},\n\n\t\tisDigit : function( str ) {\n\t\t\t// replace all unwanted chars and match\n\t\t\treturn isNaN( str ) ?\n\t\t\t\tts.regex.digitTest.test( str.toString().replace( ts.regex.digitReplace, '' ) ) :\n\t\t\t\tstr !== '';\n\t\t},\n\n\t\t// computeTableHeaderCellIndexes from:\n\t\t// http://www.javascripttoolbox.com/lib/table/examples.php\n\t\t// http://www.javascripttoolbox.com/temp/table_cellindex.html\n\t\tcomputeColumnIndex : function( $rows, c ) {\n\t\t\tvar i, j, k, l, cell, cells, rowIndex, rowSpan, colSpan, firstAvailCol,\n\t\t\t\t// total columns has been calculated, use it to set the matrixrow\n\t\t\t\tcolumns = c && c.columns || 0,\n\t\t\t\tmatrix = [],\n\t\t\t\tmatrixrow = new Array( columns );\n\t\t\tfor ( i = 0; i < $rows.length; i++ ) {\n\t\t\t\tcells = $rows[ i ].cells;\n\t\t\t\tfor ( j = 0; j < cells.length; j++ ) {\n\t\t\t\t\tcell = cells[ j ];\n\t\t\t\t\trowIndex = cell.parentNode.rowIndex;\n\t\t\t\t\trowSpan = cell.rowSpan || 1;\n\t\t\t\t\tcolSpan = cell.colSpan || 1;\n\t\t\t\t\tif ( typeof matrix[ rowIndex ] === 'undefined' ) {\n\t\t\t\t\t\tmatrix[ rowIndex ] = [];\n\t\t\t\t\t}\n\t\t\t\t\t// Find first available column in the first row\n\t\t\t\t\tfor ( k = 0; k < matrix[ rowIndex ].length + 1; k++ ) {\n\t\t\t\t\t\tif ( typeof matrix[ rowIndex ][ k ] === 'undefined' ) {\n\t\t\t\t\t\t\tfirstAvailCol = k;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// jscs:disable disallowEmptyBlocks\n\t\t\t\t\tif ( columns && cell.cellIndex === firstAvailCol ) {\n\t\t\t\t\t\t// don't to anything\n\t\t\t\t\t} else if ( cell.setAttribute ) {\n\t\t\t\t\t\t// jscs:enable disallowEmptyBlocks\n\t\t\t\t\t\t// add data-column (setAttribute = IE8+)\n\t\t\t\t\t\tcell.setAttribute( 'data-column', firstAvailCol );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// remove once we drop support for IE7 - 1/12/2016\n\t\t\t\t\t\t$( cell ).attr( 'data-column', firstAvailCol );\n\t\t\t\t\t}\n\t\t\t\t\tfor ( k = rowIndex; k < rowIndex + rowSpan; k++ ) {\n\t\t\t\t\t\tif ( typeof matrix[ k ] === 'undefined' ) {\n\t\t\t\t\t\t\tmatrix[ k ] = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatrixrow = matrix[ k ];\n\t\t\t\t\t\tfor ( l = firstAvailCol; l < firstAvailCol + colSpan; l++ ) {\n\t\t\t\t\t\t\tmatrixrow[ l ] = 'x';\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn matrixrow.length;\n\t\t},\n\n\t\t// automatically add a colgroup with col elements set to a percentage width\n\t\tfixColumnWidth : function( table ) {\n\t\t\ttable = $( table )[ 0 ];\n\t\t\tvar overallWidth, percent, $tbodies, len, index,\n\t\t\t\tc = table.config,\n\t\t\t\t$colgroup = c.$table.children( 'colgroup' );\n\t\t\t// remove plugin-added colgroup, in case we need to refresh the widths\n\t\t\tif ( $colgroup.length && $colgroup.hasClass( ts.css.colgroup ) ) {\n\t\t\t\t$colgroup.remove();\n\t\t\t}\n\t\t\tif ( c.widthFixed && c.$table.children( 'colgroup' ).length === 0 ) {\n\t\t\t\t$colgroup = $( '<colgroup class=\"' + ts.css.colgroup + '\">' );\n\t\t\t\toverallWidth = c.$table.width();\n\t\t\t\t// only add col for visible columns - fixes #371\n\t\t\t\t$tbodies = c.$tbodies.find( 'tr:first' ).children( ':visible' );\n\t\t\t\tlen = $tbodies.length;\n\t\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\t\tpercent = parseInt( ( $tbodies.eq( index ).width() / overallWidth ) * 1000, 10 ) / 10 + '%';\n\t\t\t\t\t$colgroup.append( $( '<col>' ).css( 'width', percent ) );\n\t\t\t\t}\n\t\t\t\tc.$table.prepend( $colgroup );\n\t\t\t}\n\t\t},\n\n\t\t// get sorter, string, empty, etc options for each column from\n\t\t// jQuery data, metadata, header option or header class name ('sorter-false')\n\t\t// priority = jQuery data > meta > headers option > header class name\n\t\tgetData : function( header, configHeader, key ) {\n\t\t\tvar meta, cl4ss,\n\t\t\t\tval = '',\n\t\t\t\t$header = $( header );\n\t\t\tif ( !$header.length ) { return ''; }\n\t\t\tmeta = $.metadata ? $header.metadata() : false;\n\t\t\tcl4ss = ' ' + ( $header.attr( 'class' ) || '' );\n\t\t\tif ( typeof $header.data( key ) !== 'undefined' ||\n\t\t\t\ttypeof $header.data( key.toLowerCase() ) !== 'undefined' ) {\n\t\t\t\t// 'data-lockedOrder' is assigned to 'lockedorder'; but 'data-locked-order' is assigned to 'lockedOrder'\n\t\t\t\t// 'data-sort-initial-order' is assigned to 'sortInitialOrder'\n\t\t\t\tval += $header.data( key ) || $header.data( key.toLowerCase() );\n\t\t\t} else if ( meta && typeof meta[ key ] !== 'undefined' ) {\n\t\t\t\tval += meta[ key ];\n\t\t\t} else if ( configHeader && typeof configHeader[ key ] !== 'undefined' ) {\n\t\t\t\tval += configHeader[ key ];\n\t\t\t} else if ( cl4ss !== ' ' && cl4ss.match( ' ' + key + '-' ) ) {\n\t\t\t\t// include sorter class name 'sorter-text', etc; now works with 'sorter-my-custom-parser'\n\t\t\t\tval = cl4ss.match( new RegExp( '\\\\s' + key + '-([\\\\w-]+)' ) )[ 1 ] || '';\n\t\t\t}\n\t\t\treturn $.trim( val );\n\t\t},\n\n\t\tgetColumnData : function( table, obj, indx, getCell, $headers ) {\n\t\t\tif ( typeof obj !== 'object' || obj === null ) {\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t\ttable = $( table )[ 0 ];\n\t\t\tvar $header, key,\n\t\t\t\tc = table.config,\n\t\t\t\t$cells = ( $headers || c.$headers ),\n\t\t\t\t// c.$headerIndexed is not defined initially\n\t\t\t\t$cell = c.$headerIndexed && c.$headerIndexed[ indx ] ||\n\t\t\t\t\t$cells.filter( '[data-column=\"' + indx + '\"]:last' );\n\t\t\tif ( typeof obj[ indx ] !== 'undefined' ) {\n\t\t\t\treturn getCell ? obj[ indx ] : obj[ $cells.index( $cell ) ];\n\t\t\t}\n\t\t\tfor ( key in obj ) {\n\t\t\t\tif ( typeof key === 'string' ) {\n\t\t\t\t\t$header = $cell\n\t\t\t\t\t\t// header cell with class/id\n\t\t\t\t\t\t.filter( key )\n\t\t\t\t\t\t// find elements within the header cell with cell/id\n\t\t\t\t\t\t.add( $cell.find( key ) );\n\t\t\t\t\tif ( $header.length ) {\n\t\t\t\t\t\treturn obj[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t},\n\n\t\t// *** Process table ***\n\t\t// add processing indicator\n\t\tisProcessing : function( $table, toggle, $headers ) {\n\t\t\t$table = $( $table );\n\t\t\tvar c = $table[ 0 ].config,\n\t\t\t\t// default to all headers\n\t\t\t\t$header = $headers || $table.find( '.' + ts.css.header );\n\t\t\tif ( toggle ) {\n\t\t\t\t// don't use sortList if custom $headers used\n\t\t\t\tif ( typeof $headers !== 'undefined' && c.sortList.length > 0 ) {\n\t\t\t\t\t// get headers from the sortList\n\t\t\t\t\t$header = $header.filter( function() {\n\t\t\t\t\t\t// get data-column from attr to keep compatibility with jQuery 1.2.6\n\t\t\t\t\t\treturn this.sortDisabled ?\n\t\t\t\t\t\t\tfalse :\n\t\t\t\t\t\t\tts.isValueInArray( parseFloat( $( this ).attr( 'data-column' ) ), c.sortList ) >= 0;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t$table.add( $header ).addClass( ts.css.processing + ' ' + c.cssProcessing );\n\t\t\t} else {\n\t\t\t\t$table.add( $header ).removeClass( ts.css.processing + ' ' + c.cssProcessing );\n\t\t\t}\n\t\t},\n\n\t\t// detach tbody but save the position\n\t\t// don't use tbody because there are portions that look for a tbody index (updateCell)\n\t\tprocessTbody : function( table, $tb, getIt ) {\n\t\t\ttable = $( table )[ 0 ];\n\t\t\tif ( getIt ) {\n\t\t\t\ttable.isProcessing = true;\n\t\t\t\t$tb.before( '<colgroup class=\"tablesorter-savemyplace\"/>' );\n\t\t\t\treturn $.fn.detach ? $tb.detach() : $tb.remove();\n\t\t\t}\n\t\t\tvar holdr = $( table ).find( 'colgroup.tablesorter-savemyplace' );\n\t\t\t$tb.insertAfter( holdr );\n\t\t\tholdr.remove();\n\t\t\ttable.isProcessing = false;\n\t\t},\n\n\t\tclearTableBody : function( table ) {\n\t\t\t$( table )[ 0 ].config.$tbodies.children().detach();\n\t\t},\n\n\t\t// used when replacing accented characters during sorting\n\t\tcharacterEquivalents : {\n\t\t\t'a' : '\\u00e1\\u00e0\\u00e2\\u00e3\\u00e4\\u0105\\u00e5', // áàâãäąå\n\t\t\t'A' : '\\u00c1\\u00c0\\u00c2\\u00c3\\u00c4\\u0104\\u00c5', // ÁÀÂÃÄĄÅ\n\t\t\t'c' : '\\u00e7\\u0107\\u010d', // çćč\n\t\t\t'C' : '\\u00c7\\u0106\\u010c', // ÇĆČ\n\t\t\t'e' : '\\u00e9\\u00e8\\u00ea\\u00eb\\u011b\\u0119', // éèêëěę\n\t\t\t'E' : '\\u00c9\\u00c8\\u00ca\\u00cb\\u011a\\u0118', // ÉÈÊËĚĘ\n\t\t\t'i' : '\\u00ed\\u00ec\\u0130\\u00ee\\u00ef\\u0131', // íìİîïı\n\t\t\t'I' : '\\u00cd\\u00cc\\u0130\\u00ce\\u00cf', // ÍÌİÎÏ\n\t\t\t'o' : '\\u00f3\\u00f2\\u00f4\\u00f5\\u00f6\\u014d', // óòôõöō\n\t\t\t'O' : '\\u00d3\\u00d2\\u00d4\\u00d5\\u00d6\\u014c', // ÓÒÔÕÖŌ\n\t\t\t'ss': '\\u00df', // ß (s sharp)\n\t\t\t'SS': '\\u1e9e', // ẞ (Capital sharp s)\n\t\t\t'u' : '\\u00fa\\u00f9\\u00fb\\u00fc\\u016f', // úùûüů\n\t\t\t'U' : '\\u00da\\u00d9\\u00db\\u00dc\\u016e' // ÚÙÛÜŮ\n\t\t},\n\n\t\treplaceAccents : function( str ) {\n\t\t\tvar chr,\n\t\t\t\tacc = '[',\n\t\t\t\teq = ts.characterEquivalents;\n\t\t\tif ( !ts.characterRegex ) {\n\t\t\t\tts.characterRegexArray = {};\n\t\t\t\tfor ( chr in eq ) {\n\t\t\t\t\tif ( typeof chr === 'string' ) {\n\t\t\t\t\t\tacc += eq[ chr ];\n\t\t\t\t\t\tts.characterRegexArray[ chr ] = new RegExp( '[' + eq[ chr ] + ']', 'g' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tts.characterRegex = new RegExp( acc + ']' );\n\t\t\t}\n\t\t\tif ( ts.characterRegex.test( str ) ) {\n\t\t\t\tfor ( chr in eq ) {\n\t\t\t\t\tif ( typeof chr === 'string' ) {\n\t\t\t\t\t\tstr = str.replace( ts.characterRegexArray[ chr ], chr );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn str;\n\t\t},\n\n\t\tvalidateOptions : function( c ) {\n\t\t\tvar setting, setting2, typ, timer,\n\t\t\t\t// ignore options containing an array\n\t\t\t\tignore = 'headers sortForce sortList sortAppend widgets'.split( ' ' ),\n\t\t\t\torig = c.originalSettings;\n\t\t\tif ( orig ) {\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\ttimer = new Date();\n\t\t\t\t}\n\t\t\t\tfor ( setting in orig ) {\n\t\t\t\t\ttyp = typeof ts.defaults[setting];\n\t\t\t\t\tif ( typ === 'undefined' ) {\n\t\t\t\t\t\tconsole.warn( 'Tablesorter Warning! \"table.config.' + setting + '\" option not recognized' );\n\t\t\t\t\t} else if ( typ === 'object' ) {\n\t\t\t\t\t\tfor ( setting2 in orig[setting] ) {\n\t\t\t\t\t\t\ttyp = ts.defaults[setting] && typeof ts.defaults[setting][setting2];\n\t\t\t\t\t\t\tif ( $.inArray( setting, ignore ) < 0 && typ === 'undefined' ) {\n\t\t\t\t\t\t\t\tconsole.warn( 'Tablesorter Warning! \"table.config.' + setting + '.' + setting2 + '\" option not recognized' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( c.debug ) {\n\t\t\t\t\tconsole.log( 'validate options time:' + ts.benchmark( timer ) );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// restore headers\n\t\trestoreHeaders : function( table ) {\n\t\t\tvar index, $cell,\n\t\t\t\tc = $( table )[ 0 ].config,\n\t\t\t\t$headers = c.$table.find( c.selectorHeaders ),\n\t\t\t\tlen = $headers.length;\n\t\t\t// don't use c.$headers here in case header cells were swapped\n\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\t$cell = $headers.eq( index );\n\t\t\t\t// only restore header cells if it is wrapped\n\t\t\t\t// because this is also used by the updateAll method\n\t\t\t\tif ( $cell.find( '.' + ts.css.headerIn ).length ) {\n\t\t\t\t\t$cell.html( c.headerContent[ index ] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tdestroy : function( table, removeClasses, callback ) {\n\t\t\ttable = $( table )[ 0 ];\n\t\t\tif ( !table.hasInitialized ) { return; }\n\t\t\t// remove all widgets\n\t\t\tts.removeWidget( table, true, false );\n\t\t\tvar events,\n\t\t\t\t$t = $( table ),\n\t\t\t\tc = table.config,\n\t\t\t\tdebug = c.debug,\n\t\t\t\t$h = $t.find( 'thead:first' ),\n\t\t\t\t$r = $h.find( 'tr.' + ts.css.headerRow ).removeClass( ts.css.headerRow + ' ' + c.cssHeaderRow ),\n\t\t\t\t$f = $t.find( 'tfoot:first > tr' ).children( 'th, td' );\n\t\t\tif ( removeClasses === false && $.inArray( 'uitheme', c.widgets ) >= 0 ) {\n\t\t\t\t// reapply uitheme classes, in case we want to maintain appearance\n\t\t\t\t$t.triggerHandler( 'applyWidgetId', [ 'uitheme' ] );\n\t\t\t\t$t.triggerHandler( 'applyWidgetId', [ 'zebra' ] );\n\t\t\t}\n\t\t\t// remove widget added rows, just in case\n\t\t\t$h.find( 'tr' ).not( $r ).remove();\n\t\t\t// disable tablesorter - not using .unbind( namespace ) because namespacing was\n\t\t\t// added in jQuery v1.4.3 - see http://api.jquery.com/event.namespace/\n\t\t\tevents = 'sortReset update updateRows updateAll updateHeaders updateCell addRows updateComplete sorton ' +\n\t\t\t\t'appendCache updateCache applyWidgetId applyWidgets refreshWidgets removeWidget destroy mouseup mouseleave ' +\n\t\t\t\t'keypress sortBegin sortEnd resetToLoadState '.split( ' ' )\n\t\t\t\t.join( c.namespace + ' ' );\n\t\t\t$t\n\t\t\t\t.removeData( 'tablesorter' )\n\t\t\t\t.unbind( events.replace( ts.regex.spaces, ' ' ) );\n\t\t\tc.$headers\n\t\t\t\t.add( $f )\n\t\t\t\t.removeClass( [ ts.css.header, c.cssHeader, c.cssAsc, c.cssDesc, ts.css.sortAsc, ts.css.sortDesc, ts.css.sortNone ].join( ' ' ) )\n\t\t\t\t.removeAttr( 'data-column' )\n\t\t\t\t.removeAttr( 'aria-label' )\n\t\t\t\t.attr( 'aria-disabled', 'true' );\n\t\t\t$r\n\t\t\t\t.find( c.selectorSort )\n\t\t\t\t.unbind( ( 'mousedown mouseup keypress '.split( ' ' ).join( c.namespace + ' ' ) ).replace( ts.regex.spaces, ' ' ) );\n\t\t\tts.restoreHeaders( table );\n\t\t\t$t.toggleClass( ts.css.table + ' ' + c.tableClass + ' tablesorter-' + c.theme, removeClasses === false );\n\t\t\t// clear flag in case the plugin is initialized again\n\t\t\ttable.hasInitialized = false;\n\t\t\tdelete table.config.cache;\n\t\t\tif ( typeof callback === 'function' ) {\n\t\t\t\tcallback( table );\n\t\t\t}\n\t\t\tif ( debug ) {\n\t\t\t\tconsole.log( 'tablesorter has been removed' );\n\t\t\t}\n\t\t}\n\n\t};\n\n\t$.fn.tablesorter = function( settings ) {\n\t\treturn this.each( function() {\n\t\t\tvar table = this,\n\t\t\t// merge & extend config options\n\t\t\tc = $.extend( true, {}, ts.defaults, settings, ts.instanceMethods );\n\t\t\t// save initial settings\n\t\t\tc.originalSettings = settings;\n\t\t\t// create a table from data (build table widget)\n\t\t\tif ( !table.hasInitialized && ts.buildTable && this.nodeName !== 'TABLE' ) {\n\t\t\t\t// return the table (in case the original target is the table's container)\n\t\t\t\tts.buildTable( table, c );\n\t\t\t} else {\n\t\t\t\tts.setup( table, c );\n\t\t\t}\n\t\t});\n\t};\n\n\t// set up debug logs\n\tif ( !( window.console && window.console.log ) ) {\n\t\t// access $.tablesorter.logs for browsers that don't have a console...\n\t\tts.logs = [];\n\t\t/*jshint -W020 */\n\t\tconsole = {};\n\t\tconsole.log = console.warn = console.error = console.table = function() {\n\t\t\tvar arg = arguments.length > 1 ? arguments : arguments[0];\n\t\t\tts.logs[ ts.logs.length ] = { date: Date.now(), log: arg };\n\t\t};\n\t}\n\n\t// add default parsers\n\tts.addParser({\n\t\tid : 'no-parser',\n\t\tis : function() {\n\t\t\treturn false;\n\t\t},\n\t\tformat : function() {\n\t\t\treturn '';\n\t\t},\n\t\ttype : 'text'\n\t});\n\n\tts.addParser({\n\t\tid : 'text',\n\t\tis : function() {\n\t\t\treturn true;\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\tvar c = table.config;\n\t\t\tif ( str ) {\n\t\t\t\tstr = $.trim( c.ignoreCase ? str.toLocaleLowerCase() : str );\n\t\t\t\tstr = c.sortLocaleCompare ? ts.replaceAccents( str ) : str;\n\t\t\t}\n\t\t\treturn str;\n\t\t},\n\t\ttype : 'text'\n\t});\n\n\tts.regex.nondigit = /[^\\w,. \\-()]/g;\n\tts.addParser({\n\t\tid : 'digit',\n\t\tis : function( str ) {\n\t\t\treturn ts.isDigit( str );\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\tvar num = ts.formatFloat( ( str || '' ).replace( ts.regex.nondigit, '' ), table );\n\t\t\treturn str && typeof num === 'number' ? num :\n\t\t\t\tstr ? $.trim( str && table.config.ignoreCase ? str.toLocaleLowerCase() : str ) : str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\tts.regex.currencyReplace = /[+\\-,. ]/g;\n\tts.regex.currencyTest = /^\\(?\\d+[\\u00a3$\\u20ac\\u00a4\\u00a5\\u00a2?.]|[\\u00a3$\\u20ac\\u00a4\\u00a5\\u00a2?.]\\d+\\)?$/;\n\tts.addParser({\n\t\tid : 'currency',\n\t\tis : function( str ) {\n\t\t\tstr = ( str || '' ).replace( ts.regex.currencyReplace, '' );\n\t\t\t// test for £$€¤¥¢\n\t\t\treturn ts.regex.currencyTest.test( str );\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\tvar num = ts.formatFloat( ( str || '' ).replace( ts.regex.nondigit, '' ), table );\n\t\t\treturn str && typeof num === 'number' ? num :\n\t\t\t\tstr ? $.trim( str && table.config.ignoreCase ? str.toLocaleLowerCase() : str ) : str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\t// too many protocols to add them all https://en.wikipedia.org/wiki/URI_scheme\n\t// now, this regex can be updated before initialization\n\tts.regex.urlProtocolTest = /^(https?|ftp|file):\\/\\//;\n\tts.regex.urlProtocolReplace = /(https?|ftp|file):\\/\\/(www\\.)?/;\n\tts.addParser({\n\t\tid : 'url',\n\t\tis : function( str ) {\n\t\t\treturn ts.regex.urlProtocolTest.test( str );\n\t\t},\n\t\tformat : function( str ) {\n\t\t\treturn str ? $.trim( str.replace( ts.regex.urlProtocolReplace, '' ) ) : str;\n\t\t},\n\t\ttype : 'text'\n\t});\n\n\tts.regex.dash = /-/g;\n\tts.regex.isoDate = /^\\d{4}[\\/\\-]\\d{1,2}[\\/\\-]\\d{1,2}/;\n\tts.addParser({\n\t\tid : 'isoDate',\n\t\tis : function( str ) {\n\t\t\treturn ts.regex.isoDate.test( str );\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\tvar date = str ? new Date( str.replace( ts.regex.dash, '/' ) ) : str;\n\t\t\treturn date instanceof Date && isFinite( date ) ? date.getTime() : str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\tts.regex.percent = /%/g;\n\tts.regex.percentTest = /(\\d\\s*?%|%\\s*?\\d)/;\n\tts.addParser({\n\t\tid : 'percent',\n\t\tis : function( str ) {\n\t\t\treturn ts.regex.percentTest.test( str ) && str.length < 15;\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\treturn str ? ts.formatFloat( str.replace( ts.regex.percent, '' ), table ) : str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\t// added image parser to core v2.17.9\n\tts.addParser({\n\t\tid : 'image',\n\t\tis : function( str, table, node, $node ) {\n\t\t\treturn $node.find( 'img' ).length > 0;\n\t\t},\n\t\tformat : function( str, table, cell ) {\n\t\t\treturn $( cell ).find( 'img' ).attr( table.config.imgAttr || 'alt' ) || str;\n\t\t},\n\t\tparsed : true, // filter widget flag\n\t\ttype : 'text'\n\t});\n\n\tts.regex.dateReplace = /(\\S)([AP]M)$/i; // used by usLongDate & time parser\n\tts.regex.usLongDateTest1 = /^[A-Z]{3,10}\\.?\\s+\\d{1,2},?\\s+(\\d{4})(\\s+\\d{1,2}:\\d{2}(:\\d{2})?(\\s+[AP]M)?)?$/i;\n\tts.regex.usLongDateTest2 = /^\\d{1,2}\\s+[A-Z]{3,10}\\s+\\d{4}/i;\n\tts.addParser({\n\t\tid : 'usLongDate',\n\t\tis : function( str ) {\n\t\t\t// two digit years are not allowed cross-browser\n\t\t\t// Jan 01, 2013 12:34:56 PM or 01 Jan 2013\n\t\t\treturn ts.regex.usLongDateTest1.test( str ) || ts.regex.usLongDateTest2.test( str );\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\tvar date = str ? new Date( str.replace( ts.regex.dateReplace, '$1 $2' ) ) : str;\n\t\t\treturn date instanceof Date && isFinite( date ) ? date.getTime() : str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\t// testing for ##-##-#### or ####-##-##, so it's not perfect; time can be included\n\tts.regex.shortDateTest = /(^\\d{1,2}[\\/\\s]\\d{1,2}[\\/\\s]\\d{4})|(^\\d{4}[\\/\\s]\\d{1,2}[\\/\\s]\\d{1,2})/;\n\t// escaped \"-\" because JSHint in Firefox was showing it as an error\n\tts.regex.shortDateReplace = /[\\-.,]/g;\n\t// XXY covers MDY & DMY formats\n\tts.regex.shortDateXXY = /(\\d{1,2})[\\/\\s](\\d{1,2})[\\/\\s](\\d{4})/;\n\tts.regex.shortDateYMD = /(\\d{4})[\\/\\s](\\d{1,2})[\\/\\s](\\d{1,2})/;\n\tts.convertFormat = function( dateString, format ) {\n\t\tdateString = ( dateString || '' )\n\t\t\t.replace( ts.regex.spaces, ' ' )\n\t\t\t.replace( ts.regex.shortDateReplace, '/' );\n\t\tif ( format === 'mmddyyyy' ) {\n\t\t\tdateString = dateString.replace( ts.regex.shortDateXXY, '$3/$1/$2' );\n\t\t} else if ( format === 'ddmmyyyy' ) {\n\t\t\tdateString = dateString.replace( ts.regex.shortDateXXY, '$3/$2/$1' );\n\t\t} else if ( format === 'yyyymmdd' ) {\n\t\t\tdateString = dateString.replace( ts.regex.shortDateYMD, '$1/$2/$3' );\n\t\t}\n\t\tvar date = new Date( dateString );\n\t\treturn date instanceof Date && isFinite( date ) ? date.getTime() : '';\n\t};\n\n\tts.addParser({\n\t\tid : 'shortDate', // 'mmddyyyy', 'ddmmyyyy' or 'yyyymmdd'\n\t\tis : function( str ) {\n\t\t\tstr = ( str || '' ).replace( ts.regex.spaces, ' ' ).replace( ts.regex.shortDateReplace, '/' );\n\t\t\treturn ts.regex.shortDateTest.test( str );\n\t\t},\n\t\tformat : function( str, table, cell, cellIndex ) {\n\t\t\tif ( str ) {\n\t\t\t\tvar c = table.config,\n\t\t\t\t\t$header = c.$headerIndexed[ cellIndex ],\n\t\t\t\t\tformat = $header.length && $header.data( 'dateFormat' ) ||\n\t\t\t\t\t\tts.getData( $header, ts.getColumnData( table, c.headers, cellIndex ), 'dateFormat' ) ||\n\t\t\t\t\t\tc.dateFormat;\n\t\t\t\t// save format because getData can be slow...\n\t\t\t\tif ( $header.length ) {\n\t\t\t\t\t$header.data( 'dateFormat', format );\n\t\t\t\t}\n\t\t\t\treturn ts.convertFormat( str, format ) || str;\n\t\t\t}\n\t\t\treturn str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\t// match 24 hour time & 12 hours time + am/pm - see http://regexr.com/3c3tk\n\tts.regex.timeTest = /^(0?[1-9]|1[0-2]):([0-5]\\d)(\\s[AP]M)$|^((?:[01]\\d|[2][0-4]):[0-5]\\d)$/i;\n\tts.regex.timeMatch = /(0?[1-9]|1[0-2]):([0-5]\\d)(\\s[AP]M)|((?:[01]\\d|[2][0-4]):[0-5]\\d)/i;\n\tts.addParser({\n\t\tid : 'time',\n\t\tis : function( str ) {\n\t\t\treturn ts.regex.timeTest.test( str );\n\t\t},\n\t\tformat : function( str, table ) {\n\t\t\t// isolate time... ignore month, day and year\n\t\t\tvar temp,\n\t\t\t\ttimePart = ( str || '' ).match( ts.regex.timeMatch ),\n\t\t\t\torig = new Date( str ),\n\t\t\t\t// no time component? default to 00:00 by leaving it out, but only if str is defined\n\t\t\t\ttime = str && ( timePart !== null ? timePart[ 0 ] : '00:00 AM' ),\n\t\t\t\tdate = time ? new Date( '2000/01/01 ' + time.replace( ts.regex.dateReplace, '$1 $2' ) ) : time;\n\t\t\tif ( date instanceof Date && isFinite( date ) ) {\n\t\t\t\ttemp = orig instanceof Date && isFinite( orig ) ? orig.getTime() : 0;\n\t\t\t\t// if original string was a valid date, add it to the decimal so the column sorts in some kind of order\n\t\t\t\t// luckily new Date() ignores the decimals\n\t\t\t\treturn temp ? parseFloat( date.getTime() + '.' + orig.getTime() ) : date.getTime();\n\t\t\t}\n\t\t\treturn str;\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\tts.addParser({\n\t\tid : 'metadata',\n\t\tis : function() {\n\t\t\treturn false;\n\t\t},\n\t\tformat : function( str, table, cell ) {\n\t\t\tvar c = table.config,\n\t\t\tp = ( !c.parserMetadataName ) ? 'sortValue' : c.parserMetadataName;\n\t\t\treturn $( cell ).metadata()[ p ];\n\t\t},\n\t\ttype : 'numeric'\n\t});\n\n\t/*\n\t\t██████ ██████ █████▄ █████▄ ▄████▄\n\t\t ▄█▀ ██▄▄ ██▄▄██ ██▄▄██ ██▄▄██\n\t\t▄█▀ ██▀▀ ██▀▀██ ██▀▀█ ██▀▀██\n\t\t██████ ██████ █████▀ ██ ██ ██ ██\n\t\t*/\n\t// add default widgets\n\tts.addWidget({\n\t\tid : 'zebra',\n\t\tpriority : 90,\n\t\tformat : function( table, c, wo ) {\n\t\t\tvar $visibleRows, $row, count, isEven, tbodyIndex, rowIndex, len,\n\t\t\t\tchild = new RegExp( c.cssChildRow, 'i' ),\n\t\t\t\t$tbodies = c.$tbodies.add( $( c.namespace + '_extra_table' ).children( 'tbody:not(.' + c.cssInfoBlock + ')' ) );\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {\n\t\t\t\t// loop through the visible rows\n\t\t\t\tcount = 0;\n\t\t\t\t$visibleRows = $tbodies.eq( tbodyIndex ).children( 'tr:visible' ).not( c.selectorRemove );\n\t\t\t\tlen = $visibleRows.length;\n\t\t\t\tfor ( rowIndex = 0; rowIndex < len; rowIndex++ ) {\n\t\t\t\t\t$row = $visibleRows.eq( rowIndex );\n\t\t\t\t\t// style child rows the same way the parent row was styled\n\t\t\t\t\tif ( !child.test( $row[ 0 ].className ) ) { count++; }\n\t\t\t\t\tisEven = ( count % 2 === 0 );\n\t\t\t\t\t$row\n\t\t\t\t\t\t.removeClass( wo.zebra[ isEven ? 1 : 0 ] )\n\t\t\t\t\t\t.addClass( wo.zebra[ isEven ? 0 : 1 ] );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tremove : function( table, c, wo, refreshing ) {\n\t\t\tif ( refreshing ) { return; }\n\t\t\tvar tbodyIndex, $tbody,\n\t\t\t\t$tbodies = c.$tbodies,\n\t\t\t\ttoRemove = ( wo.zebra || [ 'even', 'odd' ] ).join( ' ' );\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ){\n\t\t\t\t$tbody = ts.processTbody( table, $tbodies.eq( tbodyIndex ), true ); // remove tbody\n\t\t\t\t$tbody.children().removeClass( toRemove );\n\t\t\t\tts.processTbody( table, $tbody, false ); // restore tbody\n\t\t\t}\n\t\t}\n\t});\n\n})( jQuery );\n\n/*! Widget: storage - updated 11/26/2016 (v2.28.0) */\n/*global JSON:false */\n;(function ($, window, document) {\n\t'use strict';\n\n\tvar ts = $.tablesorter || {};\n\t// *** Store data in local storage, with a cookie fallback ***\n\t/* IE7 needs JSON library for JSON.stringify - (http://caniuse.com/#search=json)\n\t if you need it, then include https://github.com/douglascrockford/JSON-js\n\n\t $.parseJSON is not available is jQuery versions older than 1.4.1, using older\n\t versions will only allow storing information for one page at a time\n\n\t // *** Save data (JSON format only) ***\n\t // val must be valid JSON... use http://jsonlint.com/ to ensure it is valid\n\t var val = { \"mywidget\" : \"data1\" }; // valid JSON uses double quotes\n\t // $.tablesorter.storage(table, key, val);\n\t $.tablesorter.storage(table, 'tablesorter-mywidget', val);\n\n\t // *** Get data: $.tablesorter.storage(table, key); ***\n\t v = $.tablesorter.storage(table, 'tablesorter-mywidget');\n\t // val may be empty, so also check for your data\n\t val = (v && v.hasOwnProperty('mywidget')) ? v.mywidget : '';\n\t alert(val); // 'data1' if saved, or '' if not\n\t*/\n\tts.storage = function(table, key, value, options) {\n\t\ttable = $(table)[0];\n\t\tvar cookieIndex, cookies, date,\n\t\t\thasStorage = false,\n\t\t\tvalues = {},\n\t\t\tc = table.config,\n\t\t\two = c && c.widgetOptions,\n\t\t\tstorageType = ( options && options.useSessionStorage ) || ( wo && wo.storage_useSessionStorage ) ?\n\t\t\t\t'sessionStorage' : 'localStorage',\n\t\t\t$table = $(table),\n\t\t\t// id from (1) options ID, (2) table 'data-table-group' attribute, (3) widgetOptions.storage_tableId,\n\t\t\t// (4) table ID, then (5) table index\n\t\t\tid = options && options.id ||\n\t\t\t\t$table.attr( options && options.group || wo && wo.storage_group || 'data-table-group') ||\n\t\t\t\two && wo.storage_tableId || table.id || $('.tablesorter').index( $table ),\n\t\t\t// url from (1) options url, (2) table 'data-table-page' attribute, (3) widgetOptions.storage_fixedUrl,\n\t\t\t// (4) table.config.fixedUrl (deprecated), then (5) window location path\n\t\t\turl = options && options.url ||\n\t\t\t\t$table.attr(options && options.page || wo && wo.storage_page || 'data-table-page') ||\n\t\t\t\two && wo.storage_fixedUrl || c && c.fixedUrl || window.location.pathname;\n\t\t// update defaults for validator; these values must be falsy!\n\t\t$.extend(true, ts.defaults, {\n\t\t\tfixedUrl: '',\n\t\t\twidgetOptions: {\n\t\t\t\tstorage_fixedUrl: '',\n\t\t\t\tstorage_group: '',\n\t\t\t\tstorage_page: '',\n\t\t\t\tstorage_tableId: '',\n\t\t\t\tstorage_useSessionStorage: ''\n\t\t\t}\n\t\t});\n\t\t// https://gist.github.com/paulirish/5558557\n\t\tif (storageType in window) {\n\t\t\ttry {\n\t\t\t\twindow[storageType].setItem('_tmptest', 'temp');\n\t\t\t\thasStorage = true;\n\t\t\t\twindow[storageType].removeItem('_tmptest');\n\t\t\t} catch (error) {\n\t\t\t\tif (c && c.debug) {\n\t\t\t\t\tconsole.warn( storageType + ' is not supported in this browser' );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// *** get value ***\n\t\tif ($.parseJSON) {\n\t\t\tif (hasStorage) {\n\t\t\t\tvalues = $.parseJSON( window[storageType][key] || 'null' ) || {};\n\t\t\t} else {\n\t\t\t\t// old browser, using cookies\n\t\t\t\tcookies = document.cookie.split(/[;\\s|=]/);\n\t\t\t\t// add one to get from the key to the value\n\t\t\t\tcookieIndex = $.inArray(key, cookies) + 1;\n\t\t\t\tvalues = (cookieIndex !== 0) ? $.parseJSON(cookies[cookieIndex] || 'null') || {} : {};\n\t\t\t}\n\t\t}\n\t\t// allow value to be an empty string too\n\t\tif (typeof value !== 'undefined' && window.JSON && JSON.hasOwnProperty('stringify')) {\n\t\t\t// add unique identifiers = url pathname > table ID/index on page > data\n\t\t\tif (!values[url]) {\n\t\t\t\tvalues[url] = {};\n\t\t\t}\n\t\t\tvalues[url][id] = value;\n\t\t\t// *** set value ***\n\t\t\tif (hasStorage) {\n\t\t\t\twindow[storageType][key] = JSON.stringify(values);\n\t\t\t} else {\n\t\t\t\tdate = new Date();\n\t\t\t\tdate.setTime(date.getTime() + (31536e+6)); // 365 days\n\t\t\t\tdocument.cookie = key + '=' + (JSON.stringify(values)).replace(/\\\"/g, '\\\"') + '; expires=' + date.toGMTString() + '; path=/';\n\t\t\t}\n\t\t} else {\n\t\t\treturn values && values[url] ? values[url][id] : '';\n\t\t}\n\t};\n\n})(jQuery, window, document);\n\n/*! Widget: uitheme - updated 12/8/2016 (v2.28.1) */\n;(function ($) {\n\t'use strict';\n\tvar ts = $.tablesorter || {};\n\n\tts.themes = {\n\t\t'bootstrap' : {\n\t\t\ttable : 'table table-bordered table-striped',\n\t\t\tcaption : 'caption',\n\t\t\t// header class names\n\t\t\theader : 'bootstrap-header', // give the header a gradient background (theme.bootstrap_2.css)\n\t\t\tsortNone : '',\n\t\t\tsortAsc : '',\n\t\t\tsortDesc : '',\n\t\t\tactive : '', // applied when column is sorted\n\t\t\thover : '', // custom css required - a defined bootstrap style may not override other classes\n\t\t\t// icon class names\n\t\t\ticons : '', // add 'icon-white' to make them white; this icon class is added to the <i> in the header\n\t\t\ticonSortNone : 'bootstrap-icon-unsorted', // class name added to icon when column is not sorted\n\t\t\ticonSortAsc : 'icon-chevron-up glyphicon glyphicon-chevron-up', // class name added to icon when column has ascending sort\n\t\t\ticonSortDesc : 'icon-chevron-down glyphicon glyphicon-chevron-down', // class name added to icon when column has descending sort\n\t\t\tfilterRow : '', // filter row class\n\t\t\tfooterRow : '',\n\t\t\tfooterCells : '',\n\t\t\teven : '', // even row zebra striping\n\t\t\todd : '' // odd row zebra striping\n\t\t},\n\t\t'jui' : {\n\t\t\ttable : 'ui-widget ui-widget-content ui-corner-all', // table classes\n\t\t\tcaption : 'ui-widget-content',\n\t\t\t// header class names\n\t\t\theader : 'ui-widget-header ui-corner-all ui-state-default', // header classes\n\t\t\tsortNone : '',\n\t\t\tsortAsc : '',\n\t\t\tsortDesc : '',\n\t\t\tactive : 'ui-state-active', // applied when column is sorted\n\t\t\thover : 'ui-state-hover', // hover class\n\t\t\t// icon class names\n\t\t\ticons : 'ui-icon', // icon class added to the <i> in the header\n\t\t\ticonSortNone : 'ui-icon-carat-2-n-s ui-icon-caret-2-n-s', // class name added to icon when column is not sorted\n\t\t\ticonSortAsc : 'ui-icon-carat-1-n ui-icon-caret-1-n', // class name added to icon when column has ascending sort\n\t\t\ticonSortDesc : 'ui-icon-carat-1-s ui-icon-caret-1-s', // class name added to icon when column has descending sort\n\t\t\tfilterRow : '',\n\t\t\tfooterRow : '',\n\t\t\tfooterCells : '',\n\t\t\teven : 'ui-widget-content', // even row zebra striping\n\t\t\todd : 'ui-state-default' // odd row zebra striping\n\t\t}\n\t};\n\n\t$.extend(ts.css, {\n\t\twrapper : 'tablesorter-wrapper' // ui theme & resizable\n\t});\n\n\tts.addWidget({\n\t\tid: 'uitheme',\n\t\tpriority: 10,\n\t\tformat: function(table, c, wo) {\n\t\t\tvar i, tmp, hdr, icon, time, $header, $icon, $tfoot, $h, oldtheme, oldremove, oldIconRmv, hasOldTheme,\n\t\t\t\tthemesAll = ts.themes,\n\t\t\t\t$table = c.$table.add( $( c.namespace + '_extra_table' ) ),\n\t\t\t\t$headers = c.$headers.add( $( c.namespace + '_extra_headers' ) ),\n\t\t\t\ttheme = c.theme || 'jui',\n\t\t\t\tthemes = themesAll[theme] || {},\n\t\t\t\tremove = $.trim( [ themes.sortNone, themes.sortDesc, themes.sortAsc, themes.active ].join( ' ' ) ),\n\t\t\t\ticonRmv = $.trim( [ themes.iconSortNone, themes.iconSortDesc, themes.iconSortAsc ].join( ' ' ) );\n\t\t\tif (c.debug) { time = new Date(); }\n\t\t\t// initialization code - run once\n\t\t\tif (!$table.hasClass('tablesorter-' + theme) || c.theme !== c.appliedTheme || !wo.uitheme_applied) {\n\t\t\t\two.uitheme_applied = true;\n\t\t\t\toldtheme = themesAll[c.appliedTheme] || {};\n\t\t\t\thasOldTheme = !$.isEmptyObject(oldtheme);\n\t\t\t\toldremove = hasOldTheme ? [ oldtheme.sortNone, oldtheme.sortDesc, oldtheme.sortAsc, oldtheme.active ].join( ' ' ) : '';\n\t\t\t\toldIconRmv = hasOldTheme ? [ oldtheme.iconSortNone, oldtheme.iconSortDesc, oldtheme.iconSortAsc ].join( ' ' ) : '';\n\t\t\t\tif (hasOldTheme) {\n\t\t\t\t\two.zebra[0] = $.trim( ' ' + wo.zebra[0].replace(' ' + oldtheme.even, '') );\n\t\t\t\t\two.zebra[1] = $.trim( ' ' + wo.zebra[1].replace(' ' + oldtheme.odd, '') );\n\t\t\t\t\tc.$tbodies.children().removeClass( [ oldtheme.even, oldtheme.odd ].join(' ') );\n\t\t\t\t}\n\t\t\t\t// update zebra stripes\n\t\t\t\tif (themes.even) { wo.zebra[0] += ' ' + themes.even; }\n\t\t\t\tif (themes.odd) { wo.zebra[1] += ' ' + themes.odd; }\n\t\t\t\t// add caption style\n\t\t\t\t$table.children('caption')\n\t\t\t\t\t.removeClass(oldtheme.caption || '')\n\t\t\t\t\t.addClass(themes.caption);\n\t\t\t\t// add table/footer class names\n\t\t\t\t$tfoot = $table\n\t\t\t\t\t// remove other selected themes\n\t\t\t\t\t.removeClass( (c.appliedTheme ? 'tablesorter-' + (c.appliedTheme || '') : '') + ' ' + (oldtheme.table || '') )\n\t\t\t\t\t.addClass('tablesorter-' + theme + ' ' + (themes.table || '')) // add theme widget class name\n\t\t\t\t\t.children('tfoot');\n\t\t\t\tc.appliedTheme = c.theme;\n\n\t\t\t\tif ($tfoot.length) {\n\t\t\t\t\t$tfoot\n\t\t\t\t\t\t// if oldtheme.footerRow or oldtheme.footerCells are undefined, all class names are removed\n\t\t\t\t\t\t.children('tr').removeClass(oldtheme.footerRow || '').addClass(themes.footerRow)\n\t\t\t\t\t\t.children('th, td').removeClass(oldtheme.footerCells || '').addClass(themes.footerCells);\n\t\t\t\t}\n\t\t\t\t// update header classes\n\t\t\t\t$headers\n\t\t\t\t\t.removeClass( (hasOldTheme ? [ oldtheme.header, oldtheme.hover, oldremove ].join(' ') : '') || '' )\n\t\t\t\t\t.addClass(themes.header)\n\t\t\t\t\t.not('.sorter-false')\n\t\t\t\t\t.unbind('mouseenter.tsuitheme mouseleave.tsuitheme')\n\t\t\t\t\t.bind('mouseenter.tsuitheme mouseleave.tsuitheme', function(event) {\n\t\t\t\t\t\t// toggleClass with switch added in jQuery 1.3\n\t\t\t\t\t\t$(this)[ event.type === 'mouseenter' ? 'addClass' : 'removeClass' ](themes.hover || '');\n\t\t\t\t\t});\n\n\t\t\t\t$headers.each(function(){\n\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\tif (!$this.find('.' + ts.css.wrapper).length) {\n\t\t\t\t\t\t// Firefox needs this inner div to position the icon & resizer correctly\n\t\t\t\t\t\t$this.wrapInner('<div class=\"' + ts.css.wrapper + '\" style=\"position:relative;height:100%;width:100%\"></div>');\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (c.cssIcon) {\n\t\t\t\t\t// if c.cssIcon is '', then no <i> is added to the header\n\t\t\t\t\t$headers\n\t\t\t\t\t\t.find('.' + ts.css.icon)\n\t\t\t\t\t\t.removeClass(hasOldTheme ? [ oldtheme.icons, oldIconRmv ].join(' ') : '')\n\t\t\t\t\t\t.addClass(themes.icons || '');\n\t\t\t\t}\n\t\t\t\t// filter widget initializes after uitheme\n\t\t\t\tif (ts.hasWidget( c.table, 'filter' )) {\n\t\t\t\t\ttmp = function() {\n\t\t\t\t\t\t$table.children('thead').children('.' + ts.css.filterRow)\n\t\t\t\t\t\t\t.removeClass(hasOldTheme ? oldtheme.filterRow || '' : '')\n\t\t\t\t\t\t\t.addClass(themes.filterRow || '');\n\t\t\t\t\t};\n\t\t\t\t\tif (wo.filter_initialized) {\n\t\t\t\t\t\ttmp();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$table.one('filterInit', function() {\n\t\t\t\t\t\t\ttmp();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (i = 0; i < c.columns; i++) {\n\t\t\t\t$header = c.$headers\n\t\t\t\t\t.add($(c.namespace + '_extra_headers'))\n\t\t\t\t\t.not('.sorter-false')\n\t\t\t\t\t.filter('[data-column=\"' + i + '\"]');\n\t\t\t\t$icon = (ts.css.icon) ? $header.find('.' + ts.css.icon) : $();\n\t\t\t\t$h = $headers.not('.sorter-false').filter('[data-column=\"' + i + '\"]:last');\n\t\t\t\tif ($h.length) {\n\t\t\t\t\t$header.removeClass(remove);\n\t\t\t\t\t$icon.removeClass(iconRmv);\n\t\t\t\t\tif ($h[0].sortDisabled) {\n\t\t\t\t\t\t// no sort arrows for disabled columns!\n\t\t\t\t\t\t$icon.removeClass(themes.icons || '');\n\t\t\t\t\t} else {\n\t\t\t\t\t\thdr = themes.sortNone;\n\t\t\t\t\t\ticon = themes.iconSortNone;\n\t\t\t\t\t\tif ($h.hasClass(ts.css.sortAsc)) {\n\t\t\t\t\t\t\thdr = [ themes.sortAsc, themes.active ].join(' ');\n\t\t\t\t\t\t\ticon = themes.iconSortAsc;\n\t\t\t\t\t\t} else if ($h.hasClass(ts.css.sortDesc)) {\n\t\t\t\t\t\t\thdr = [ themes.sortDesc, themes.active ].join(' ');\n\t\t\t\t\t\t\ticon = themes.iconSortDesc;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$header.addClass(hdr);\n\t\t\t\t\t\t$icon.addClass(icon || '');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (c.debug) {\n\t\t\t\tconsole.log('Applying ' + theme + ' theme' + ts.benchmark(time));\n\t\t\t}\n\t\t},\n\t\tremove: function(table, c, wo, refreshing) {\n\t\t\tif (!wo.uitheme_applied) { return; }\n\t\t\tvar $table = c.$table,\n\t\t\t\ttheme = c.appliedTheme || 'jui',\n\t\t\t\tthemes = ts.themes[ theme ] || ts.themes.jui,\n\t\t\t\t$headers = $table.children('thead').children(),\n\t\t\t\tremove = themes.sortNone + ' ' + themes.sortDesc + ' ' + themes.sortAsc,\n\t\t\t\ticonRmv = themes.iconSortNone + ' ' + themes.iconSortDesc + ' ' + themes.iconSortAsc;\n\t\t\t$table.removeClass('tablesorter-' + theme + ' ' + themes.table);\n\t\t\two.uitheme_applied = false;\n\t\t\tif (refreshing) { return; }\n\t\t\t$table.find(ts.css.header).removeClass(themes.header);\n\t\t\t$headers\n\t\t\t\t.unbind('mouseenter.tsuitheme mouseleave.tsuitheme') // remove hover\n\t\t\t\t.removeClass(themes.hover + ' ' + remove + ' ' + themes.active)\n\t\t\t\t.filter('.' + ts.css.filterRow)\n\t\t\t\t.removeClass(themes.filterRow);\n\t\t\t$headers.find('.' + ts.css.icon).removeClass(themes.icons + ' ' + iconRmv);\n\t\t}\n\t});\n\n})(jQuery);\n\n/*! Widget: columns */\n;(function ($) {\n\t'use strict';\n\tvar ts = $.tablesorter || {};\n\n\tts.addWidget({\n\t\tid: 'columns',\n\t\tpriority: 30,\n\t\toptions : {\n\t\t\tcolumns : [ 'primary', 'secondary', 'tertiary' ]\n\t\t},\n\t\tformat: function(table, c, wo) {\n\t\t\tvar $tbody, tbodyIndex, $rows, rows, $row, $cells, remove, indx,\n\t\t\t$table = c.$table,\n\t\t\t$tbodies = c.$tbodies,\n\t\t\tsortList = c.sortList,\n\t\t\tlen = sortList.length,\n\t\t\t// removed c.widgetColumns support\n\t\t\tcss = wo && wo.columns || [ 'primary', 'secondary', 'tertiary' ],\n\t\t\tlast = css.length - 1;\n\t\t\tremove = css.join(' ');\n\t\t\t// check if there is a sort (on initialization there may not be one)\n\t\t\tfor (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {\n\t\t\t\t$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // detach tbody\n\t\t\t\t$rows = $tbody.children('tr');\n\t\t\t\t// loop through the visible rows\n\t\t\t\t$rows.each(function() {\n\t\t\t\t\t$row = $(this);\n\t\t\t\t\tif (this.style.display !== 'none') {\n\t\t\t\t\t\t// remove all columns class names\n\t\t\t\t\t\t$cells = $row.children().removeClass(remove);\n\t\t\t\t\t\t// add appropriate column class names\n\t\t\t\t\t\tif (sortList && sortList[0]) {\n\t\t\t\t\t\t\t// primary sort column class\n\t\t\t\t\t\t\t$cells.eq(sortList[0][0]).addClass(css[0]);\n\t\t\t\t\t\t\tif (len > 1) {\n\t\t\t\t\t\t\t\tfor (indx = 1; indx < len; indx++) {\n\t\t\t\t\t\t\t\t\t// secondary, tertiary, etc sort column classes\n\t\t\t\t\t\t\t\t\t$cells.eq(sortList[indx][0]).addClass( css[indx] || css[last] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tts.processTbody(table, $tbody, false);\n\t\t\t}\n\t\t\t// add classes to thead and tfoot\n\t\t\trows = wo.columns_thead !== false ? [ 'thead tr' ] : [];\n\t\t\tif (wo.columns_tfoot !== false) {\n\t\t\t\trows.push('tfoot tr');\n\t\t\t}\n\t\t\tif (rows.length) {\n\t\t\t\t$rows = $table.find( rows.join(',') ).children().removeClass(remove);\n\t\t\t\tif (len) {\n\t\t\t\t\tfor (indx = 0; indx < len; indx++) {\n\t\t\t\t\t\t// add primary. secondary, tertiary, etc sort column classes\n\t\t\t\t\t\t$rows.filter('[data-column=\"' + sortList[indx][0] + '\"]').addClass(css[indx] || css[last]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tremove: function(table, c, wo) {\n\t\t\tvar tbodyIndex, $tbody,\n\t\t\t\t$tbodies = c.$tbodies,\n\t\t\t\tremove = (wo.columns || [ 'primary', 'secondary', 'tertiary' ]).join(' ');\n\t\t\tc.$headers.removeClass(remove);\n\t\t\tc.$table.children('tfoot').children('tr').children('th, td').removeClass(remove);\n\t\t\tfor (tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {\n\t\t\t\t$tbody = ts.processTbody(table, $tbodies.eq(tbodyIndex), true); // remove tbody\n\t\t\t\t$tbody.children('tr').each(function() {\n\t\t\t\t\t$(this).children().removeClass(remove);\n\t\t\t\t});\n\t\t\t\tts.processTbody(table, $tbody, false); // restore tbody\n\t\t\t}\n\t\t}\n\t});\n\n})(jQuery);\n\n/*! Widget: filter - updated 12/8/2016 (v2.28.1) *//*\n * Requires tablesorter v2.8+ and jQuery 1.7+\n * by Rob Garrison\n */\n;( function ( $ ) {\n\t'use strict';\n\tvar tsf, tsfRegex,\n\t\tts = $.tablesorter || {},\n\t\ttscss = ts.css,\n\t\ttskeyCodes = ts.keyCodes;\n\n\t$.extend( tscss, {\n\t\tfilterRow : 'tablesorter-filter-row',\n\t\tfilter : 'tablesorter-filter',\n\t\tfilterDisabled : 'disabled',\n\t\tfilterRowHide : 'hideme'\n\t});\n\n\t$.extend( tskeyCodes, {\n\t\tbackSpace : 8,\n\t\tescape : 27,\n\t\tspace : 32,\n\t\tleft : 37,\n\t\tdown : 40\n\t});\n\n\tts.addWidget({\n\t\tid: 'filter',\n\t\tpriority: 50,\n\t\toptions : {\n\t\t\tfilter_cellFilter : '', // css class name added to the filter cell ( string or array )\n\t\t\tfilter_childRows : false, // if true, filter includes child row content in the search\n\t\t\tfilter_childByColumn : false, // ( filter_childRows must be true ) if true = search child rows by column; false = search all child row text grouped\n\t\t\tfilter_childWithSibs : true, // if true, include matching child row siblings\n\t\t\tfilter_columnAnyMatch: true, // if true, allows using '#:{query}' in AnyMatch searches ( column:query )\n\t\t\tfilter_columnFilters : true, // if true, a filter will be added to the top of each table column\n\t\t\tfilter_cssFilter : '', // css class name added to the filter row & each input in the row ( tablesorter-filter is ALWAYS added )\n\t\t\tfilter_defaultAttrib : 'data-value', // data attribute in the header cell that contains the default filter value\n\t\t\tfilter_defaultFilter : {}, // add a default column filter type '~{query}' to make fuzzy searches default; '{q1} AND {q2}' to make all searches use a logical AND.\n\t\t\tfilter_excludeFilter : {}, // filters to exclude, per column\n\t\t\tfilter_external : '', // jQuery selector string ( or jQuery object ) of external filters\n\t\t\tfilter_filteredRow : 'filtered', // class added to filtered rows; define in css with \"display:none\" to hide the filtered-out rows\n\t\t\tfilter_formatter : null, // add custom filter elements to the filter row\n\t\t\tfilter_functions : null, // add custom filter functions using this option\n\t\t\tfilter_hideEmpty : true, // hide filter row when table is empty\n\t\t\tfilter_hideFilters : false, // collapse filter row when mouse leaves the area\n\t\t\tfilter_ignoreCase : true, // if true, make all searches case-insensitive\n\t\t\tfilter_liveSearch : true, // if true, search column content while the user types ( with a delay )\n\t\t\tfilter_matchType : { 'input': 'exact', 'select': 'exact' }, // global query settings ('exact' or 'match'); overridden by \"filter-match\" or \"filter-exact\" class\n\t\t\tfilter_onlyAvail : 'filter-onlyAvail', // a header with a select dropdown & this class name will only show available ( visible ) options within the drop down\n\t\t\tfilter_placeholder : { search : '', select : '' }, // default placeholder text ( overridden by any header 'data-placeholder' setting )\n\t\t\tfilter_reset : null, // jQuery selector string of an element used to reset the filters\n\t\t\tfilter_resetOnEsc : true, // Reset filter input when the user presses escape - normalized across browsers\n\t\t\tfilter_saveFilters : false, // Use the $.tablesorter.storage utility to save the most recent filters\n\t\t\tfilter_searchDelay : 300, // typing delay in milliseconds before starting a search\n\t\t\tfilter_searchFiltered: true, // allow searching through already filtered rows in special circumstances; will speed up searching in large tables if true\n\t\t\tfilter_selectSource : null, // include a function to return an array of values to be added to the column filter select\n\t\t\tfilter_selectSourceSeparator : '|', // filter_selectSource array text left of the separator is added to the option value, right into the option text\n\t\t\tfilter_serversideFiltering : false, // if true, must perform server-side filtering b/c client-side filtering is disabled, but the ui and events will still be used.\n\t\t\tfilter_startsWith : false, // if true, filter start from the beginning of the cell contents\n\t\t\tfilter_useParsedData : false // filter all data using parsed content\n\t\t},\n\t\tformat: function( table, c, wo ) {\n\t\t\tif ( !c.$table.hasClass( 'hasFilters' ) ) {\n\t\t\t\ttsf.init( table, c, wo );\n\t\t\t}\n\t\t},\n\t\tremove: function( table, c, wo, refreshing ) {\n\t\t\tvar tbodyIndex, $tbody,\n\t\t\t\t$table = c.$table,\n\t\t\t\t$tbodies = c.$tbodies,\n\t\t\t\tevents = 'addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search '\n\t\t\t\t\t.split( ' ' ).join( c.namespace + 'filter ' );\n\t\t\t$table\n\t\t\t\t.removeClass( 'hasFilters' )\n\t\t\t\t// add filter namespace to all BUT search\n\t\t\t\t.unbind( events.replace( ts.regex.spaces, ' ' ) )\n\t\t\t\t// remove the filter row even if refreshing, because the column might have been moved\n\t\t\t\t.find( '.' + tscss.filterRow ).remove();\n\t\t\two.filter_initialized = false;\n\t\t\tif ( refreshing ) { return; }\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < $tbodies.length; tbodyIndex++ ) {\n\t\t\t\t$tbody = ts.processTbody( table, $tbodies.eq( tbodyIndex ), true ); // remove tbody\n\t\t\t\t$tbody.children().removeClass( wo.filter_filteredRow ).show();\n\t\t\t\tts.processTbody( table, $tbody, false ); // restore tbody\n\t\t\t}\n\t\t\tif ( wo.filter_reset ) {\n\t\t\t\t$( document ).undelegate( wo.filter_reset, 'click' + c.namespace + 'filter' );\n\t\t\t}\n\t\t}\n\t});\n\n\ttsf = ts.filter = {\n\n\t\t// regex used in filter 'check' functions - not for general use and not documented\n\t\tregex: {\n\t\t\tregex : /^\\/((?:\\\\\\/|[^\\/])+)\\/([migyu]{0,5})?$/, // regex to test for regex\n\t\t\tchild : /tablesorter-childRow/, // child row class name; this gets updated in the script\n\t\t\tfiltered : /filtered/, // filtered (hidden) row class name; updated in the script\n\t\t\ttype : /undefined|number/, // check type\n\t\t\texact : /(^[\\\"\\'=]+)|([\\\"\\'=]+$)/g, // exact match (allow '==')\n\t\t\toperators : /[<>=]/g, // replace operators\n\t\t\tquery : '(q|query)', // replace filter queries\n\t\t\twild01 : /\\?/g, // wild card match 0 or 1\n\t\t\twild0More : /\\*/g, // wild care match 0 or more\n\t\t\tquote : /\\\"/g,\n\t\t\tisNeg1 : /(>=?\\s*-\\d)/,\n\t\t\tisNeg2 : /(<=?\\s*\\d)/\n\t\t},\n\t\t// function( c, data ) { }\n\t\t// c = table.config\n\t\t// data.$row = jQuery object of the row currently being processed\n\t\t// data.$cells = jQuery object of all cells within the current row\n\t\t// data.filters = array of filters for all columns ( some may be undefined )\n\t\t// data.filter = filter for the current column\n\t\t// data.iFilter = same as data.filter, except lowercase ( if wo.filter_ignoreCase is true )\n\t\t// data.exact = table cell text ( or parsed data if column parser enabled; may be a number & not a string )\n\t\t// data.iExact = same as data.exact, except lowercase ( if wo.filter_ignoreCase is true; may be a number & not a string )\n\t\t// data.cache = table cell text from cache, so it has been parsed ( & in all lower case if c.ignoreCase is true )\n\t\t// data.cacheArray = An array of parsed content from each table cell in the row being processed\n\t\t// data.index = column index; table = table element ( DOM )\n\t\t// data.parsed = array ( by column ) of boolean values ( from filter_useParsedData or 'filter-parsed' class )\n\t\ttypes: {\n\t\t\tor : function( c, data, vars ) {\n\t\t\t\t// look for \"|\", but not if it is inside of a regular expression\n\t\t\t\tif ( ( tsfRegex.orTest.test( data.iFilter ) || tsfRegex.orSplit.test( data.filter ) ) &&\n\t\t\t\t\t// this test for regex has potential to slow down the overall search\n\t\t\t\t\t!tsfRegex.regex.test( data.filter ) ) {\n\t\t\t\t\tvar indx, filterMatched, query, regex,\n\t\t\t\t\t\t// duplicate data but split filter\n\t\t\t\t\t\tdata2 = $.extend( {}, data ),\n\t\t\t\t\t\tfilter = data.filter.split( tsfRegex.orSplit ),\n\t\t\t\t\t\tiFilter = data.iFilter.split( tsfRegex.orSplit ),\n\t\t\t\t\t\tlen = filter.length;\n\t\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\t\tdata2.nestedFilters = true;\n\t\t\t\t\t\tdata2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );\n\t\t\t\t\t\tdata2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );\n\t\t\t\t\t\tquery = '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')';\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// use try/catch, because query may not be a valid regex if \"|\" is contained within a partial regex search,\n\t\t\t\t\t\t\t// e.g \"/(Alex|Aar\" -> Uncaught SyntaxError: Invalid regular expression: /(/(Alex)/: Unterminated group\n\t\t\t\t\t\t\tregex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );\n\t\t\t\t\t\t\t// filterMatched = data2.filter === '' && indx > 0 ? true\n\t\t\t\t\t\t\t// look for an exact match with the 'or' unless the 'filter-match' class is found\n\t\t\t\t\t\t\tfilterMatched = regex.test( data2.exact ) || tsf.processTypes( c, data2, vars );\n\t\t\t\t\t\t\tif ( filterMatched ) {\n\t\t\t\t\t\t\t\treturn filterMatched;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch ( error ) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// may be null from processing types\n\t\t\t\t\treturn filterMatched || false;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for an AND or && operator ( logical and )\n\t\t\tand : function( c, data, vars ) {\n\t\t\t\tif ( tsfRegex.andTest.test( data.filter ) ) {\n\t\t\t\t\tvar indx, filterMatched, result, query, regex,\n\t\t\t\t\t\t// duplicate data but split filter\n\t\t\t\t\t\tdata2 = $.extend( {}, data ),\n\t\t\t\t\t\tfilter = data.filter.split( tsfRegex.andSplit ),\n\t\t\t\t\t\tiFilter = data.iFilter.split( tsfRegex.andSplit ),\n\t\t\t\t\t\tlen = filter.length;\n\t\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\t\tdata2.nestedFilters = true;\n\t\t\t\t\t\tdata2.filter = '' + ( tsf.parseFilter( c, filter[ indx ], data ) || '' );\n\t\t\t\t\t\tdata2.iFilter = '' + ( tsf.parseFilter( c, iFilter[ indx ], data ) || '' );\n\t\t\t\t\t\tquery = ( '(' + ( tsf.parseFilter( c, data2.filter, data ) || '' ) + ')' )\n\t\t\t\t\t\t\t// replace wild cards since /(a*)/i will match anything\n\t\t\t\t\t\t\t.replace( tsfRegex.wild01, '\\\\S{1}' ).replace( tsfRegex.wild0More, '\\\\S*' );\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// use try/catch just in case RegExp is invalid\n\t\t\t\t\t\t\tregex = new RegExp( data.isMatch ? query : '^' + query + '$', c.widgetOptions.filter_ignoreCase ? 'i' : '' );\n\t\t\t\t\t\t\t// look for an exact match with the 'and' unless the 'filter-match' class is found\n\t\t\t\t\t\t\tresult = ( regex.test( data2.exact ) || tsf.processTypes( c, data2, vars ) );\n\t\t\t\t\t\t\tif ( indx === 0 ) {\n\t\t\t\t\t\t\t\tfilterMatched = result;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfilterMatched = filterMatched && result;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch ( error ) {\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// may be null from processing types\n\t\t\t\t\treturn filterMatched || false;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for regex\n\t\t\tregex: function( c, data ) {\n\t\t\t\tif ( tsfRegex.regex.test( data.filter ) ) {\n\t\t\t\t\tvar matches,\n\t\t\t\t\t\t// cache regex per column for optimal speed\n\t\t\t\t\t\tregex = data.filter_regexCache[ data.index ] || tsfRegex.regex.exec( data.filter ),\n\t\t\t\t\t\tisRegex = regex instanceof RegExp;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ( !isRegex ) {\n\t\t\t\t\t\t\t// force case insensitive search if ignoreCase option set?\n\t\t\t\t\t\t\t// if ( c.ignoreCase && !regex[2] ) { regex[2] = 'i'; }\n\t\t\t\t\t\t\tdata.filter_regexCache[ data.index ] = regex = new RegExp( regex[1], regex[2] );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatches = regex.test( data.exact );\n\t\t\t\t\t} catch ( error ) {\n\t\t\t\t\t\tmatches = false;\n\t\t\t\t\t}\n\t\t\t\t\treturn matches;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for operators >, >=, < or <=\n\t\t\toperators: function( c, data ) {\n\t\t\t\t// ignore empty strings... because '' < 10 is true\n\t\t\t\tif ( tsfRegex.operTest.test( data.iFilter ) && data.iExact !== '' ) {\n\t\t\t\t\tvar cachedValue, result, txt,\n\t\t\t\t\t\ttable = c.table,\n\t\t\t\t\t\tparsed = data.parsed[ data.index ],\n\t\t\t\t\t\tquery = ts.formatFloat( data.iFilter.replace( tsfRegex.operators, '' ), table ),\n\t\t\t\t\t\tparser = c.parsers[ data.index ] || {},\n\t\t\t\t\t\tsavedSearch = query;\n\t\t\t\t\t// parse filter value in case we're comparing numbers ( dates )\n\t\t\t\t\tif ( parsed || parser.type === 'numeric' ) {\n\t\t\t\t\t\ttxt = $.trim( '' + data.iFilter.replace( tsfRegex.operators, '' ) );\n\t\t\t\t\t\tresult = tsf.parseFilter( c, txt, data, true );\n\t\t\t\t\t\tquery = ( typeof result === 'number' && result !== '' && !isNaN( result ) ) ? result : query;\n\t\t\t\t\t}\n\t\t\t\t\t// iExact may be numeric - see issue #149;\n\t\t\t\t\t// check if cached is defined, because sometimes j goes out of range? ( numeric columns )\n\t\t\t\t\tif ( ( parsed || parser.type === 'numeric' ) && !isNaN( query ) &&\n\t\t\t\t\t\ttypeof data.cache !== 'undefined' ) {\n\t\t\t\t\t\tcachedValue = data.cache;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttxt = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;\n\t\t\t\t\t\tcachedValue = ts.formatFloat( txt, table );\n\t\t\t\t\t}\n\t\t\t\t\tif ( tsfRegex.gtTest.test( data.iFilter ) ) {\n\t\t\t\t\t\tresult = tsfRegex.gteTest.test( data.iFilter ) ? cachedValue >= query : cachedValue > query;\n\t\t\t\t\t} else if ( tsfRegex.ltTest.test( data.iFilter ) ) {\n\t\t\t\t\t\tresult = tsfRegex.lteTest.test( data.iFilter ) ? cachedValue <= query : cachedValue < query;\n\t\t\t\t\t}\n\t\t\t\t\t// keep showing all rows if nothing follows the operator\n\t\t\t\t\tif ( !result && savedSearch === '' ) {\n\t\t\t\t\t\tresult = true;\n\t\t\t\t\t}\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for a not match\n\t\t\tnotMatch: function( c, data ) {\n\t\t\t\tif ( tsfRegex.notTest.test( data.iFilter ) ) {\n\t\t\t\t\tvar indx,\n\t\t\t\t\t\ttxt = data.iFilter.replace( '!', '' ),\n\t\t\t\t\t\tfilter = tsf.parseFilter( c, txt, data ) || '';\n\t\t\t\t\tif ( tsfRegex.exact.test( filter ) ) {\n\t\t\t\t\t\t// look for exact not matches - see #628\n\t\t\t\t\t\tfilter = filter.replace( tsfRegex.exact, '' );\n\t\t\t\t\t\treturn filter === '' ? true : $.trim( filter ) !== data.iExact;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tindx = data.iExact.search( $.trim( filter ) );\n\t\t\t\t\t\treturn filter === '' ? true :\n\t\t\t\t\t\t\t// return true if not found\n\t\t\t\t\t\t\tdata.anyMatch ? indx < 0 :\n\t\t\t\t\t\t\t// return false if found\n\t\t\t\t\t\t\t!( c.widgetOptions.filter_startsWith ? indx === 0 : indx >= 0 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for quotes or equals to get an exact match; ignore type since iExact could be numeric\n\t\t\texact: function( c, data ) {\n\t\t\t\t/*jshint eqeqeq:false */\n\t\t\t\tif ( tsfRegex.exact.test( data.iFilter ) ) {\n\t\t\t\t\tvar txt = data.iFilter.replace( tsfRegex.exact, '' ),\n\t\t\t\t\t\tfilter = tsf.parseFilter( c, txt, data ) || '';\n\t\t\t\t\treturn data.anyMatch ? $.inArray( filter, data.rowArray ) >= 0 : filter == data.iExact;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for a range ( using ' to ' or ' - ' ) - see issue #166; thanks matzhu!\n\t\t\trange : function( c, data ) {\n\t\t\t\tif ( tsfRegex.toTest.test( data.iFilter ) ) {\n\t\t\t\t\tvar result, tmp, range1, range2,\n\t\t\t\t\t\ttable = c.table,\n\t\t\t\t\t\tindex = data.index,\n\t\t\t\t\t\tparsed = data.parsed[index],\n\t\t\t\t\t\t// make sure the dash is for a range and not indicating a negative number\n\t\t\t\t\t\tquery = data.iFilter.split( tsfRegex.toSplit );\n\n\t\t\t\t\ttmp = query[0].replace( ts.regex.nondigit, '' ) || '';\n\t\t\t\t\trange1 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );\n\t\t\t\t\ttmp = query[1].replace( ts.regex.nondigit, '' ) || '';\n\t\t\t\t\trange2 = ts.formatFloat( tsf.parseFilter( c, tmp, data ), table );\n\t\t\t\t\t// parse filter value in case we're comparing numbers ( dates )\n\t\t\t\t\tif ( parsed || c.parsers[ index ].type === 'numeric' ) {\n\t\t\t\t\t\tresult = c.parsers[ index ].format( '' + query[0], table, c.$headers.eq( index ), index );\n\t\t\t\t\t\trange1 = ( result !== '' && !isNaN( result ) ) ? result : range1;\n\t\t\t\t\t\tresult = c.parsers[ index ].format( '' + query[1], table, c.$headers.eq( index ), index );\n\t\t\t\t\t\trange2 = ( result !== '' && !isNaN( result ) ) ? result : range2;\n\t\t\t\t\t}\n\t\t\t\t\tif ( ( parsed || c.parsers[ index ].type === 'numeric' ) && !isNaN( range1 ) && !isNaN( range2 ) ) {\n\t\t\t\t\t\tresult = data.cache;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttmp = isNaN( data.iExact ) ? data.iExact.replace( ts.regex.nondigit, '' ) : data.iExact;\n\t\t\t\t\t\tresult = ts.formatFloat( tmp, table );\n\t\t\t\t\t}\n\t\t\t\t\tif ( range1 > range2 ) {\n\t\t\t\t\t\ttmp = range1; range1 = range2; range2 = tmp; // swap\n\t\t\t\t\t}\n\t\t\t\t\treturn ( result >= range1 && result <= range2 ) || ( range1 === '' || range2 === '' );\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// Look for wild card: ? = single, * = multiple, or | = logical OR\n\t\t\twild : function( c, data ) {\n\t\t\t\tif ( tsfRegex.wildOrTest.test( data.iFilter ) ) {\n\t\t\t\t\tvar query = '' + ( tsf.parseFilter( c, data.iFilter, data ) || '' );\n\t\t\t\t\t// look for an exact match with the 'or' unless the 'filter-match' class is found\n\t\t\t\t\tif ( !tsfRegex.wildTest.test( query ) && data.nestedFilters ) {\n\t\t\t\t\t\tquery = data.isMatch ? query : '^(' + query + ')$';\n\t\t\t\t\t}\n\t\t\t\t\t// parsing the filter may not work properly when using wildcards =/\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn new RegExp(\n\t\t\t\t\t\t\tquery.replace( tsfRegex.wild01, '\\\\S{1}' ).replace( tsfRegex.wild0More, '\\\\S*' ),\n\t\t\t\t\t\t\tc.widgetOptions.filter_ignoreCase ? 'i' : ''\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.test( data.exact );\n\t\t\t\t\t} catch ( error ) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\t// fuzzy text search; modified from https://github.com/mattyork/fuzzy ( MIT license )\n\t\t\tfuzzy: function( c, data ) {\n\t\t\t\tif ( tsfRegex.fuzzyTest.test( data.iFilter ) ) {\n\t\t\t\t\tvar indx,\n\t\t\t\t\t\tpatternIndx = 0,\n\t\t\t\t\t\tlen = data.iExact.length,\n\t\t\t\t\t\ttxt = data.iFilter.slice( 1 ),\n\t\t\t\t\t\tpattern = tsf.parseFilter( c, txt, data ) || '';\n\t\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\t\tif ( data.iExact[ indx ] === pattern[ patternIndx ] ) {\n\t\t\t\t\t\t\tpatternIndx += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn patternIndx === pattern.length;\n\t\t\t\t}\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\t\tinit: function( table ) {\n\t\t\t// filter language options\n\t\t\tts.language = $.extend( true, {}, {\n\t\t\t\tto : 'to',\n\t\t\t\tor : 'or',\n\t\t\t\tand : 'and'\n\t\t\t}, ts.language );\n\n\t\t\tvar options, string, txt, $header, column, val, fxn, noSelect,\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions;\n\t\t\tc.$table.addClass( 'hasFilters' );\n\t\t\tc.lastSearch = [];\n\n\t\t\t// define timers so using clearTimeout won't cause an undefined error\n\t\t\two.filter_searchTimer = null;\n\t\t\two.filter_initTimer = null;\n\t\t\two.filter_formatterCount = 0;\n\t\t\two.filter_formatterInit = [];\n\t\t\two.filter_anyColumnSelector = '[data-column=\"all\"],[data-column=\"any\"]';\n\t\t\two.filter_multipleColumnSelector = '[data-column*=\"-\"],[data-column*=\",\"]';\n\n\t\t\tval = '\\\\{' + tsfRegex.query + '\\\\}';\n\t\t\t$.extend( tsfRegex, {\n\t\t\t\tchild : new RegExp( c.cssChildRow ),\n\t\t\t\tfiltered : new RegExp( wo.filter_filteredRow ),\n\t\t\t\talreadyFiltered : new RegExp( '(\\\\s+(' + ts.language.or + '|-|' + ts.language.to + ')\\\\s+)', 'i' ),\n\t\t\t\ttoTest : new RegExp( '\\\\s+(-|' + ts.language.to + ')\\\\s+', 'i' ),\n\t\t\t\ttoSplit : new RegExp( '(?:\\\\s+(?:-|' + ts.language.to + ')\\\\s+)', 'gi' ),\n\t\t\t\tandTest : new RegExp( '\\\\s+(' + ts.language.and + '|&&)\\\\s+', 'i' ),\n\t\t\t\tandSplit : new RegExp( '(?:\\\\s+(?:' + ts.language.and + '|&&)\\\\s+)', 'gi' ),\n\t\t\t\torTest : new RegExp( '(\\\\||\\\\s+' + ts.language.or + '\\\\s+)', 'i' ),\n\t\t\t\torSplit : new RegExp( '(?:\\\\s+(?:' + ts.language.or + ')\\\\s+|\\\\|)', 'gi' ),\n\t\t\t\tiQuery : new RegExp( val, 'i' ),\n\t\t\t\tigQuery : new RegExp( val, 'ig' ),\n\t\t\t\toperTest : /^[<>]=?/,\n\t\t\t\tgtTest : />/,\n\t\t\t\tgteTest : />=/,\n\t\t\t\tltTest : /</,\n\t\t\t\tlteTest : /<=/,\n\t\t\t\tnotTest : /^\\!/,\n\t\t\t\twildOrTest : /[\\?\\*\\|]/,\n\t\t\t\twildTest : /\\?\\*/,\n\t\t\t\tfuzzyTest : /^~/,\n\t\t\t\texactTest : /[=\\\"\\|!]/\n\t\t\t});\n\n\t\t\t// don't build filter row if columnFilters is false or all columns are set to 'filter-false'\n\t\t\t// see issue #156\n\t\t\tval = c.$headers.filter( '.filter-false, .parser-false' ).length;\n\t\t\tif ( wo.filter_columnFilters !== false && val !== c.$headers.length ) {\n\t\t\t\t// build filter row\n\t\t\t\ttsf.buildRow( table, c, wo );\n\t\t\t}\n\n\t\t\ttxt = 'addRows updateCell update updateRows updateComplete appendCache filterReset ' +\n\t\t\t\t'filterResetSaved filterEnd search '.split( ' ' ).join( c.namespace + 'filter ' );\n\t\t\tc.$table.bind( txt, function( event, filter ) {\n\t\t\t\tval = wo.filter_hideEmpty &&\n\t\t\t\t\t$.isEmptyObject( c.cache ) &&\n\t\t\t\t\t!( c.delayInit && event.type === 'appendCache' );\n\t\t\t\t// hide filter row using the 'filtered' class name\n\t\t\t\tc.$table.find( '.' + tscss.filterRow ).toggleClass( wo.filter_filteredRow, val ); // fixes #450\n\t\t\t\tif ( !/(search|filter)/.test( event.type ) ) {\n\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\ttsf.buildDefault( table, true );\n\t\t\t\t}\n\t\t\t\tif ( event.type === 'filterReset' ) {\n\t\t\t\t\tc.$table.find( '.' + tscss.filter ).add( wo.filter_$externalFilters ).val( '' );\n\t\t\t\t\ttsf.searching( table, [] );\n\t\t\t\t} else if ( event.type === 'filterResetSaved' ) {\n\t\t\t\t\tts.storage( table, 'tablesorter-filters', '' );\n\t\t\t\t} else if ( event.type === 'filterEnd' ) {\n\t\t\t\t\ttsf.buildDefault( table, true );\n\t\t\t\t} else {\n\t\t\t\t\t// send false argument to force a new search; otherwise if the filter hasn't changed,\n\t\t\t\t\t// it will return\n\t\t\t\t\tfilter = event.type === 'search' ? filter :\n\t\t\t\t\t\tevent.type === 'updateComplete' ? c.$table.data( 'lastSearch' ) : '';\n\t\t\t\t\tif ( /(update|add)/.test( event.type ) && event.type !== 'updateComplete' ) {\n\t\t\t\t\t\t// force a new search since content has changed\n\t\t\t\t\t\tc.lastCombinedFilter = null;\n\t\t\t\t\t\tc.lastSearch = [];\n\t\t\t\t\t\t// update filterFormatters after update (& small delay) - Fixes #1237\n\t\t\t\t\t\tsetTimeout(function(){\n\t\t\t\t\t\t\tc.$table.triggerHandler( 'filterFomatterUpdate' );\n\t\t\t\t\t\t}, 100);\n\t\t\t\t\t}\n\t\t\t\t\t// pass true ( skipFirst ) to prevent the tablesorter.setFilters function from skipping the first\n\t\t\t\t\t// input ensures all inputs are updated when a search is triggered on the table\n\t\t\t\t\t// $( 'table' ).trigger( 'search', [...] );\n\t\t\t\t\ttsf.searching( table, filter, true );\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t// reset button/link\n\t\t\tif ( wo.filter_reset ) {\n\t\t\t\tif ( wo.filter_reset instanceof $ ) {\n\t\t\t\t\t// reset contains a jQuery object, bind to it\n\t\t\t\t\two.filter_reset.click( function() {\n\t\t\t\t\t\tc.$table.triggerHandler( 'filterReset' );\n\t\t\t\t\t});\n\t\t\t\t} else if ( $( wo.filter_reset ).length ) {\n\t\t\t\t\t// reset is a jQuery selector, use event delegation\n\t\t\t\t\t$( document )\n\t\t\t\t\t\t.undelegate( wo.filter_reset, 'click' + c.namespace + 'filter' )\n\t\t\t\t\t\t.delegate( wo.filter_reset, 'click' + c.namespace + 'filter', function() {\n\t\t\t\t\t\t\t// trigger a reset event, so other functions ( filter_formatter ) know when to reset\n\t\t\t\t\t\t\tc.$table.triggerHandler( 'filterReset' );\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( wo.filter_functions ) {\n\t\t\t\tfor ( column = 0; column < c.columns; column++ ) {\n\t\t\t\t\tfxn = ts.getColumnData( table, wo.filter_functions, column );\n\t\t\t\t\tif ( fxn ) {\n\t\t\t\t\t\t// remove 'filter-select' from header otherwise the options added here are replaced with\n\t\t\t\t\t\t// all options\n\t\t\t\t\t\t$header = c.$headerIndexed[ column ].removeClass( 'filter-select' );\n\t\t\t\t\t\t// don't build select if 'filter-false' or 'parser-false' set\n\t\t\t\t\t\tnoSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );\n\t\t\t\t\t\toptions = '';\n\t\t\t\t\t\tif ( fxn === true && noSelect ) {\n\t\t\t\t\t\t\ttsf.buildSelect( table, column );\n\t\t\t\t\t\t} else if ( typeof fxn === 'object' && noSelect ) {\n\t\t\t\t\t\t\t// add custom drop down list\n\t\t\t\t\t\t\tfor ( string in fxn ) {\n\t\t\t\t\t\t\t\tif ( typeof string === 'string' ) {\n\t\t\t\t\t\t\t\t\toptions += options === '' ?\n\t\t\t\t\t\t\t\t\t\t'<option value=\"\">' +\n\t\t\t\t\t\t\t\t\t\t\t( $header.data( 'placeholder' ) ||\n\t\t\t\t\t\t\t\t\t\t\t\t$header.attr( 'data-placeholder' ) ||\n\t\t\t\t\t\t\t\t\t\t\t\two.filter_placeholder.select ||\n\t\t\t\t\t\t\t\t\t\t\t\t''\n\t\t\t\t\t\t\t\t\t\t\t) +\n\t\t\t\t\t\t\t\t\t\t'</option>' : '';\n\t\t\t\t\t\t\t\t\tval = string;\n\t\t\t\t\t\t\t\t\ttxt = string;\n\t\t\t\t\t\t\t\t\tif ( string.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {\n\t\t\t\t\t\t\t\t\t\tval = string.split( wo.filter_selectSourceSeparator );\n\t\t\t\t\t\t\t\t\t\ttxt = val[1];\n\t\t\t\t\t\t\t\t\t\tval = val[0];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\toptions += '<option ' +\n\t\t\t\t\t\t\t\t\t\t( txt === val ? '' : 'data-function-name=\"' + string + '\" ' ) +\n\t\t\t\t\t\t\t\t\t\t'value=\"' + val + '\">' + txt + '</option>';\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tc.$table\n\t\t\t\t\t\t\t\t.find( 'thead' )\n\t\t\t\t\t\t\t\t.find( 'select.' + tscss.filter + '[data-column=\"' + column + '\"]' )\n\t\t\t\t\t\t\t\t.append( options );\n\t\t\t\t\t\t\ttxt = wo.filter_selectSource;\n\t\t\t\t\t\t\tfxn = typeof txt === 'function' ? true : ts.getColumnData( table, txt, column );\n\t\t\t\t\t\t\tif ( fxn ) {\n\t\t\t\t\t\t\t\t// updating so the extra options are appended\n\t\t\t\t\t\t\t\ttsf.buildSelect( c.table, column, '', true, $header.hasClass( wo.filter_onlyAvail ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// not really updating, but if the column has both the 'filter-select' class &\n\t\t\t// filter_functions set to true, it would append the same options twice.\n\t\t\ttsf.buildDefault( table, true );\n\n\t\t\ttsf.bindSearch( table, c.$table.find( '.' + tscss.filter ), true );\n\t\t\tif ( wo.filter_external ) {\n\t\t\t\ttsf.bindSearch( table, wo.filter_external );\n\t\t\t}\n\n\t\t\tif ( wo.filter_hideFilters ) {\n\t\t\t\ttsf.hideFilters( c );\n\t\t\t}\n\n\t\t\t// show processing icon\n\t\t\tif ( c.showProcessing ) {\n\t\t\t\ttxt = 'filterStart filterEnd '.split( ' ' ).join( c.namespace + 'filter ' );\n\t\t\t\tc.$table\n\t\t\t\t\t.unbind( txt.replace( ts.regex.spaces, ' ' ) )\n\t\t\t\t\t.bind( txt, function( event, columns ) {\n\t\t\t\t\t// only add processing to certain columns to all columns\n\t\t\t\t\t$header = ( columns ) ?\n\t\t\t\t\t\tc.$table\n\t\t\t\t\t\t\t.find( '.' + tscss.header )\n\t\t\t\t\t\t\t.filter( '[data-column]' )\n\t\t\t\t\t\t\t.filter( function() {\n\t\t\t\t\t\t\t\treturn columns[ $( this ).data( 'column' ) ] !== '';\n\t\t\t\t\t\t\t}) : '';\n\t\t\t\t\tts.isProcessing( table, event.type === 'filterStart', columns ? $header : '' );\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// set filtered rows count ( intially unfiltered )\n\t\t\tc.filteredRows = c.totalRows;\n\n\t\t\t// add default values\n\t\t\ttxt = 'tablesorter-initialized pagerBeforeInitialized '.split( ' ' ).join( c.namespace + 'filter ' );\n\t\t\tc.$table\n\t\t\t.unbind( txt.replace( ts.regex.spaces, ' ' ) )\n\t\t\t.bind( txt, function() {\n\t\t\t\ttsf.completeInit( this );\n\t\t\t});\n\t\t\t// if filter widget is added after pager has initialized; then set filter init flag\n\t\t\tif ( c.pager && c.pager.initialized && !wo.filter_initialized ) {\n\t\t\t\tc.$table.triggerHandler( 'filterFomatterUpdate' );\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\ttsf.filterInitComplete( c );\n\t\t\t\t}, 100 );\n\t\t\t} else if ( !wo.filter_initialized ) {\n\t\t\t\ttsf.completeInit( table );\n\t\t\t}\n\t\t},\n\t\tcompleteInit: function( table ) {\n\t\t\t// redefine 'c' & 'wo' so they update properly inside this callback\n\t\t\tvar c = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tfilters = tsf.setDefaults( table, c, wo ) || [];\n\t\t\tif ( filters.length ) {\n\t\t\t\t// prevent delayInit from triggering a cache build if filters are empty\n\t\t\t\tif ( !( c.delayInit && filters.join( '' ) === '' ) ) {\n\t\t\t\t\tts.setFilters( table, filters, true );\n\t\t\t\t}\n\t\t\t}\n\t\t\tc.$table.triggerHandler( 'filterFomatterUpdate' );\n\t\t\t// trigger init after setTimeout to prevent multiple filterStart/End/Init triggers\n\t\t\tsetTimeout( function() {\n\t\t\t\tif ( !wo.filter_initialized ) {\n\t\t\t\t\ttsf.filterInitComplete( c );\n\t\t\t\t}\n\t\t\t}, 100 );\n\t\t},\n\n\t\t// $cell parameter, but not the config, is passed to the filter_formatters,\n\t\t// so we have to work with it instead\n\t\tformatterUpdated: function( $cell, column ) {\n\t\t\t// prevent error if $cell is undefined - see #1056\n\t\t\tvar wo = $cell && $cell.closest( 'table' )[0].config.widgetOptions;\n\t\t\tif ( wo && !wo.filter_initialized ) {\n\t\t\t\t// add updates by column since this function\n\t\t\t\t// may be called numerous times before initialization\n\t\t\t\two.filter_formatterInit[ column ] = 1;\n\t\t\t}\n\t\t},\n\t\tfilterInitComplete: function( c ) {\n\t\t\tvar indx, len,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tcount = 0,\n\t\t\t\tcompleted = function() {\n\t\t\t\t\two.filter_initialized = true;\n\t\t\t\t\t// update lastSearch - it gets cleared often\n\t\t\t\t\tc.lastSearch = c.$table.data( 'lastSearch' );\n\t\t\t\t\tc.$table.triggerHandler( 'filterInit', c );\n\t\t\t\t\ttsf.findRows( c.table, c.lastSearch || [] );\n\t\t\t\t};\n\t\t\tif ( $.isEmptyObject( wo.filter_formatter ) ) {\n\t\t\t\tcompleted();\n\t\t\t} else {\n\t\t\t\tlen = wo.filter_formatterInit.length;\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\tif ( wo.filter_formatterInit[ indx ] === 1 ) {\n\t\t\t\t\t\tcount++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tclearTimeout( wo.filter_initTimer );\n\t\t\t\tif ( !wo.filter_initialized && count === wo.filter_formatterCount ) {\n\t\t\t\t\t// filter widget initialized\n\t\t\t\t\tcompleted();\n\t\t\t\t} else if ( !wo.filter_initialized ) {\n\t\t\t\t\t// fall back in case a filter_formatter doesn't call\n\t\t\t\t\t// $.tablesorter.filter.formatterUpdated( $cell, column ), and the count is off\n\t\t\t\t\two.filter_initTimer = setTimeout( function() {\n\t\t\t\t\t\tcompleted();\n\t\t\t\t\t}, 500 );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// encode or decode filters for storage; see #1026\n\t\tprocessFilters: function( filters, encode ) {\n\t\t\tvar indx,\n\t\t\t\t// fixes #1237; previously returning an encoded \"filters\" value\n\t\t\t\tresult = [],\n\t\t\t\tmode = encode ? encodeURIComponent : decodeURIComponent,\n\t\t\t\tlen = filters.length;\n\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\tif ( filters[ indx ] ) {\n\t\t\t\t\tresult[ indx ] = mode( filters[ indx ] );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tsetDefaults: function( table, c, wo ) {\n\t\t\tvar isArray, saved, indx, col, $filters,\n\t\t\t\t// get current ( default ) filters\n\t\t\t\tfilters = ts.getFilters( table ) || [];\n\t\t\tif ( wo.filter_saveFilters && ts.storage ) {\n\t\t\t\tsaved = ts.storage( table, 'tablesorter-filters' ) || [];\n\t\t\t\tisArray = $.isArray( saved );\n\t\t\t\t// make sure we're not just getting an empty array\n\t\t\t\tif ( !( isArray && saved.join( '' ) === '' || !isArray ) ) {\n\t\t\t\t\tfilters = tsf.processFilters( saved );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// if no filters saved, then check default settings\n\t\t\tif ( filters.join( '' ) === '' ) {\n\t\t\t\t// allow adding default setting to external filters\n\t\t\t\t$filters = c.$headers.add( wo.filter_$externalFilters )\n\t\t\t\t\t.filter( '[' + wo.filter_defaultAttrib + ']' );\n\t\t\t\tfor ( indx = 0; indx <= c.columns; indx++ ) {\n\t\t\t\t\t// include data-column='all' external filters\n\t\t\t\t\tcol = indx === c.columns ? 'all' : indx;\n\t\t\t\t\tfilters[ indx ] = $filters\n\t\t\t\t\t\t.filter( '[data-column=\"' + col + '\"]' )\n\t\t\t\t\t\t.attr( wo.filter_defaultAttrib ) || filters[indx] || '';\n\t\t\t\t}\n\t\t\t}\n\t\t\tc.$table.data( 'lastSearch', filters );\n\t\t\treturn filters;\n\t\t},\n\t\tparseFilter: function( c, filter, data, parsed ) {\n\t\t\treturn parsed || data.parsed[ data.index ] ?\n\t\t\t\tc.parsers[ data.index ].format( filter, c.table, [], data.index ) :\n\t\t\t\tfilter;\n\t\t},\n\t\tbuildRow: function( table, c, wo ) {\n\t\t\tvar $filter, col, column, $header, makeSelect, disabled, name, ffxn, tmp,\n\t\t\t\t// c.columns defined in computeThIndexes()\n\t\t\t\tcellFilter = wo.filter_cellFilter,\n\t\t\t\tcolumns = c.columns,\n\t\t\t\tarry = $.isArray( cellFilter ),\n\t\t\t\tbuildFilter = '<tr role=\"row\" class=\"' + tscss.filterRow + ' ' + c.cssIgnoreRow + '\">';\n\t\t\tfor ( column = 0; column < columns; column++ ) {\n\t\t\t\tif ( c.$headerIndexed[ column ].length ) {\n\t\t\t\t\t// account for entire column set with colspan. See #1047\n\t\t\t\t\ttmp = c.$headerIndexed[ column ] && c.$headerIndexed[ column ][0].colSpan || 0;\n\t\t\t\t\tif ( tmp > 1 ) {\n\t\t\t\t\t\tbuildFilter += '<td data-column=\"' + column + '-' + ( column + tmp - 1 ) + '\" colspan=\"' + tmp + '\"';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuildFilter += '<td data-column=\"' + column + '\"';\n\t\t\t\t\t}\n\t\t\t\t\tif ( arry ) {\n\t\t\t\t\t\tbuildFilter += ( cellFilter[ column ] ? ' class=\"' + cellFilter[ column ] + '\"' : '' );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuildFilter += ( cellFilter !== '' ? ' class=\"' + cellFilter + '\"' : '' );\n\t\t\t\t\t}\n\t\t\t\t\tbuildFilter += '></td>';\n\t\t\t\t}\n\t\t\t}\n\t\t\tc.$filters = $( buildFilter += '</tr>' )\n\t\t\t\t.appendTo( c.$table.children( 'thead' ).eq( 0 ) )\n\t\t\t\t.children( 'td' );\n\t\t\t// build each filter input\n\t\t\tfor ( column = 0; column < columns; column++ ) {\n\t\t\t\tdisabled = false;\n\t\t\t\t// assuming last cell of a column is the main column\n\t\t\t\t$header = c.$headerIndexed[ column ];\n\t\t\t\tif ( $header && $header.length ) {\n\t\t\t\t\t// $filter = c.$filters.filter( '[data-column=\"' + column + '\"]' );\n\t\t\t\t\t$filter = tsf.getColumnElm( c, c.$filters, column );\n\t\t\t\t\tffxn = ts.getColumnData( table, wo.filter_functions, column );\n\t\t\t\t\tmakeSelect = ( wo.filter_functions && ffxn && typeof ffxn !== 'function' ) ||\n\t\t\t\t\t\t$header.hasClass( 'filter-select' );\n\t\t\t\t\t// get data from jQuery data, metadata, headers option or header class name\n\t\t\t\t\tcol = ts.getColumnData( table, c.headers, column );\n\t\t\t\t\tdisabled = ts.getData( $header[0], col, 'filter' ) === 'false' ||\n\t\t\t\t\t\tts.getData( $header[0], col, 'parser' ) === 'false';\n\n\t\t\t\t\tif ( makeSelect ) {\n\t\t\t\t\t\tbuildFilter = $( '<select>' ).appendTo( $filter );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tffxn = ts.getColumnData( table, wo.filter_formatter, column );\n\t\t\t\t\t\tif ( ffxn ) {\n\t\t\t\t\t\t\two.filter_formatterCount++;\n\t\t\t\t\t\t\tbuildFilter = ffxn( $filter, column );\n\t\t\t\t\t\t\t// no element returned, so lets go find it\n\t\t\t\t\t\t\tif ( buildFilter && buildFilter.length === 0 ) {\n\t\t\t\t\t\t\t\tbuildFilter = $filter.children( 'input' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// element not in DOM, so lets attach it\n\t\t\t\t\t\t\tif ( buildFilter && ( buildFilter.parent().length === 0 ||\n\t\t\t\t\t\t\t\t( buildFilter.parent().length && buildFilter.parent()[0] !== $filter[0] ) ) ) {\n\t\t\t\t\t\t\t\t$filter.append( buildFilter );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tbuildFilter = $( '<input type=\"search\">' ).appendTo( $filter );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( buildFilter ) {\n\t\t\t\t\t\t\ttmp = $header.data( 'placeholder' ) ||\n\t\t\t\t\t\t\t\t$header.attr( 'data-placeholder' ) ||\n\t\t\t\t\t\t\t\two.filter_placeholder.search || '';\n\t\t\t\t\t\t\tbuildFilter.attr( 'placeholder', tmp );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( buildFilter ) {\n\t\t\t\t\t\t// add filter class name\n\t\t\t\t\t\tname = ( $.isArray( wo.filter_cssFilter ) ?\n\t\t\t\t\t\t\t( typeof wo.filter_cssFilter[column] !== 'undefined' ? wo.filter_cssFilter[column] || '' : '' ) :\n\t\t\t\t\t\t\two.filter_cssFilter ) || '';\n\t\t\t\t\t\t// copy data-column from table cell (it will include colspan)\n\t\t\t\t\t\tbuildFilter.addClass( tscss.filter + ' ' + name ).attr( 'data-column', $filter.attr( 'data-column' ) );\n\t\t\t\t\t\tif ( disabled ) {\n\t\t\t\t\t\t\tbuildFilter.attr( 'placeholder', '' ).addClass( tscss.filterDisabled )[0].disabled = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tbindSearch: function( table, $el, internal ) {\n\t\t\ttable = $( table )[0];\n\t\t\t$el = $( $el ); // allow passing a selector string\n\t\t\tif ( !$el.length ) { return; }\n\t\t\tvar tmp,\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tnamespace = c.namespace + 'filter',\n\t\t\t\t$ext = wo.filter_$externalFilters;\n\t\t\tif ( internal !== true ) {\n\t\t\t\t// save anyMatch element\n\t\t\t\ttmp = wo.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector;\n\t\t\t\two.filter_$anyMatch = $el.filter( tmp );\n\t\t\t\tif ( $ext && $ext.length ) {\n\t\t\t\t\two.filter_$externalFilters = wo.filter_$externalFilters.add( $el );\n\t\t\t\t} else {\n\t\t\t\t\two.filter_$externalFilters = $el;\n\t\t\t\t}\n\t\t\t\t// update values ( external filters added after table initialization )\n\t\t\t\tts.setFilters( table, c.$table.data( 'lastSearch' ) || [], internal === false );\n\t\t\t}\n\t\t\t// unbind events\n\t\t\ttmp = ( 'keypress keyup keydown search change input '.split( ' ' ).join( namespace + ' ' ) );\n\t\t\t$el\n\t\t\t// use data attribute instead of jQuery data since the head is cloned without including\n\t\t\t// the data/binding\n\t\t\t.attr( 'data-lastSearchTime', new Date().getTime() )\n\t\t\t.unbind( tmp.replace( ts.regex.spaces, ' ' ) )\n\t\t\t.bind( 'keydown' + namespace, function( event ) {\n\t\t\t\tif ( event.which === tskeyCodes.escape && !table.config.widgetOptions.filter_resetOnEsc ) {\n\t\t\t\t\t// prevent keypress event\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t})\n\t\t\t.bind( 'keyup' + namespace, function( event ) {\n\t\t\t\two = table.config.widgetOptions; // make sure \"wo\" isn't cached\n\t\t\t\tvar column = parseInt( $( this ).attr( 'data-column' ), 10 ),\n\t\t\t\t\tliveSearch = typeof wo.filter_liveSearch === 'boolean' ? wo.filter_liveSearch :\n\t\t\t\t\t\tts.getColumnData( table, wo.filter_liveSearch, column );\n\t\t\t\tif ( typeof liveSearch === 'undefined' ) {\n\t\t\t\t\tliveSearch = wo.filter_liveSearch.fallback || false;\n\t\t\t\t}\n\t\t\t\t$( this ).attr( 'data-lastSearchTime', new Date().getTime() );\n\t\t\t\t// emulate what webkit does.... escape clears the filter\n\t\t\t\tif ( event.which === tskeyCodes.escape ) {\n\t\t\t\t\t// make sure to restore the last value on escape\n\t\t\t\t\tthis.value = wo.filter_resetOnEsc ? '' : c.lastSearch[column];\n\t\t\t\t// live search\n\t\t\t\t} else if ( liveSearch === false ) {\n\t\t\t\t\treturn;\n\t\t\t\t\t// don't return if the search value is empty ( all rows need to be revealed )\n\t\t\t\t} else if ( this.value !== '' && (\n\t\t\t\t\t// liveSearch can contain a min value length; ignore arrow and meta keys, but allow backspace\n\t\t\t\t\t( typeof liveSearch === 'number' && this.value.length < liveSearch ) ||\n\t\t\t\t\t// let return & backspace continue on, but ignore arrows & non-valid characters\n\t\t\t\t\t( event.which !== tskeyCodes.enter && event.which !== tskeyCodes.backSpace &&\n\t\t\t\t\t\t( event.which < tskeyCodes.space || ( event.which >= tskeyCodes.left && event.which <= tskeyCodes.down ) ) ) ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// change event = no delay; last true flag tells getFilters to skip newest timed input\n\t\t\t\ttsf.searching( table, true, true, column );\n\t\t\t})\n\t\t\t// include change for select - fixes #473\n\t\t\t.bind( 'search change keypress input '.split( ' ' ).join( namespace + ' ' ), function( event ) {\n\t\t\t\t// don't get cached data, in case data-column changes dynamically\n\t\t\t\tvar column = parseInt( $( this ).attr( 'data-column' ), 10 ),\n\t\t\t\t\tliveSearch = typeof wo.filter_liveSearch === 'boolean' ?\n\t\t\t\t\t\two.filter_liveSearch :\n\t\t\t\t\t\tts.getColumnData( table, wo.filter_liveSearch, column );\n\t\t\t\tif ( table.config.widgetOptions.filter_initialized &&\n\t\t\t\t\t// immediate search if user presses enter\n\t\t\t\t\t( event.which === tskeyCodes.enter ||\n\t\t\t\t\t\t// immediate search if a \"search\" is triggered on the input\n\t\t\t\t\t\tevent.type === 'search' ||\n\t\t\t\t\t\t// change & input events must be ignored if liveSearch !== true\n\t\t\t\t\t\t( event.type === 'change' || event.type === 'input' ) &&\n\t\t\t\t\t\t// prevent search if liveSearch is a number\n\t\t\t\t\t\tliveSearch === true &&\n\t\t\t\t\t\t// don't allow 'change' or 'input' event to process if the input value\n\t\t\t\t\t\t// is the same - fixes #685\n\t\t\t\t\t\tthis.value !== c.lastSearch[column]\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t// init search with no delay\n\t\t\t\t\t$( this ).attr( 'data-lastSearchTime', new Date().getTime() );\n\t\t\t\t\ttsf.searching( table, event.type !== 'keypress', true, column );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tsearching: function( table, filter, skipFirst, column ) {\n\t\t\tvar liveSearch,\n\t\t\t\two = table.config.widgetOptions;\n\t\t\tif (typeof column === 'undefined') {\n\t\t\t\t// no delay\n\t\t\t\tliveSearch = false;\n\t\t\t} else {\n\t\t\t\tliveSearch = typeof wo.filter_liveSearch === 'boolean' ?\n\t\t\t\t\two.filter_liveSearch :\n\t\t\t\t\t// get column setting, or set to fallback value, or default to false\n\t\t\t\t\tts.getColumnData( table, wo.filter_liveSearch, column );\n\t\t\t\tif ( typeof liveSearch === 'undefined' ) {\n\t\t\t\t\tliveSearch = wo.filter_liveSearch.fallback || false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tclearTimeout( wo.filter_searchTimer );\n\t\t\tif ( typeof filter === 'undefined' || filter === true ) {\n\t\t\t\t// delay filtering\n\t\t\t\two.filter_searchTimer = setTimeout( function() {\n\t\t\t\t\ttsf.checkFilters( table, filter, skipFirst );\n\t\t\t\t}, liveSearch ? wo.filter_searchDelay : 10 );\n\t\t\t} else {\n\t\t\t\t// skip delay\n\t\t\t\ttsf.checkFilters( table, filter, skipFirst );\n\t\t\t}\n\t\t},\n\t\tcheckFilters: function( table, filter, skipFirst ) {\n\t\t\tvar c = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tfilterArray = $.isArray( filter ),\n\t\t\t\tfilters = ( filterArray ) ? filter : ts.getFilters( table, true ),\n\t\t\t\tcombinedFilters = ( filters || [] ).join( '' ); // combined filter values\n\t\t\t// prevent errors if delay init is set\n\t\t\tif ( $.isEmptyObject( c.cache ) ) {\n\t\t\t\t// update cache if delayInit set & pager has initialized ( after user initiates a search )\n\t\t\t\tif ( c.delayInit && ( !c.pager || c.pager && c.pager.initialized ) ) {\n\t\t\t\t\tts.updateCache( c, function() {\n\t\t\t\t\t\ttsf.checkFilters( table, false, skipFirst );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// add filter array back into inputs\n\t\t\tif ( filterArray ) {\n\t\t\t\tts.setFilters( table, filters, false, skipFirst !== true );\n\t\t\t\tif ( !wo.filter_initialized ) { c.lastCombinedFilter = ''; }\n\t\t\t}\n\t\t\tif ( wo.filter_hideFilters ) {\n\t\t\t\t// show/hide filter row as needed\n\t\t\t\tc.$table\n\t\t\t\t\t.find( '.' + tscss.filterRow )\n\t\t\t\t\t.triggerHandler( tsf.hideFiltersCheck( c ) ? 'mouseleave' : 'mouseenter' );\n\t\t\t}\n\t\t\t// return if the last search is the same; but filter === false when updating the search\n\t\t\t// see example-widget-filter.html filter toggle buttons\n\t\t\tif ( c.lastCombinedFilter === combinedFilters && filter !== false ) {\n\t\t\t\treturn;\n\t\t\t} else if ( filter === false ) {\n\t\t\t\t// force filter refresh\n\t\t\t\tc.lastCombinedFilter = null;\n\t\t\t\tc.lastSearch = [];\n\t\t\t}\n\t\t\t// define filter inside it is false\n\t\t\tfilters = filters || [];\n\t\t\t// convert filters to strings - see #1070\n\t\t\tfilters = Array.prototype.map ?\n\t\t\t\tfilters.map( String ) :\n\t\t\t\t// for IE8 & older browsers - maybe not the best method\n\t\t\t\tfilters.join( '\\ufffd' ).split( '\\ufffd' );\n\n\t\t\tif ( wo.filter_initialized ) {\n\t\t\t\tc.$table.triggerHandler( 'filterStart', [ filters ] );\n\t\t\t}\n\t\t\tif ( c.showProcessing ) {\n\t\t\t\t// give it time for the processing icon to kick in\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\ttsf.findRows( table, filters, combinedFilters );\n\t\t\t\t\treturn false;\n\t\t\t\t}, 30 );\n\t\t\t} else {\n\t\t\t\ttsf.findRows( table, filters, combinedFilters );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\thideFiltersCheck: function( c ) {\n\t\t\tif (typeof c.widgetOptions.filter_hideFilters === 'function') {\n\t\t\t\tvar val = c.widgetOptions.filter_hideFilters( c );\n\t\t\t\tif (typeof val === 'boolean') {\n\t\t\t\t\treturn val;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ts.getFilters( c.$table ).join( '' ) === '';\n\t\t},\n\t\thideFilters: function( c, $table ) {\n\t\t\tvar timer;\n\t\t\t( $table || c.$table )\n\t\t\t\t.find( '.' + tscss.filterRow )\n\t\t\t\t.addClass( tscss.filterRowHide )\n\t\t\t\t.bind( 'mouseenter mouseleave', function( e ) {\n\t\t\t\t\t// save event object - http://bugs.jquery.com/ticket/12140\n\t\t\t\t\tvar event = e,\n\t\t\t\t\t\t$row = $( this );\n\t\t\t\t\tclearTimeout( timer );\n\t\t\t\t\ttimer = setTimeout( function() {\n\t\t\t\t\t\tif ( /enter|over/.test( event.type ) ) {\n\t\t\t\t\t\t\t$row.removeClass( tscss.filterRowHide );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// don't hide if input has focus\n\t\t\t\t\t\t\t// $( ':focus' ) needs jQuery 1.6+\n\t\t\t\t\t\t\tif ( $( document.activeElement ).closest( 'tr' )[0] !== $row[0] ) {\n\t\t\t\t\t\t\t\t// don't hide row if any filter has a value\n\t\t\t\t\t\t\t\t$row.toggleClass( tscss.filterRowHide, tsf.hideFiltersCheck( c ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 200 );\n\t\t\t\t})\n\t\t\t\t.find( 'input, select' ).bind( 'focus blur', function( e ) {\n\t\t\t\t\tvar event = e,\n\t\t\t\t\t\t$row = $( this ).closest( 'tr' );\n\t\t\t\t\tclearTimeout( timer );\n\t\t\t\t\ttimer = setTimeout( function() {\n\t\t\t\t\t\tclearTimeout( timer );\n\t\t\t\t\t\t// don't hide row if any filter has a value\n\t\t\t\t\t\t$row.toggleClass( tscss.filterRowHide, tsf.hideFiltersCheck( c ) && event.type !== 'focus' );\n\t\t\t\t\t}, 200 );\n\t\t\t\t});\n\t\t},\n\t\tdefaultFilter: function( filter, mask ) {\n\t\t\tif ( filter === '' ) { return filter; }\n\t\t\tvar regex = tsfRegex.iQuery,\n\t\t\t\tmaskLen = mask.match( tsfRegex.igQuery ).length,\n\t\t\t\tquery = maskLen > 1 ? $.trim( filter ).split( /\\s/ ) : [ $.trim( filter ) ],\n\t\t\t\tlen = query.length - 1,\n\t\t\t\tindx = 0,\n\t\t\t\tval = mask;\n\t\t\tif ( len < 1 && maskLen > 1 ) {\n\t\t\t\t// only one 'word' in query but mask has >1 slots\n\t\t\t\tquery[1] = query[0];\n\t\t\t}\n\t\t\t// replace all {query} with query words...\n\t\t\t// if query = 'Bob', then convert mask from '!{query}' to '!Bob'\n\t\t\t// if query = 'Bob Joe Frank', then convert mask '{q} OR {q}' to 'Bob OR Joe OR Frank'\n\t\t\twhile ( regex.test( val ) ) {\n\t\t\t\tval = val.replace( regex, query[indx++] || '' );\n\t\t\t\tif ( regex.test( val ) && indx < len && ( query[indx] || '' ) !== '' ) {\n\t\t\t\t\tval = mask.replace( regex, val );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn val;\n\t\t},\n\t\tgetLatestSearch: function( $input ) {\n\t\t\tif ( $input ) {\n\t\t\t\treturn $input.sort( function( a, b ) {\n\t\t\t\t\treturn $( b ).attr( 'data-lastSearchTime' ) - $( a ).attr( 'data-lastSearchTime' );\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn $input || $();\n\t\t},\n\t\tfindRange: function( c, val, ignoreRanges ) {\n\t\t\t// look for multiple columns '1-3,4-6,8' in data-column\n\t\t\tvar temp, ranges, range, start, end, singles, i, indx, len,\n\t\t\t\tcolumns = [];\n\t\t\tif ( /^[0-9]+$/.test( val ) ) {\n\t\t\t\t// always return an array\n\t\t\t\treturn [ parseInt( val, 10 ) ];\n\t\t\t}\n\t\t\t// process column range\n\t\t\tif ( !ignoreRanges && /-/.test( val ) ) {\n\t\t\t\tranges = val.match( /(\\d+)\\s*-\\s*(\\d+)/g );\n\t\t\t\tlen = ranges ? ranges.length : 0;\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\trange = ranges[indx].split( /\\s*-\\s*/ );\n\t\t\t\t\tstart = parseInt( range[0], 10 ) || 0;\n\t\t\t\t\tend = parseInt( range[1], 10 ) || ( c.columns - 1 );\n\t\t\t\t\tif ( start > end ) {\n\t\t\t\t\t\ttemp = start; start = end; end = temp; // swap\n\t\t\t\t\t}\n\t\t\t\t\tif ( end >= c.columns ) {\n\t\t\t\t\t\tend = c.columns - 1;\n\t\t\t\t\t}\n\t\t\t\t\tfor ( ; start <= end; start++ ) {\n\t\t\t\t\t\tcolumns[ columns.length ] = start;\n\t\t\t\t\t}\n\t\t\t\t\t// remove processed range from val\n\t\t\t\t\tval = val.replace( ranges[ indx ], '' );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// process single columns\n\t\t\tif ( !ignoreRanges && /,/.test( val ) ) {\n\t\t\t\tsingles = val.split( /\\s*,\\s*/ );\n\t\t\t\tlen = singles.length;\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( singles[ i ] !== '' ) {\n\t\t\t\t\t\tindx = parseInt( singles[ i ], 10 );\n\t\t\t\t\t\tif ( indx < c.columns ) {\n\t\t\t\t\t\t\tcolumns[ columns.length ] = indx;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// return all columns\n\t\t\tif ( !columns.length ) {\n\t\t\t\tfor ( indx = 0; indx < c.columns; indx++ ) {\n\t\t\t\t\tcolumns[ columns.length ] = indx;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn columns;\n\t\t},\n\t\tgetColumnElm: function( c, $elements, column ) {\n\t\t\t// data-column may contain multiple columns '1-3,5-6,8'\n\t\t\t// replaces: c.$filters.filter( '[data-column=\"' + column + '\"]' );\n\t\t\treturn $elements.filter( function() {\n\t\t\t\tvar cols = tsf.findRange( c, $( this ).attr( 'data-column' ) );\n\t\t\t\treturn $.inArray( column, cols ) > -1;\n\t\t\t});\n\t\t},\n\t\tmultipleColumns: function( c, $input ) {\n\t\t\t// look for multiple columns '1-3,4-6,8' in data-column\n\t\t\tvar wo = c.widgetOptions,\n\t\t\t\t// only target 'all' column inputs on initialization\n\t\t\t\t// & don't target 'all' column inputs if they don't exist\n\t\t\t\ttargets = wo.filter_initialized || !$input.filter( wo.filter_anyColumnSelector ).length,\n\t\t\t\tval = $.trim( tsf.getLatestSearch( $input ).attr( 'data-column' ) || '' );\n\t\t\treturn tsf.findRange( c, val, !targets );\n\t\t},\n\t\tprocessTypes: function( c, data, vars ) {\n\t\t\tvar ffxn,\n\t\t\t\tfilterMatched = null,\n\t\t\t\tmatches = null;\n\t\t\tfor ( ffxn in tsf.types ) {\n\t\t\t\tif ( $.inArray( ffxn, vars.excludeMatch ) < 0 && matches === null ) {\n\t\t\t\t\tmatches = tsf.types[ffxn]( c, data, vars );\n\t\t\t\t\tif ( matches !== null ) {\n\t\t\t\t\t\tfilterMatched = matches;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn filterMatched;\n\t\t},\n\t\tmatchType: function( c, columnIndex ) {\n\t\t\tvar isMatch,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\t$el = c.$headerIndexed[ columnIndex ];\n\t\t\t// filter-exact > filter-match > filter_matchType for type\n\t\t\tif ( $el.hasClass( 'filter-exact' ) ) {\n\t\t\t\tisMatch = false;\n\t\t\t} else if ( $el.hasClass( 'filter-match' ) ) {\n\t\t\t\tisMatch = true;\n\t\t\t} else {\n\t\t\t\t// filter-select is not applied when filter_functions are used, so look for a select\n\t\t\t\tif ( wo.filter_columnFilters ) {\n\t\t\t\t\t$el = c.$filters\n\t\t\t\t\t\t.find( '.' + tscss.filter )\n\t\t\t\t\t\t.add( wo.filter_$externalFilters )\n\t\t\t\t\t\t.filter( '[data-column=\"' + columnIndex + '\"]' );\n\t\t\t\t} else if ( wo.filter_$externalFilters ) {\n\t\t\t\t\t$el = wo.filter_$externalFilters.filter( '[data-column=\"' + columnIndex + '\"]' );\n\t\t\t\t}\n\t\t\t\tisMatch = $el.length ?\n\t\t\t\t\tc.widgetOptions.filter_matchType[ ( $el[ 0 ].nodeName || '' ).toLowerCase() ] === 'match' :\n\t\t\t\t\t// default to exact, if no inputs found\n\t\t\t\t\tfalse;\n\t\t\t}\n\t\t\treturn isMatch;\n\t\t},\n\t\tprocessRow: function( c, data, vars ) {\n\t\t\tvar result, filterMatched,\n\t\t\t\tfxn, ffxn, txt,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tshowRow = true,\n\t\t\t\thasAnyMatchInput = wo.filter_$anyMatch && wo.filter_$anyMatch.length,\n\n\t\t\t\t// if wo.filter_$anyMatch data-column attribute is changed dynamically\n\t\t\t\t// we don't want to do an \"anyMatch\" search on one column using data\n\t\t\t\t// for the entire row - see #998\n\t\t\t\tcolumnIndex = wo.filter_$anyMatch && wo.filter_$anyMatch.length ?\n\t\t\t\t\t// look for multiple columns '1-3,4-6,8'\n\t\t\t\t\ttsf.multipleColumns( c, wo.filter_$anyMatch ) :\n\t\t\t\t\t[];\n\t\t\tdata.$cells = data.$row.children();\n\t\t\tif ( data.anyMatchFlag && columnIndex.length > 1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {\n\t\t\t\tdata.anyMatch = true;\n\t\t\t\tdata.isMatch = true;\n\t\t\t\tdata.rowArray = data.$cells.map( function( i ) {\n\t\t\t\t\tif ( $.inArray( i, columnIndex ) > -1 || ( data.anyMatchFilter && !hasAnyMatchInput ) ) {\n\t\t\t\t\t\tif ( data.parsed[ i ] ) {\n\t\t\t\t\t\t\ttxt = data.cacheArray[ i ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttxt = data.rawArray[ i ];\n\t\t\t\t\t\t\ttxt = $.trim( wo.filter_ignoreCase ? txt.toLowerCase() : txt );\n\t\t\t\t\t\t\tif ( c.sortLocaleCompare ) {\n\t\t\t\t\t\t\t\ttxt = ts.replaceAccents( txt );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn txt;\n\t\t\t\t\t}\n\t\t\t\t}).get();\n\t\t\t\tdata.filter = data.anyMatchFilter;\n\t\t\t\tdata.iFilter = data.iAnyMatchFilter;\n\t\t\t\tdata.exact = data.rowArray.join( ' ' );\n\t\t\t\tdata.iExact = wo.filter_ignoreCase ? data.exact.toLowerCase() : data.exact;\n\t\t\t\tdata.cache = data.cacheArray.slice( 0, -1 ).join( ' ' );\n\t\t\t\tvars.excludeMatch = vars.noAnyMatch;\n\t\t\t\tfilterMatched = tsf.processTypes( c, data, vars );\n\t\t\t\tif ( filterMatched !== null ) {\n\t\t\t\t\tshowRow = filterMatched;\n\t\t\t\t} else {\n\t\t\t\t\tif ( wo.filter_startsWith ) {\n\t\t\t\t\t\tshowRow = false;\n\t\t\t\t\t\t// data.rowArray may not contain all columns\n\t\t\t\t\t\tcolumnIndex = Math.min( c.columns, data.rowArray.length );\n\t\t\t\t\t\twhile ( !showRow && columnIndex > 0 ) {\n\t\t\t\t\t\t\tcolumnIndex--;\n\t\t\t\t\t\t\tshowRow = showRow || data.rowArray[ columnIndex ].indexOf( data.iFilter ) === 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tshowRow = ( data.iExact + data.childRowText ).indexOf( data.iFilter ) >= 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdata.anyMatch = false;\n\t\t\t\t// no other filters to process\n\t\t\t\tif ( data.filters.join( '' ) === data.filter ) {\n\t\t\t\t\treturn showRow;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( columnIndex = 0; columnIndex < c.columns; columnIndex++ ) {\n\t\t\t\tdata.filter = data.filters[ columnIndex ];\n\t\t\t\tdata.index = columnIndex;\n\n\t\t\t\t// filter types to exclude, per column\n\t\t\t\tvars.excludeMatch = vars.excludeFilter[ columnIndex ];\n\n\t\t\t\t// ignore if filter is empty or disabled\n\t\t\t\tif ( data.filter ) {\n\t\t\t\t\tdata.cache = data.cacheArray[ columnIndex ];\n\t\t\t\t\tresult = data.parsed[ columnIndex ] ? data.cache : data.rawArray[ columnIndex ] || '';\n\t\t\t\t\tdata.exact = c.sortLocaleCompare ? ts.replaceAccents( result ) : result; // issue #405\n\t\t\t\t\tdata.iExact = !tsfRegex.type.test( typeof data.exact ) && wo.filter_ignoreCase ?\n\t\t\t\t\t\tdata.exact.toLowerCase() : data.exact;\n\t\t\t\t\tdata.isMatch = tsf.matchType( c, columnIndex );\n\n\t\t\t\t\tresult = showRow; // if showRow is true, show that row\n\n\t\t\t\t\t// in case select filter option has a different value vs text 'a - z|A through Z'\n\t\t\t\t\tffxn = wo.filter_columnFilters ?\n\t\t\t\t\t\tc.$filters.add( wo.filter_$externalFilters )\n\t\t\t\t\t\t\t.filter( '[data-column=\"' + columnIndex + '\"]' )\n\t\t\t\t\t\t\t.find( 'select option:selected' )\n\t\t\t\t\t\t\t.attr( 'data-function-name' ) || '' : '';\n\t\t\t\t\t// replace accents - see #357\n\t\t\t\t\tif ( c.sortLocaleCompare ) {\n\t\t\t\t\t\tdata.filter = ts.replaceAccents( data.filter );\n\t\t\t\t\t}\n\n\t\t\t\t\t// replace column specific default filters - see #1088\n\t\t\t\t\tif ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultColFilter[ columnIndex ] ) ) {\n\t\t\t\t\t\tdata.filter = tsf.defaultFilter( data.filter, vars.defaultColFilter[ columnIndex ] );\n\t\t\t\t\t}\n\n\t\t\t\t\t// data.iFilter = case insensitive ( if wo.filter_ignoreCase is true ),\n\t\t\t\t\t// data.filter = case sensitive\n\t\t\t\t\tdata.iFilter = wo.filter_ignoreCase ? ( data.filter || '' ).toLowerCase() : data.filter;\n\t\t\t\t\tfxn = vars.functions[ columnIndex ];\n\t\t\t\t\tfilterMatched = null;\n\t\t\t\t\tif ( fxn ) {\n\t\t\t\t\t\tif ( fxn === true ) {\n\t\t\t\t\t\t\t// default selector uses exact match unless 'filter-match' class is found\n\t\t\t\t\t\t\tfilterMatched = data.isMatch ?\n\t\t\t\t\t\t\t\t// data.iExact may be a number\n\t\t\t\t\t\t\t\t( '' + data.iExact ).search( data.iFilter ) >= 0 :\n\t\t\t\t\t\t\t\tdata.filter === data.exact;\n\t\t\t\t\t\t} else if ( typeof fxn === 'function' ) {\n\t\t\t\t\t\t\t// filter callback( exact cell content, parser normalized content,\n\t\t\t\t\t\t\t// filter input value, column index, jQuery row object )\n\t\t\t\t\t\t\tfilterMatched = fxn( data.exact, data.cache, data.filter, columnIndex, data.$row, c, data );\n\t\t\t\t\t\t} else if ( typeof fxn[ ffxn || data.filter ] === 'function' ) {\n\t\t\t\t\t\t\t// selector option function\n\t\t\t\t\t\t\ttxt = ffxn || data.filter;\n\t\t\t\t\t\t\tfilterMatched =\n\t\t\t\t\t\t\t\tfxn[ txt ]( data.exact, data.cache, data.filter, columnIndex, data.$row, c, data );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( filterMatched === null ) {\n\t\t\t\t\t\t// cycle through the different filters\n\t\t\t\t\t\t// filters return a boolean or null if nothing matches\n\t\t\t\t\t\tfilterMatched = tsf.processTypes( c, data, vars );\n\t\t\t\t\t\tif ( filterMatched !== null ) {\n\t\t\t\t\t\t\tresult = filterMatched;\n\t\t\t\t\t\t// Look for match, and add child row data for matching\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttxt = ( data.iExact + data.childRowText ).indexOf( tsf.parseFilter( c, data.iFilter, data ) );\n\t\t\t\t\t\t\tresult = ( ( !wo.filter_startsWith && txt >= 0 ) || ( wo.filter_startsWith && txt === 0 ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult = filterMatched;\n\t\t\t\t\t}\n\t\t\t\t\tshowRow = ( result ) ? showRow : false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn showRow;\n\t\t},\n\t\tfindRows: function( table, filters, combinedFilters ) {\n\t\t\tif ( table.config.lastCombinedFilter === combinedFilters ||\n\t\t\t\t!table.config.widgetOptions.filter_initialized ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar len, norm_rows, rowData, $rows, $row, rowIndex, tbodyIndex, $tbody, columnIndex,\n\t\t\t\tisChild, childRow, lastSearch, showRow, showParent, time, val, indx,\n\t\t\t\tnotFiltered, searchFiltered, query, injected, res, id, txt,\n\t\t\t\tstoredFilters = $.extend( [], filters ),\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\t// data object passed to filters; anyMatch is a flag for the filters\n\t\t\t\tdata = {\n\t\t\t\t\tanyMatch: false,\n\t\t\t\t\tfilters: filters,\n\t\t\t\t\t// regex filter type cache\n\t\t\t\t\tfilter_regexCache : []\n\t\t\t\t},\n\t\t\t\tvars = {\n\t\t\t\t\t// anyMatch really screws up with these types of filters\n\t\t\t\t\tnoAnyMatch: [ 'range', 'operators' ],\n\t\t\t\t\t// cache filter variables that use ts.getColumnData in the main loop\n\t\t\t\t\tfunctions : [],\n\t\t\t\t\texcludeFilter : [],\n\t\t\t\t\tdefaultColFilter : [],\n\t\t\t\t\tdefaultAnyFilter : ts.getColumnData( table, wo.filter_defaultFilter, c.columns, true ) || ''\n\t\t\t\t};\n\n\t\t\t// parse columns after formatter, in case the class is added at that point\n\t\t\tdata.parsed = [];\n\t\t\tfor ( columnIndex = 0; columnIndex < c.columns; columnIndex++ ) {\n\t\t\t\tdata.parsed[ columnIndex ] = wo.filter_useParsedData ||\n\t\t\t\t\t// parser has a \"parsed\" parameter\n\t\t\t\t\t( c.parsers && c.parsers[ columnIndex ] && c.parsers[ columnIndex ].parsed ||\n\t\t\t\t\t// getData may not return 'parsed' if other 'filter-' class names exist\n\t\t\t\t\t// ( e.g. <th class=\"filter-select filter-parsed\"> )\n\t\t\t\t\tts.getData && ts.getData( c.$headerIndexed[ columnIndex ],\n\t\t\t\t\t\tts.getColumnData( table, c.headers, columnIndex ), 'filter' ) === 'parsed' ||\n\t\t\t\t\tc.$headerIndexed[ columnIndex ].hasClass( 'filter-parsed' ) );\n\n\t\t\t\tvars.functions[ columnIndex ] =\n\t\t\t\t\tts.getColumnData( table, wo.filter_functions, columnIndex ) ||\n\t\t\t\t\tc.$headerIndexed[ columnIndex ].hasClass( 'filter-select' );\n\t\t\t\tvars.defaultColFilter[ columnIndex ] =\n\t\t\t\t\tts.getColumnData( table, wo.filter_defaultFilter, columnIndex ) || '';\n\t\t\t\tvars.excludeFilter[ columnIndex ] =\n\t\t\t\t\t( ts.getColumnData( table, wo.filter_excludeFilter, columnIndex, true ) || '' ).split( /\\s+/ );\n\t\t\t}\n\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole.log( 'Filter: Starting filter widget search', filters );\n\t\t\t\ttime = new Date();\n\t\t\t}\n\t\t\t// filtered rows count\n\t\t\tc.filteredRows = 0;\n\t\t\tc.totalRows = 0;\n\t\t\t// combindedFilters are undefined on init\n\t\t\tcombinedFilters = ( storedFilters || [] ).join( '' );\n\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {\n\t\t\t\t$tbody = ts.processTbody( table, c.$tbodies.eq( tbodyIndex ), true );\n\t\t\t\t// skip child rows & widget added ( removable ) rows - fixes #448 thanks to @hempel!\n\t\t\t\t// $rows = $tbody.children( 'tr' ).not( c.selectorRemove );\n\t\t\t\tcolumnIndex = c.columns;\n\t\t\t\t// convert stored rows into a jQuery object\n\t\t\t\tnorm_rows = c.cache[ tbodyIndex ].normalized;\n\t\t\t\t$rows = $( $.map( norm_rows, function( el ) {\n\t\t\t\t\treturn el[ columnIndex ].$row.get();\n\t\t\t\t}) );\n\n\t\t\t\tif ( combinedFilters === '' || wo.filter_serversideFiltering ) {\n\t\t\t\t\t$rows\n\t\t\t\t\t\t.removeClass( wo.filter_filteredRow )\n\t\t\t\t\t\t.not( '.' + c.cssChildRow )\n\t\t\t\t\t\t.css( 'display', '' );\n\t\t\t\t} else {\n\t\t\t\t\t// filter out child rows\n\t\t\t\t\t$rows = $rows.not( '.' + c.cssChildRow );\n\t\t\t\t\tlen = $rows.length;\n\n\t\t\t\t\tif ( ( wo.filter_$anyMatch && wo.filter_$anyMatch.length ) ||\n\t\t\t\t\t\ttypeof filters[c.columns] !== 'undefined' ) {\n\t\t\t\t\t\tdata.anyMatchFlag = true;\n\t\t\t\t\t\tdata.anyMatchFilter = '' + (\n\t\t\t\t\t\t\tfilters[ c.columns ] ||\n\t\t\t\t\t\t\two.filter_$anyMatch && tsf.getLatestSearch( wo.filter_$anyMatch ).val() ||\n\t\t\t\t\t\t\t''\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif ( wo.filter_columnAnyMatch ) {\n\t\t\t\t\t\t\t// specific columns search\n\t\t\t\t\t\t\tquery = data.anyMatchFilter.split( tsfRegex.andSplit );\n\t\t\t\t\t\t\tinjected = false;\n\t\t\t\t\t\t\tfor ( indx = 0; indx < query.length; indx++ ) {\n\t\t\t\t\t\t\t\tres = query[ indx ].split( ':' );\n\t\t\t\t\t\t\t\tif ( res.length > 1 ) {\n\t\t\t\t\t\t\t\t\t// make the column a one-based index ( non-developers start counting from one :P )\n\t\t\t\t\t\t\t\t\tif ( isNaN( res[0] ) ) {\n\t\t\t\t\t\t\t\t\t\t$.each( c.headerContent, function( i, txt ) {\n\t\t\t\t\t\t\t\t\t\t\t// multiple matches are possible\n\t\t\t\t\t\t\t\t\t\t\tif ( txt.toLowerCase().indexOf( res[0] ) > -1 ) {\n\t\t\t\t\t\t\t\t\t\t\t\tid = i;\n\t\t\t\t\t\t\t\t\t\t\t\tfilters[ id ] = res[1];\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tid = parseInt( res[0], 10 ) - 1;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif ( id >= 0 && id < c.columns ) { // if id is an integer\n\t\t\t\t\t\t\t\t\t\tfilters[ id ] = res[1];\n\t\t\t\t\t\t\t\t\t\tquery.splice( indx, 1 );\n\t\t\t\t\t\t\t\t\t\tindx--;\n\t\t\t\t\t\t\t\t\t\tinjected = true;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( injected ) {\n\t\t\t\t\t\t\t\tdata.anyMatchFilter = query.join( ' && ' );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// optimize searching only through already filtered rows - see #313\n\t\t\t\t\tsearchFiltered = wo.filter_searchFiltered;\n\t\t\t\t\tlastSearch = c.lastSearch || c.$table.data( 'lastSearch' ) || [];\n\t\t\t\t\tif ( searchFiltered ) {\n\t\t\t\t\t\t// cycle through all filters; include last ( columnIndex + 1 = match any column ). Fixes #669\n\t\t\t\t\t\tfor ( indx = 0; indx < columnIndex + 1; indx++ ) {\n\t\t\t\t\t\t\tval = filters[indx] || '';\n\t\t\t\t\t\t\t// break out of loop if we've already determined not to search filtered rows\n\t\t\t\t\t\t\tif ( !searchFiltered ) { indx = columnIndex; }\n\t\t\t\t\t\t\t// search already filtered rows if...\n\t\t\t\t\t\t\tsearchFiltered = searchFiltered && lastSearch.length &&\n\t\t\t\t\t\t\t\t// there are no changes from beginning of filter\n\t\t\t\t\t\t\t\tval.indexOf( lastSearch[indx] || '' ) === 0 &&\n\t\t\t\t\t\t\t\t// if there is NOT a logical 'or', or range ( 'to' or '-' ) in the string\n\t\t\t\t\t\t\t\t!tsfRegex.alreadyFiltered.test( val ) &&\n\t\t\t\t\t\t\t\t// if we are not doing exact matches, using '|' ( logical or ) or not '!'\n\t\t\t\t\t\t\t\t!tsfRegex.exactTest.test( val ) &&\n\t\t\t\t\t\t\t\t// don't search only filtered if the value is negative\n\t\t\t\t\t\t\t\t// ( '> -10' => '> -100' will ignore hidden rows )\n\t\t\t\t\t\t\t\t!( tsfRegex.isNeg1.test( val ) || tsfRegex.isNeg2.test( val ) ) &&\n\t\t\t\t\t\t\t\t// if filtering using a select without a 'filter-match' class ( exact match ) - fixes #593\n\t\t\t\t\t\t\t\t!( val !== '' && c.$filters && c.$filters.filter( '[data-column=\"' + indx + '\"]' ).find( 'select' ).length &&\n\t\t\t\t\t\t\t\t\t!tsf.matchType( c, indx ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tnotFiltered = $rows.not( '.' + wo.filter_filteredRow ).length;\n\t\t\t\t\t// can't search when all rows are hidden - this happens when looking for exact matches\n\t\t\t\t\tif ( searchFiltered && notFiltered === 0 ) { searchFiltered = false; }\n\t\t\t\t\tif ( c.debug ) {\n\t\t\t\t\t\tconsole.log( 'Filter: Searching through ' +\n\t\t\t\t\t\t\t( searchFiltered && notFiltered < len ? notFiltered : 'all' ) + ' rows' );\n\t\t\t\t\t}\n\t\t\t\t\tif ( data.anyMatchFlag ) {\n\t\t\t\t\t\tif ( c.sortLocaleCompare ) {\n\t\t\t\t\t\t\t// replace accents\n\t\t\t\t\t\t\tdata.anyMatchFilter = ts.replaceAccents( data.anyMatchFilter );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( wo.filter_defaultFilter && tsfRegex.iQuery.test( vars.defaultAnyFilter ) ) {\n\t\t\t\t\t\t\tdata.anyMatchFilter = tsf.defaultFilter( data.anyMatchFilter, vars.defaultAnyFilter );\n\t\t\t\t\t\t\t// clear search filtered flag because default filters are not saved to the last search\n\t\t\t\t\t\t\tsearchFiltered = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// make iAnyMatchFilter lowercase unless both filter widget & core ignoreCase options are true\n\t\t\t\t\t\t// when c.ignoreCase is true, the cache contains all lower case data\n\t\t\t\t\t\tdata.iAnyMatchFilter = !( wo.filter_ignoreCase && c.ignoreCase ) ?\n\t\t\t\t\t\t\tdata.anyMatchFilter :\n\t\t\t\t\t\t\tdata.anyMatchFilter.toLowerCase();\n\t\t\t\t\t}\n\n\t\t\t\t\t// loop through the rows\n\t\t\t\t\tfor ( rowIndex = 0; rowIndex < len; rowIndex++ ) {\n\n\t\t\t\t\t\ttxt = $rows[ rowIndex ].className;\n\t\t\t\t\t\t// the first row can never be a child row\n\t\t\t\t\t\tisChild = rowIndex && tsfRegex.child.test( txt );\n\t\t\t\t\t\t// skip child rows & already filtered rows\n\t\t\t\t\t\tif ( isChild || ( searchFiltered && tsfRegex.filtered.test( txt ) ) ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdata.$row = $rows.eq( rowIndex );\n\t\t\t\t\t\tdata.rowIndex = rowIndex;\n\t\t\t\t\t\tdata.cacheArray = norm_rows[ rowIndex ];\n\t\t\t\t\t\trowData = data.cacheArray[ c.columns ];\n\t\t\t\t\t\tdata.rawArray = rowData.raw;\n\t\t\t\t\t\tdata.childRowText = '';\n\n\t\t\t\t\t\tif ( !wo.filter_childByColumn ) {\n\t\t\t\t\t\t\ttxt = '';\n\t\t\t\t\t\t\t// child row cached text\n\t\t\t\t\t\t\tchildRow = rowData.child;\n\t\t\t\t\t\t\t// so, if 'table.config.widgetOptions.filter_childRows' is true and there is\n\t\t\t\t\t\t\t// a match anywhere in the child row, then it will make the row visible\n\t\t\t\t\t\t\t// checked here so the option can be changed dynamically\n\t\t\t\t\t\t\tfor ( indx = 0; indx < childRow.length; indx++ ) {\n\t\t\t\t\t\t\t\ttxt += ' ' + childRow[indx].join( ' ' ) || '';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdata.childRowText = wo.filter_childRows ?\n\t\t\t\t\t\t\t\t( wo.filter_ignoreCase ? txt.toLowerCase() : txt ) :\n\t\t\t\t\t\t\t\t'';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tshowRow = false;\n\t\t\t\t\t\tshowParent = tsf.processRow( c, data, vars );\n\t\t\t\t\t\t$row = rowData.$row;\n\n\t\t\t\t\t\t// don't pass reference to val\n\t\t\t\t\t\tval = showParent ? true : false;\n\t\t\t\t\t\tchildRow = rowData.$row.filter( ':gt(0)' );\n\t\t\t\t\t\tif ( wo.filter_childRows && childRow.length ) {\n\t\t\t\t\t\t\tif ( wo.filter_childByColumn ) {\n\t\t\t\t\t\t\t\tif ( !wo.filter_childWithSibs ) {\n\t\t\t\t\t\t\t\t\t// hide all child rows\n\t\t\t\t\t\t\t\t\tchildRow.addClass( wo.filter_filteredRow );\n\t\t\t\t\t\t\t\t\t// if only showing resulting child row, only include parent\n\t\t\t\t\t\t\t\t\t$row = $row.eq( 0 );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// cycle through each child row\n\t\t\t\t\t\t\t\tfor ( indx = 0; indx < childRow.length; indx++ ) {\n\t\t\t\t\t\t\t\t\tdata.$row = childRow.eq( indx );\n\t\t\t\t\t\t\t\t\tdata.cacheArray = rowData.child[ indx ];\n\t\t\t\t\t\t\t\t\tdata.rawArray = data.cacheArray;\n\t\t\t\t\t\t\t\t\tval = tsf.processRow( c, data, vars );\n\t\t\t\t\t\t\t\t\t// use OR comparison on child rows\n\t\t\t\t\t\t\t\t\tshowRow = showRow || val;\n\t\t\t\t\t\t\t\t\tif ( !wo.filter_childWithSibs && val ) {\n\t\t\t\t\t\t\t\t\t\tchildRow.eq( indx ).removeClass( wo.filter_filteredRow );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// keep parent row match even if no child matches... see #1020\n\t\t\t\t\t\t\tshowRow = showRow || showParent;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tshowRow = val;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$row\n\t\t\t\t\t\t\t.toggleClass( wo.filter_filteredRow, !showRow )[0]\n\t\t\t\t\t\t\t.display = showRow ? '' : 'none';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tc.filteredRows += $rows.not( '.' + wo.filter_filteredRow ).length;\n\t\t\t\tc.totalRows += $rows.length;\n\t\t\t\tts.processTbody( table, $tbody, false );\n\t\t\t}\n\t\t\tc.lastCombinedFilter = combinedFilters; // save last search\n\t\t\t// don't save 'filters' directly since it may have altered ( AnyMatch column searches )\n\t\t\tc.lastSearch = storedFilters;\n\t\t\tc.$table.data( 'lastSearch', storedFilters );\n\t\t\tif ( wo.filter_saveFilters && ts.storage ) {\n\t\t\t\tts.storage( table, 'tablesorter-filters', tsf.processFilters( storedFilters, true ) );\n\t\t\t}\n\t\t\tif ( c.debug ) {\n\t\t\t\tconsole.log( 'Completed filter widget search' + ts.benchmark(time) );\n\t\t\t}\n\t\t\tif ( wo.filter_initialized ) {\n\t\t\t\tc.$table.triggerHandler( 'filterBeforeEnd', c );\n\t\t\t\tc.$table.triggerHandler( 'filterEnd', c );\n\t\t\t}\n\t\t\tsetTimeout( function() {\n\t\t\t\tts.applyWidget( c.table ); // make sure zebra widget is applied\n\t\t\t}, 0 );\n\t\t},\n\t\tgetOptionSource: function( table, column, onlyAvail ) {\n\t\t\ttable = $( table )[0];\n\t\t\tvar c = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tarry = false,\n\t\t\t\tsource = wo.filter_selectSource,\n\t\t\t\tlast = c.$table.data( 'lastSearch' ) || [],\n\t\t\t\tfxn = typeof source === 'function' ? true : ts.getColumnData( table, source, column );\n\n\t\t\tif ( onlyAvail && last[column] !== '' ) {\n\t\t\t\tonlyAvail = false;\n\t\t\t}\n\n\t\t\t// filter select source option\n\t\t\tif ( fxn === true ) {\n\t\t\t\t// OVERALL source\n\t\t\t\tarry = source( table, column, onlyAvail );\n\t\t\t} else if ( fxn instanceof $ || ( $.type( fxn ) === 'string' && fxn.indexOf( '</option>' ) >= 0 ) ) {\n\t\t\t\t// selectSource is a jQuery object or string of options\n\t\t\t\treturn fxn;\n\t\t\t} else if ( $.isArray( fxn ) ) {\n\t\t\t\tarry = fxn;\n\t\t\t} else if ( $.type( source ) === 'object' && fxn ) {\n\t\t\t\t// custom select source function for a SPECIFIC COLUMN\n\t\t\t\tarry = fxn( table, column, onlyAvail );\n\t\t\t}\n\t\t\tif ( arry === false ) {\n\t\t\t\t// fall back to original method\n\t\t\t\tarry = tsf.getOptions( table, column, onlyAvail );\n\t\t\t}\n\n\t\t\treturn tsf.processOptions( table, column, arry );\n\n\t\t},\n\t\tprocessOptions: function( table, column, arry ) {\n\t\t\tif ( !$.isArray( arry ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\ttable = $( table )[0];\n\t\t\tvar cts, txt, indx, len, parsedTxt, str,\n\t\t\t\tc = table.config,\n\t\t\t\tvalidColumn = typeof column !== 'undefined' && column !== null && column >= 0 && column < c.columns,\n\t\t\t\tdirection = validColumn ? c.$headerIndexed[ column ].hasClass( 'filter-select-sort-desc' ) : false,\n\t\t\t\tparsed = [];\n\t\t\t// get unique elements and sort the list\n\t\t\t// if $.tablesorter.sortText exists ( not in the original tablesorter ),\n\t\t\t// then natural sort the list otherwise use a basic sort\n\t\t\tarry = $.grep( arry, function( value, indx ) {\n\t\t\t\tif ( value.text ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn $.inArray( value, arry ) === indx;\n\t\t\t});\n\t\t\tif ( validColumn && c.$headerIndexed[ column ].hasClass( 'filter-select-nosort' ) ) {\n\t\t\t\t// unsorted select options\n\t\t\t\treturn arry;\n\t\t\t} else {\n\t\t\t\tlen = arry.length;\n\t\t\t\t// parse select option values\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\ttxt = arry[ indx ];\n\t\t\t\t\t// check for object\n\t\t\t\t\tstr = txt.text ? txt.text : txt;\n\t\t\t\t\t// sortNatural breaks if you don't pass it strings\n\t\t\t\t\tparsedTxt = ( validColumn && c.parsers && c.parsers.length &&\n\t\t\t\t\t\tc.parsers[ column ].format( str, table, [], column ) || str ).toString();\n\t\t\t\t\tparsedTxt = c.widgetOptions.filter_ignoreCase ? parsedTxt.toLowerCase() : parsedTxt;\n\t\t\t\t\t// parse array data using set column parser; this DOES NOT pass the original\n\t\t\t\t\t// table cell to the parser format function\n\t\t\t\t\tif ( txt.text ) {\n\t\t\t\t\t\ttxt.parsed = parsedTxt;\n\t\t\t\t\t\tparsed[ parsed.length ] = txt;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tparsed[ parsed.length ] = {\n\t\t\t\t\t\t\ttext : txt,\n\t\t\t\t\t\t\t// check parser length - fixes #934\n\t\t\t\t\t\t\tparsed : parsedTxt\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// sort parsed select options\n\t\t\t\tcts = c.textSorter || '';\n\t\t\t\tparsed.sort( function( a, b ) {\n\t\t\t\t\tvar x = direction ? b.parsed : a.parsed,\n\t\t\t\t\t\ty = direction ? a.parsed : b.parsed;\n\t\t\t\t\tif ( validColumn && typeof cts === 'function' ) {\n\t\t\t\t\t\t// custom OVERALL text sorter\n\t\t\t\t\t\treturn cts( x, y, true, column, table );\n\t\t\t\t\t} else if ( validColumn && typeof cts === 'object' && cts.hasOwnProperty( column ) ) {\n\t\t\t\t\t\t// custom text sorter for a SPECIFIC COLUMN\n\t\t\t\t\t\treturn cts[column]( x, y, true, column, table );\n\t\t\t\t\t} else if ( ts.sortNatural ) {\n\t\t\t\t\t\t// fall back to natural sort\n\t\t\t\t\t\treturn ts.sortNatural( x, y );\n\t\t\t\t\t}\n\t\t\t\t\t// using an older version! do a basic sort\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\t// rebuild arry from sorted parsed data\n\t\t\t\tarry = [];\n\t\t\t\tlen = parsed.length;\n\t\t\t\tfor ( indx = 0; indx < len; indx++ ) {\n\t\t\t\t\tarry[ arry.length ] = parsed[indx];\n\t\t\t\t}\n\t\t\t\treturn arry;\n\t\t\t}\n\t\t},\n\t\tgetOptions: function( table, column, onlyAvail ) {\n\t\t\ttable = $( table )[0];\n\t\t\tvar rowIndex, tbodyIndex, len, row, cache, indx, child, childLen,\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tarry = [];\n\t\t\tfor ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {\n\t\t\t\tcache = c.cache[tbodyIndex];\n\t\t\t\tlen = c.cache[tbodyIndex].normalized.length;\n\t\t\t\t// loop through the rows\n\t\t\t\tfor ( rowIndex = 0; rowIndex < len; rowIndex++ ) {\n\t\t\t\t\t// get cached row from cache.row ( old ) or row data object\n\t\t\t\t\t// ( new; last item in normalized array )\n\t\t\t\t\trow = cache.row ?\n\t\t\t\t\t\tcache.row[ rowIndex ] :\n\t\t\t\t\t\tcache.normalized[ rowIndex ][ c.columns ].$row[0];\n\t\t\t\t\t// check if has class filtered\n\t\t\t\t\tif ( onlyAvail && row.className.match( wo.filter_filteredRow ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\t// get non-normalized cell content\n\t\t\t\t\tif ( wo.filter_useParsedData ||\n\t\t\t\t\t\tc.parsers[column].parsed ||\n\t\t\t\t\t\tc.$headerIndexed[column].hasClass( 'filter-parsed' ) ) {\n\t\t\t\t\t\tarry[ arry.length ] = '' + cache.normalized[ rowIndex ][ column ];\n\t\t\t\t\t\t// child row parsed data\n\t\t\t\t\t\tif ( wo.filter_childRows && wo.filter_childByColumn ) {\n\t\t\t\t\t\t\tchildLen = cache.normalized[ rowIndex ][ c.columns ].$row.length - 1;\n\t\t\t\t\t\t\tfor ( indx = 0; indx < childLen; indx++ ) {\n\t\t\t\t\t\t\t\tarry[ arry.length ] = '' + cache.normalized[ rowIndex ][ c.columns ].child[ indx ][ column ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// get raw cached data instead of content directly from the cells\n\t\t\t\t\t\tarry[ arry.length ] = cache.normalized[ rowIndex ][ c.columns ].raw[ column ];\n\t\t\t\t\t\t// child row unparsed data\n\t\t\t\t\t\tif ( wo.filter_childRows && wo.filter_childByColumn ) {\n\t\t\t\t\t\t\tchildLen = cache.normalized[ rowIndex ][ c.columns ].$row.length;\n\t\t\t\t\t\t\tfor ( indx = 1; indx < childLen; indx++ ) {\n\t\t\t\t\t\t\t\tchild = cache.normalized[ rowIndex ][ c.columns ].$row.eq( indx ).children().eq( column );\n\t\t\t\t\t\t\t\tarry[ arry.length ] = '' + ts.getElementText( c, child, column );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn arry;\n\t\t},\n\t\tbuildSelect: function( table, column, arry, updating, onlyAvail ) {\n\t\t\ttable = $( table )[0];\n\t\t\tcolumn = parseInt( column, 10 );\n\t\t\tif ( !table.config.cache || $.isEmptyObject( table.config.cache ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tvar indx, val, txt, t, $filters, $filter, option,\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tnode = c.$headerIndexed[ column ],\n\t\t\t\t// t.data( 'placeholder' ) won't work in jQuery older than 1.4.3\n\t\t\t\toptions = '<option value=\"\">' +\n\t\t\t\t\t( node.data( 'placeholder' ) ||\n\t\t\t\t\t\tnode.attr( 'data-placeholder' ) ||\n\t\t\t\t\t\two.filter_placeholder.select || ''\n\t\t\t\t\t) + '</option>',\n\t\t\t\t// Get curent filter value\n\t\t\t\tcurrentValue = c.$table\n\t\t\t\t\t.find( 'thead' )\n\t\t\t\t\t.find( 'select.' + tscss.filter + '[data-column=\"' + column + '\"]' )\n\t\t\t\t\t.val();\n\n\t\t\t// nothing included in arry ( external source ), so get the options from\n\t\t\t// filter_selectSource or column data\n\t\t\tif ( typeof arry === 'undefined' || arry === '' ) {\n\t\t\t\tarry = tsf.getOptionSource( table, column, onlyAvail );\n\t\t\t}\n\n\t\t\tif ( $.isArray( arry ) ) {\n\t\t\t\t// build option list\n\t\t\t\tfor ( indx = 0; indx < arry.length; indx++ ) {\n\t\t\t\t\toption = arry[ indx ];\n\t\t\t\t\tif ( option.text ) {\n\t\t\t\t\t\t// OBJECT!! add data-function-name in case the value is set in filter_functions\n\t\t\t\t\t\toption['data-function-name'] = typeof option.value === 'undefined' ? option.text : option.value;\n\n\t\t\t\t\t\t// support jQuery < v1.8, otherwise the below code could be shortened to\n\t\t\t\t\t\t// options += $( '<option>', option )[ 0 ].outerHTML;\n\t\t\t\t\t\toptions += '<option';\n\t\t\t\t\t\tfor ( val in option ) {\n\t\t\t\t\t\t\tif ( option.hasOwnProperty( val ) && val !== 'text' ) {\n\t\t\t\t\t\t\t\toptions += ' ' + val + '=\"' + option[ val ] + '\"';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( !option.value ) {\n\t\t\t\t\t\t\toptions += ' value=\"' + option.text + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\toptions += '>' + option.text + '</option>';\n\t\t\t\t\t\t// above code is needed in jQuery < v1.8\n\n\t\t\t\t\t\t// make sure we don't turn an object into a string (objects without a \"text\" property)\n\t\t\t\t\t} else if ( '' + option !== '[object Object]' ) {\n\t\t\t\t\t\ttxt = option = ( '' + option ).replace( tsfRegex.quote, '"' );\n\t\t\t\t\t\tval = txt;\n\t\t\t\t\t\t// allow including a symbol in the selectSource array\n\t\t\t\t\t\t// 'a-z|A through Z' so that 'a-z' becomes the option value\n\t\t\t\t\t\t// and 'A through Z' becomes the option text\n\t\t\t\t\t\tif ( txt.indexOf( wo.filter_selectSourceSeparator ) >= 0 ) {\n\t\t\t\t\t\t\tt = txt.split( wo.filter_selectSourceSeparator );\n\t\t\t\t\t\t\tval = t[0];\n\t\t\t\t\t\t\ttxt = t[1];\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// replace quotes - fixes #242 & ignore empty strings\n\t\t\t\t\t\t// see http://stackoverflow.com/q/14990971/145346\n\t\t\t\t\t\toptions += option !== '' ?\n\t\t\t\t\t\t\t'<option ' +\n\t\t\t\t\t\t\t\t( val === txt ? '' : 'data-function-name=\"' + option + '\" ' ) +\n\t\t\t\t\t\t\t\t'value=\"' + val + '\">' + txt +\n\t\t\t\t\t\t\t'</option>' : '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// clear arry so it doesn't get appended twice\n\t\t\t\tarry = [];\n\t\t\t}\n\n\t\t\t// update all selects in the same column ( clone thead in sticky headers &\n\t\t\t// any external selects ) - fixes 473\n\t\t\t$filters = ( c.$filters ? c.$filters : c.$table.children( 'thead' ) )\n\t\t\t\t.find( '.' + tscss.filter );\n\t\t\tif ( wo.filter_$externalFilters ) {\n\t\t\t\t$filters = $filters && $filters.length ?\n\t\t\t\t\t$filters.add( wo.filter_$externalFilters ) :\n\t\t\t\t\two.filter_$externalFilters;\n\t\t\t}\n\t\t\t$filter = $filters.filter( 'select[data-column=\"' + column + '\"]' );\n\n\t\t\t// make sure there is a select there!\n\t\t\tif ( $filter.length ) {\n\t\t\t\t$filter[ updating ? 'html' : 'append' ]( options );\n\t\t\t\tif ( !$.isArray( arry ) ) {\n\t\t\t\t\t// append options if arry is provided externally as a string or jQuery object\n\t\t\t\t\t// options ( default value ) was already added\n\t\t\t\t\t$filter.append( arry ).val( currentValue );\n\t\t\t\t}\n\t\t\t\t$filter.val( currentValue );\n\t\t\t}\n\t\t},\n\t\tbuildDefault: function( table, updating ) {\n\t\t\tvar columnIndex, $header, noSelect,\n\t\t\t\tc = table.config,\n\t\t\t\two = c.widgetOptions,\n\t\t\t\tcolumns = c.columns;\n\t\t\t// build default select dropdown\n\t\t\tfor ( columnIndex = 0; columnIndex < columns; columnIndex++ ) {\n\t\t\t\t$header = c.$headerIndexed[columnIndex];\n\t\t\t\tnoSelect = !( $header.hasClass( 'filter-false' ) || $header.hasClass( 'parser-false' ) );\n\t\t\t\t// look for the filter-select class; build/update it if found\n\t\t\t\tif ( ( $header.hasClass( 'filter-select' ) ||\n\t\t\t\t\tts.getColumnData( table, wo.filter_functions, columnIndex ) === true ) && noSelect ) {\n\t\t\t\t\ttsf.buildSelect( table, columnIndex, '', updating, $header.hasClass( wo.filter_onlyAvail ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\t// filter regex variable\n\ttsfRegex = tsf.regex;\n\n\tts.getFilters = function( table, getRaw, setFilters, skipFirst ) {\n\t\tvar i, $filters, $column, cols,\n\t\t\tfilters = [],\n\t\t\tc = table ? $( table )[0].config : '',\n\t\t\two = c ? c.widgetOptions : '';\n\t\tif ( ( getRaw !== true && wo && !wo.filter_columnFilters ) ||\n\t\t\t// setFilters called, but last search is exactly the same as the current\n\t\t\t// fixes issue #733 & #903 where calling update causes the input values to reset\n\t\t\t( $.isArray(setFilters) && setFilters.join('') === c.lastCombinedFilter ) ) {\n\t\t\treturn $( table ).data( 'lastSearch' );\n\t\t}\n\t\tif ( c ) {\n\t\t\tif ( c.$filters ) {\n\t\t\t\t$filters = c.$filters.find( '.' + tscss.filter );\n\t\t\t}\n\t\t\tif ( wo.filter_$externalFilters ) {\n\t\t\t\t$filters = $filters && $filters.length ?\n\t\t\t\t\t$filters.add( wo.filter_$externalFilters ) :\n\t\t\t\t\two.filter_$externalFilters;\n\t\t\t}\n\t\t\tif ( $filters && $filters.length ) {\n\t\t\t\tfilters = setFilters || [];\n\t\t\t\tfor ( i = 0; i < c.columns + 1; i++ ) {\n\t\t\t\t\tcols = ( i === c.columns ?\n\t\t\t\t\t\t// 'all' columns can now include a range or set of columms ( data-column='0-2,4,6-7' )\n\t\t\t\t\t\two.filter_anyColumnSelector + ',' + wo.filter_multipleColumnSelector :\n\t\t\t\t\t\t'[data-column=\"' + i + '\"]' );\n\t\t\t\t\t$column = $filters.filter( cols );\n\t\t\t\t\tif ( $column.length ) {\n\t\t\t\t\t\t// move the latest search to the first slot in the array\n\t\t\t\t\t\t$column = tsf.getLatestSearch( $column );\n\t\t\t\t\t\tif ( $.isArray( setFilters ) ) {\n\t\t\t\t\t\t\t// skip first ( latest input ) to maintain cursor position while typing\n\t\t\t\t\t\t\tif ( skipFirst && $column.length > 1 ) {\n\t\t\t\t\t\t\t\t$column = $column.slice( 1 );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( i === c.columns ) {\n\t\t\t\t\t\t\t\t// prevent data-column='all' from filling data-column='0,1' ( etc )\n\t\t\t\t\t\t\t\tcols = $column.filter( wo.filter_anyColumnSelector );\n\t\t\t\t\t\t\t\t$column = cols.length ? cols : $column;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t$column\n\t\t\t\t\t\t\t\t.val( setFilters[ i ] )\n\t\t\t\t\t\t\t\t// must include a namespace here; but not c.namespace + 'filter'?\n\t\t\t\t\t\t\t\t.trigger( 'change' + c.namespace );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tfilters[i] = $column.val() || '';\n\t\t\t\t\t\t\t// don't change the first... it will move the cursor\n\t\t\t\t\t\t\tif ( i === c.columns ) {\n\t\t\t\t\t\t\t\t// don't update range columns from 'all' setting\n\t\t\t\t\t\t\t\t$column\n\t\t\t\t\t\t\t\t\t.slice( 1 )\n\t\t\t\t\t\t\t\t\t.filter( '[data-column*=\"' + $column.attr( 'data-column' ) + '\"]' )\n\t\t\t\t\t\t\t\t\t.val( filters[ i ] );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t$column\n\t\t\t\t\t\t\t\t\t.slice( 1 )\n\t\t\t\t\t\t\t\t\t.val( filters[ i ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// save any match input dynamically\n\t\t\t\t\t\tif ( i === c.columns && $column.length ) {\n\t\t\t\t\t\t\two.filter_$anyMatch = $column;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn filters;\n\t};\n\n\tts.setFilters = function( table, filter, apply, skipFirst ) {\n\t\tvar c = table ? $( table )[0].config : '',\n\t\t\tvalid = ts.getFilters( table, true, filter, skipFirst );\n\t\t// default apply to \"true\"\n\t\tif ( typeof apply === 'undefined' ) {\n\t\t\tapply = true;\n\t\t}\n\t\tif ( c && apply ) {\n\t\t\t// ensure new set filters are applied, even if the search is the same\n\t\t\tc.lastCombinedFilter = null;\n\t\t\tc.lastSearch = [];\n\t\t\ttsf.searching( c.table, filter, skipFirst );\n\t\t\tc.$table.triggerHandler( 'filterFomatterUpdate' );\n\t\t}\n\t\treturn valid.length !== 0;\n\t};\n\n})( jQuery );\n\n/*! Widget: stickyHeaders - updated 1/6/2017 (v2.28.4) *//*\n * Requires tablesorter v2.8+ and jQuery 1.4.3+\n * by Rob Garrison\n */\n;(function ($, window) {\n\t'use strict';\n\tvar ts = $.tablesorter || {};\n\n\t$.extend(ts.css, {\n\t\tsticky : 'tablesorter-stickyHeader', // stickyHeader\n\t\tstickyVis : 'tablesorter-sticky-visible',\n\t\tstickyHide: 'tablesorter-sticky-hidden',\n\t\tstickyWrap: 'tablesorter-sticky-wrapper'\n\t});\n\n\t// Add a resize event to table headers\n\tts.addHeaderResizeEvent = function(table, disable, settings) {\n\t\ttable = $(table)[0]; // make sure we're using a dom element\n\t\tif ( !table.config ) { return; }\n\t\tvar defaults = {\n\t\t\t\ttimer : 250\n\t\t\t},\n\t\t\toptions = $.extend({}, defaults, settings),\n\t\t\tc = table.config,\n\t\t\two = c.widgetOptions,\n\t\t\tcheckSizes = function( triggerEvent ) {\n\t\t\t\tvar index, headers, $header, sizes, width, height,\n\t\t\t\t\tlen = c.$headers.length;\n\t\t\t\two.resize_flag = true;\n\t\t\t\theaders = [];\n\t\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\t\t$header = c.$headers.eq( index );\n\t\t\t\t\tsizes = $header.data( 'savedSizes' ) || [ 0, 0 ]; // fixes #394\n\t\t\t\t\twidth = $header[0].offsetWidth;\n\t\t\t\t\theight = $header[0].offsetHeight;\n\t\t\t\t\tif ( width !== sizes[0] || height !== sizes[1] ) {\n\t\t\t\t\t\t$header.data( 'savedSizes', [ width, height ] );\n\t\t\t\t\t\theaders.push( $header[0] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( headers.length && triggerEvent !== false ) {\n\t\t\t\t\tc.$table.triggerHandler( 'resize', [ headers ] );\n\t\t\t\t}\n\t\t\t\two.resize_flag = false;\n\t\t\t};\n\t\tclearInterval(wo.resize_timer);\n\t\tif (disable) {\n\t\t\two.resize_flag = false;\n\t\t\treturn false;\n\t\t}\n\t\tcheckSizes( false );\n\t\two.resize_timer = setInterval(function() {\n\t\t\tif (wo.resize_flag) { return; }\n\t\t\tcheckSizes();\n\t\t}, options.timer);\n\t};\n\n\t// Sticky headers based on this awesome article:\n\t// http://css-tricks.com/13465-persistent-headers/\n\t// and https://github.com/jmosbech/StickyTableHeaders by Jonas Mosbech\n\t// **************************\n\tts.addWidget({\n\t\tid: 'stickyHeaders',\n\t\tpriority: 54, // sticky widget must be initialized after the filter & before pager widget!\n\t\toptions: {\n\t\t\tstickyHeaders : '', // extra class name added to the sticky header row\n\t\t\tstickyHeaders_appendTo : null, // jQuery selector or object to phycially attach the sticky headers\n\t\t\tstickyHeaders_attachTo : null, // jQuery selector or object to attach scroll listener to (overridden by xScroll & yScroll settings)\n\t\t\tstickyHeaders_xScroll : null, // jQuery selector or object to monitor horizontal scroll position (defaults: xScroll > attachTo > window)\n\t\t\tstickyHeaders_yScroll : null, // jQuery selector or object to monitor vertical scroll position (defaults: yScroll > attachTo > window)\n\t\t\tstickyHeaders_offset : 0, // number or jquery selector targeting the position:fixed element\n\t\t\tstickyHeaders_filteredToTop: true, // scroll table top into view after filtering\n\t\t\tstickyHeaders_cloneId : '-sticky', // added to table ID, if it exists\n\t\t\tstickyHeaders_addResizeEvent : true, // trigger 'resize' event on headers\n\t\t\tstickyHeaders_includeCaption : true, // if false and a caption exist, it won't be included in the sticky header\n\t\t\tstickyHeaders_zIndex : 2 // The zIndex of the stickyHeaders, allows the user to adjust this to their needs\n\t\t},\n\t\tformat: function(table, c, wo) {\n\t\t\t// filter widget doesn't initialize on an empty table. Fixes #449\n\t\t\tif ( c.$table.hasClass('hasStickyHeaders') || ($.inArray('filter', c.widgets) >= 0 && !c.$table.hasClass('hasFilters')) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar index, len, $t,\n\t\t\t\t$table = c.$table,\n\t\t\t\t// add position: relative to attach element, hopefully it won't cause trouble.\n\t\t\t\t$attach = $(wo.stickyHeaders_attachTo),\n\t\t\t\tnamespace = c.namespace + 'stickyheaders ',\n\t\t\t\t// element to watch for the scroll event\n\t\t\t\t$yScroll = $(wo.stickyHeaders_yScroll || wo.stickyHeaders_attachTo || window),\n\t\t\t\t$xScroll = $(wo.stickyHeaders_xScroll || wo.stickyHeaders_attachTo || window),\n\t\t\t\t$thead = $table.children('thead:first'),\n\t\t\t\t$header = $thead.children('tr').not('.sticky-false').children(),\n\t\t\t\t$tfoot = $table.children('tfoot'),\n\t\t\t\t$stickyOffset = isNaN(wo.stickyHeaders_offset) ? $(wo.stickyHeaders_offset) : '',\n\t\t\t\tstickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0,\n\t\t\t\t// is this table nested? If so, find parent sticky header wrapper (div, not table)\n\t\t\t\t$nestedSticky = $table.parent().closest('.' + ts.css.table).hasClass('hasStickyHeaders') ?\n\t\t\t\t\t$table.parent().closest('table.tablesorter')[0].config.widgetOptions.$sticky.parent() : [],\n\t\t\t\tnestedStickyTop = $nestedSticky.length ? $nestedSticky.height() : 0,\n\t\t\t\t// clone table, then wrap to make sticky header\n\t\t\t\t$stickyTable = wo.$sticky = $table.clone()\n\t\t\t\t\t.addClass('containsStickyHeaders ' + ts.css.sticky + ' ' + wo.stickyHeaders + ' ' + c.namespace.slice(1) + '_extra_table' )\n\t\t\t\t\t.wrap('<div class=\"' + ts.css.stickyWrap + '\">'),\n\t\t\t\t$stickyWrap = $stickyTable.parent()\n\t\t\t\t\t.addClass(ts.css.stickyHide)\n\t\t\t\t\t.css({\n\t\t\t\t\t\tposition : $attach.length ? 'absolute' : 'fixed',\n\t\t\t\t\t\tpadding : parseInt( $stickyTable.parent().parent().css('padding-left'), 10 ),\n\t\t\t\t\t\ttop : stickyOffset + nestedStickyTop,\n\t\t\t\t\t\tleft : 0,\n\t\t\t\t\t\tvisibility : 'hidden',\n\t\t\t\t\t\tzIndex : wo.stickyHeaders_zIndex || 2\n\t\t\t\t\t}),\n\t\t\t\t$stickyThead = $stickyTable.children('thead:first'),\n\t\t\t\t$stickyCells,\n\t\t\t\tlaststate = '',\n\t\t\t\tspacing = 0,\n\t\t\t\tsetWidth = function($orig, $clone){\n\t\t\t\t\tvar index, width, border, $cell, $this,\n\t\t\t\t\t\t$cells = $orig.filter(':visible'),\n\t\t\t\t\t\tlen = $cells.length;\n\t\t\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\t\t\t$cell = $clone.filter(':visible').eq(index);\n\t\t\t\t\t\t$this = $cells.eq(index);\n\t\t\t\t\t\t// code from https://github.com/jmosbech/StickyTableHeaders\n\t\t\t\t\t\tif ($this.css('box-sizing') === 'border-box') {\n\t\t\t\t\t\t\twidth = $this.outerWidth();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ($cell.css('border-collapse') === 'collapse') {\n\t\t\t\t\t\t\t\tif (window.getComputedStyle) {\n\t\t\t\t\t\t\t\t\twidth = parseFloat( window.getComputedStyle($this[0], null).width );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// ie8 only\n\t\t\t\t\t\t\t\t\tborder = parseFloat( $this.css('border-width') );\n\t\t\t\t\t\t\t\t\twidth = $this.outerWidth() - parseFloat( $this.css('padding-left') ) - parseFloat( $this.css('padding-right') ) - border;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\twidth = $this.width();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$cell.css({\n\t\t\t\t\t\t\t'width': width,\n\t\t\t\t\t\t\t'min-width': width,\n\t\t\t\t\t\t\t'max-width': width\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tresizeHeader = function() {\n\t\t\t\t\tstickyOffset = $stickyOffset.length ? $stickyOffset.height() || 0 : parseInt(wo.stickyHeaders_offset, 10) || 0;\n\t\t\t\t\tspacing = 0;\n\t\t\t\t\t$stickyWrap.css({\n\t\t\t\t\t\tleft : $attach.length ? parseInt($attach.css('padding-left'), 10) || 0 :\n\t\t\t\t\t\t\t\t$table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing,\n\t\t\t\t\t\twidth: $table.outerWidth()\n\t\t\t\t\t});\n\t\t\t\t\tsetWidth( $table, $stickyTable );\n\t\t\t\t\tsetWidth( $header, $stickyCells );\n\t\t\t\t},\n\t\t\t\tscrollSticky = function( resizing ) {\n\t\t\t\t\tif (!$table.is(':visible')) { return; } // fixes #278\n\t\t\t\t\t// Detect nested tables - fixes #724\n\t\t\t\t\tnestedStickyTop = $nestedSticky.length ? $nestedSticky.offset().top - $yScroll.scrollTop() + $nestedSticky.height() : 0;\n\t\t\t\t\tvar offset = $table.offset(),\n\t\t\t\t\t\tyWindow = $.isWindow( $yScroll[0] ), // $.isWindow needs jQuery 1.4.3\n\t\t\t\t\t\txWindow = $.isWindow( $xScroll[0] ),\n\t\t\t\t\t\tattachTop = $attach.length ?\n\t\t\t\t\t\t\t( yWindow ? $yScroll.scrollTop() : $yScroll.offset().top ) :\n\t\t\t\t\t\t\t$yScroll.scrollTop(),\n\t\t\t\t\t\tcaptionHeight = wo.stickyHeaders_includeCaption ? 0 : $table.children( 'caption' ).height() || 0,\n\t\t\t\t\t\tscrollTop = attachTop + stickyOffset + nestedStickyTop - captionHeight,\n\t\t\t\t\t\ttableHeight = $table.height() - ($stickyWrap.height() + ($tfoot.height() || 0)) - captionHeight,\n\t\t\t\t\t\tisVisible = ( scrollTop > offset.top ) && ( scrollTop < offset.top + tableHeight ) ? 'visible' : 'hidden',\n\t\t\t\t\t\tcssSettings = { visibility : isVisible };\n\t\t\t\t\tif ($attach.length) {\n\t\t\t\t\t\tcssSettings.top = yWindow ? scrollTop - $attach.offset().top : $attach.scrollTop();\n\t\t\t\t\t}\n\t\t\t\t\tif (xWindow) {\n\t\t\t\t\t\t// adjust when scrolling horizontally - fixes issue #143\n\t\t\t\t\t\tcssSettings.left = $table.offset().left - parseInt($table.css('margin-left'), 10) - $xScroll.scrollLeft() - spacing;\n\t\t\t\t\t}\n\t\t\t\t\tif ($nestedSticky.length) {\n\t\t\t\t\t\tcssSettings.top = ( cssSettings.top || 0 ) + stickyOffset + nestedStickyTop;\n\t\t\t\t\t}\n\t\t\t\t\t$stickyWrap\n\t\t\t\t\t\t.removeClass( ts.css.stickyVis + ' ' + ts.css.stickyHide )\n\t\t\t\t\t\t.addClass( isVisible === 'visible' ? ts.css.stickyVis : ts.css.stickyHide )\n\t\t\t\t\t\t.css(cssSettings);\n\t\t\t\t\tif (isVisible !== laststate || resizing) {\n\t\t\t\t\t\t// make sure the column widths match\n\t\t\t\t\t\tresizeHeader();\n\t\t\t\t\t\tlaststate = isVisible;\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t// only add a position relative if a position isn't already defined\n\t\t\tif ($attach.length && !$attach.css('position')) {\n\t\t\t\t$attach.css('position', 'relative');\n\t\t\t}\n\t\t\t// fix clone ID, if it exists - fixes #271\n\t\t\tif ($stickyTable.attr('id')) { $stickyTable[0].id += wo.stickyHeaders_cloneId; }\n\t\t\t// clear out cloned table, except for sticky header\n\t\t\t// include caption & filter row (fixes #126 & #249) - don't remove cells to get correct cell indexing\n\t\t\t$stickyTable.find('thead:gt(0), tr.sticky-false').hide();\n\t\t\t$stickyTable.find('tbody, tfoot').remove();\n\t\t\t$stickyTable.find('caption').toggle(wo.stickyHeaders_includeCaption);\n\t\t\t// issue #172 - find td/th in sticky header\n\t\t\t$stickyCells = $stickyThead.children().children();\n\t\t\t$stickyTable.css({ height:0, width:0, margin: 0 });\n\t\t\t// remove resizable block\n\t\t\t$stickyCells.find('.' + ts.css.resizer).remove();\n\t\t\t// update sticky header class names to match real header after sorting\n\t\t\t$table\n\t\t\t\t.addClass('hasStickyHeaders')\n\t\t\t\t.bind('pagerComplete' + namespace, function() {\n\t\t\t\t\tresizeHeader();\n\t\t\t\t});\n\n\t\t\tts.bindEvents(table, $stickyThead.children().children('.' + ts.css.header));\n\n\t\t\tif (wo.stickyHeaders_appendTo) {\n\t\t\t\t$(wo.stickyHeaders_appendTo).append( $stickyWrap );\n\t\t\t} else {\n\t\t\t\t// add stickyheaders AFTER the table. If the table is selected by ID, the original one (first) will be returned.\n\t\t\t\t$table.after( $stickyWrap );\n\t\t\t}\n\n\t\t\t// onRenderHeader is defined, we need to do something about it (fixes #641)\n\t\t\tif (c.onRenderHeader) {\n\t\t\t\t$t = $stickyThead.children('tr').children();\n\t\t\t\tlen = $t.length;\n\t\t\t\tfor ( index = 0; index < len; index++ ) {\n\t\t\t\t\t// send second parameter\n\t\t\t\t\tc.onRenderHeader.apply( $t.eq( index ), [ index, c, $stickyTable ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// make it sticky!\n\t\t\t$xScroll.add($yScroll)\n\t\t\t\t.unbind( ('scroll resize '.split(' ').join( namespace )).replace(/\\s+/g, ' ') )\n\t\t\t\t.bind('scroll resize '.split(' ').join( namespace ), function( event ) {\n\t\t\t\t\tscrollSticky( event.type === 'resize' );\n\t\t\t\t});\n\t\t\tc.$table\n\t\t\t\t.unbind('stickyHeadersUpdate' + namespace)\n\t\t\t\t.bind('stickyHeadersUpdate' + namespace, function(){\n\t\t\t\t\tscrollSticky( true );\n\t\t\t\t});\n\n\t\t\tif (wo.stickyHeaders_addResizeEvent) {\n\t\t\t\tts.addHeaderResizeEvent(table);\n\t\t\t}\n\n\t\t\t// look for filter widget\n\t\t\tif ($table.hasClass('hasFilters') && wo.filter_columnFilters) {\n\t\t\t\t// scroll table into view after filtering, if sticky header is active - #482\n\t\t\t\t$table.bind('filterEnd' + namespace, function() {\n\t\t\t\t\t// $(':focus') needs jQuery 1.6+\n\t\t\t\t\tvar $td = $(document.activeElement).closest('td'),\n\t\t\t\t\t\tcolumn = $td.parent().children().index($td);\n\t\t\t\t\t// only scroll if sticky header is active\n\t\t\t\t\tif ($stickyWrap.hasClass(ts.css.stickyVis) && wo.stickyHeaders_filteredToTop) {\n\t\t\t\t\t\t// scroll to original table (not sticky clone)\n\t\t\t\t\t\twindow.scrollTo(0, $table.position().top);\n\t\t\t\t\t\t// give same input/select focus; check if c.$filters exists; fixes #594\n\t\t\t\t\t\tif (column >= 0 && c.$filters) {\n\t\t\t\t\t\t\tc.$filters.eq(column).find('a, select, input').filter(':visible').focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tts.filter.bindSearch( $table, $stickyCells.find('.' + ts.css.filter) );\n\t\t\t\t// support hideFilters\n\t\t\t\tif (wo.filter_hideFilters) {\n\t\t\t\t\tts.filter.hideFilters(c, $stickyTable);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// resize table (Firefox)\n\t\t\tif (wo.stickyHeaders_addResizeEvent) {\n\t\t\t\t$table.bind('resize' + c.namespace + 'stickyheaders', function() {\n\t\t\t\t\tresizeHeader();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t$table.triggerHandler('stickyHeadersInit');\n\n\t\t},\n\t\tremove: function(table, c, wo) {\n\t\t\tvar namespace = c.namespace + 'stickyheaders ';\n\t\t\tc.$table\n\t\t\t\t.removeClass('hasStickyHeaders')\n\t\t\t\t.unbind( ('pagerComplete resize filterEnd stickyHeadersUpdate '.split(' ').join(namespace)).replace(/\\s+/g, ' ') )\n\t\t\t\t.next('.' + ts.css.stickyWrap).remove();\n\t\t\tif (wo.$sticky && wo.$sticky.length) { wo.$sticky.remove(); } // remove cloned table\n\t\t\t$(window)\n\t\t\t\t.add(wo.stickyHeaders_xScroll)\n\t\t\t\t.add(wo.stickyHeaders_yScroll)\n\t\t\t\t.add(wo.stickyHeaders_attachTo)\n\t\t\t\t.unbind( ('scroll resize '.split(' ').join(namespace)).replace(/\\s+/g, ' ') );\n\t\t\tts.addHeaderResizeEvent(table, true);\n\t\t}\n\t});\n\n})(jQuery, window);\n\n/*! Widget: resizable - updated 1/28/2017 (v2.28.5) */\n/*jshint browser:true, jquery:true, unused:false */\n;(function ($, window) {\n\t'use strict';\n\tvar ts = $.tablesorter || {};\n\n\t$.extend(ts.css, {\n\t\tresizableContainer : 'tablesorter-resizable-container',\n\t\tresizableHandle : 'tablesorter-resizable-handle',\n\t\tresizableNoSelect : 'tablesorter-disableSelection',\n\t\tresizableStorage : 'tablesorter-resizable'\n\t});\n\n\t// Add extra scroller css\n\t$(function(){\n\t\tvar s = '<style>' +\n\t\t\t'body.' + ts.css.resizableNoSelect + ' { -ms-user-select: none; -moz-user-select: -moz-none;' +\n\t\t\t\t'-khtml-user-select: none; -webkit-user-select: none; user-select: none; }' +\n\t\t\t'.' + ts.css.resizableContainer + ' { position: relative; height: 1px; }' +\n\t\t\t// make handle z-index > than stickyHeader z-index, so the handle stays above sticky header\n\t\t\t'.' + ts.css.resizableHandle + ' { position: absolute; display: inline-block; width: 8px;' +\n\t\t\t\t'top: 1px; cursor: ew-resize; z-index: 3; user-select: none; -moz-user-select: none; }' +\n\t\t\t'</style>';\n\t\t$('head').append(s);\n\t});\n\n\tts.resizable = {\n\t\tinit : function( c, wo ) {\n\t\t\tif ( c.$table.hasClass( 'hasResizable' ) ) { return; }\n\t\t\tc.$table.addClass( 'hasResizable' );\n\n\t\t\tvar noResize, $header, column, storedSizes, tmp,\n\t\t\t\t$table = c.$table,\n\t\t\t\t$parent = $table.parent(),\n\t\t\t\tmarginTop = parseInt( $table.css( 'margin-top' ), 10 ),\n\n\t\t\t// internal variables\n\t\t\tvars = wo.resizable_vars = {\n\t\t\t\tuseStorage : ts.storage && wo.resizable !== false,\n\t\t\t\t$wrap : $parent,\n\t\t\t\tmouseXPosition : 0,\n\t\t\t\t$target : null,\n\t\t\t\t$next : null,\n\t\t\t\toverflow : $parent.css('overflow') === 'auto' ||\n\t\t\t\t\t$parent.css('overflow') === 'scroll' ||\n\t\t\t\t\t$parent.css('overflow-x') === 'auto' ||\n\t\t\t\t\t$parent.css('overflow-x') === 'scroll',\n\t\t\t\tstoredSizes : []\n\t\t\t};\n\n\t\t\t// set default widths\n\t\t\tts.resizableReset( c.table, true );\n\n\t\t\t// now get measurements!\n\t\t\tvars.tableWidth = $table.width();\n\t\t\t// attempt to autodetect\n\t\t\tvars.fullWidth = Math.abs( $parent.width() - vars.tableWidth ) < 20;\n\n\t\t\t/*\n\t\t\t// Hacky method to determine if table width is set to 'auto'\n\t\t\t// http://stackoverflow.com/a/20892048/145346\n\t\t\tif ( !vars.fullWidth ) {\n\t\t\t\ttmp = $table.width();\n\t\t\t\t$header = $table.wrap('<span>').parent(); // temp variable\n\t\t\t\tstoredSizes = parseInt( $table.css( 'margin-left' ), 10 ) || 0;\n\t\t\t\t$table.css( 'margin-left', storedSizes + 50 );\n\t\t\t\tvars.tableWidth = $header.width() > tmp ? 'auto' : tmp;\n\t\t\t\t$table.css( 'margin-left', storedSizes ? storedSizes : '' );\n\t\t\t\t$header = null;\n\t\t\t\t$table.unwrap('<span>');\n\t\t\t}\n\t\t\t*/\n\n\t\t\tif ( vars.useStorage && vars.overflow ) {\n\t\t\t\t// save table width\n\t\t\t\tts.storage( c.table, 'tablesorter-table-original-css-width', vars.tableWidth );\n\t\t\t\ttmp = ts.storage( c.table, 'tablesorter-table-resized-width' ) || 'auto';\n\t\t\t\tts.resizable.setWidth( $table, tmp, true );\n\t\t\t}\n\t\t\two.resizable_vars.storedSizes = storedSizes = ( vars.useStorage ?\n\t\t\t\tts.storage( c.table, ts.css.resizableStorage ) :\n\t\t\t\t[] ) || [];\n\t\t\tts.resizable.setWidths( c, wo, storedSizes );\n\t\t\tts.resizable.updateStoredSizes( c, wo );\n\n\t\t\two.$resizable_container = $( '<div class=\"' + ts.css.resizableContainer + '\">' )\n\t\t\t\t.css({ top : marginTop })\n\t\t\t\t.insertBefore( $table );\n\t\t\t// add container\n\t\t\tfor ( column = 0; column < c.columns; column++ ) {\n\t\t\t\t$header = c.$headerIndexed[ column ];\n\t\t\t\ttmp = ts.getColumnData( c.table, c.headers, column );\n\t\t\t\tnoResize = ts.getData( $header, tmp, 'resizable' ) === 'false';\n\t\t\t\tif ( !noResize ) {\n\t\t\t\t\t$( '<div class=\"' + ts.css.resizableHandle + '\">' )\n\t\t\t\t\t\t.appendTo( wo.$resizable_container )\n\t\t\t\t\t\t.attr({\n\t\t\t\t\t\t\t'data-column' : column,\n\t\t\t\t\t\t\t'unselectable' : 'on'\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.data( 'header', $header )\n\t\t\t\t\t\t.bind( 'selectstart', false );\n\t\t\t\t}\n\t\t\t}\n\t\t\tts.resizable.bindings( c, wo );\n\t\t},\n\n\t\tupdateStoredSizes : function( c, wo ) {\n\t\t\tvar column, $header,\n\t\t\t\tlen = c.columns,\n\t\t\t\tvars = wo.resizable_vars;\n\t\t\tvars.storedSizes = [];\n\t\t\tfor ( column = 0; column < len; column++ ) {\n\t\t\t\t$header = c.$headerIndexed[ column ];\n\t\t\t\tvars.storedSizes[ column ] = $header.is(':visible') ? $header.width() : 0;\n\t\t\t}\n\t\t},\n\n\t\tsetWidth : function( $el, width, overflow ) {\n\t\t\t// overflow tables need min & max width set as well\n\t\t\t$el.css({\n\t\t\t\t'width' : width,\n\t\t\t\t'min-width' : overflow ? width : '',\n\t\t\t\t'max-width' : overflow ? width : ''\n\t\t\t});\n\t\t},\n\n\t\tsetWidths : function( c, wo, storedSizes ) {\n\t\t\tvar column, $temp,\n\t\t\t\tvars = wo.resizable_vars,\n\t\t\t\t$extra = $( c.namespace + '_extra_headers' ),\n\t\t\t\t$col = c.$table.children( 'colgroup' ).children( 'col' );\n\t\t\tstoredSizes = storedSizes || vars.storedSizes || [];\n\t\t\t// process only if table ID or url match\n\t\t\tif ( storedSizes.length ) {\n\t\t\t\tfor ( column = 0; column < c.columns; column++ ) {\n\t\t\t\t\t// set saved resizable widths\n\t\t\t\t\tts.resizable.setWidth( c.$headerIndexed[ column ], storedSizes[ column ], vars.overflow );\n\t\t\t\t\tif ( $extra.length ) {\n\t\t\t\t\t\t// stickyHeaders needs to modify min & max width as well\n\t\t\t\t\t\t$temp = $extra.eq( column ).add( $col.eq( column ) );\n\t\t\t\t\t\tts.resizable.setWidth( $temp, storedSizes[ column ], vars.overflow );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$temp = $( c.namespace + '_extra_table' );\n\t\t\t\tif ( $temp.length && !ts.hasWidget( c.table, 'scroller' ) ) {\n\t\t\t\t\tts.resizable.setWidth( $temp, c.$table.outerWidth(), vars.overflow );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tsetHandlePosition : function( c, wo ) {\n\t\t\tvar startPosition,\n\t\t\t\ttableHeight = c.$table.height(),\n\t\t\t\t$handles = wo.$resizable_container.children(),\n\t\t\t\thandleCenter = Math.floor( $handles.width() / 2 );\n\n\t\t\tif ( ts.hasWidget( c.table, 'scroller' ) ) {\n\t\t\t\ttableHeight = 0;\n\t\t\t\tc.$table.closest( '.' + ts.css.scrollerWrap ).children().each(function(){\n\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\t// center table has a max-height set\n\t\t\t\t\ttableHeight += $this.filter('[style*=\"height\"]').length ? $this.height() : $this.children('table').height();\n\t\t\t\t});\n\t\t\t}\n\t\t\t// subtract out table left position from resizable handles. Fixes #864\n\t\t\tstartPosition = c.$table.position().left;\n\t\t\t$handles.each( function() {\n\t\t\t\tvar $this = $(this),\n\t\t\t\t\tcolumn = parseInt( $this.attr( 'data-column' ), 10 ),\n\t\t\t\t\tcolumns = c.columns - 1,\n\t\t\t\t\t$header = $this.data( 'header' );\n\t\t\t\tif ( !$header ) { return; } // see #859\n\t\t\t\tif ( !$header.is(':visible') ) {\n\t\t\t\t\t$this.hide();\n\t\t\t\t} else if ( column < columns || column === columns && wo.resizable_addLastColumn ) {\n\t\t\t\t\t$this.css({\n\t\t\t\t\t\tdisplay: 'inline-block',\n\t\t\t\t\t\theight : tableHeight,\n\t\t\t\t\t\tleft : $header.position().left - startPosition + $header.outerWidth() - handleCenter\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\t// prevent text selection while dragging resize bar\n\t\ttoggleTextSelection : function( c, wo, toggle ) {\n\t\t\tvar namespace = c.namespace + 'tsresize';\n\t\t\two.resizable_vars.disabled = toggle;\n\t\t\t$( 'body' ).toggleClass( ts.css.resizableNoSelect, toggle );\n\t\t\tif ( toggle ) {\n\t\t\t\t$( 'body' )\n\t\t\t\t\t.attr( 'unselectable', 'on' )\n\t\t\t\t\t.bind( 'selectstart' + namespace, false );\n\t\t\t} else {\n\t\t\t\t$( 'body' )\n\t\t\t\t\t.removeAttr( 'unselectable' )\n\t\t\t\t\t.unbind( 'selectstart' + namespace );\n\t\t\t}\n\t\t},\n\n\t\tbindings : function( c, wo ) {\n\t\t\tvar namespace = c.namespace + 'tsresize';\n\t\t\two.$resizable_container.children().bind( 'mousedown', function( event ) {\n\t\t\t\t// save header cell and mouse position\n\t\t\t\tvar column,\n\t\t\t\t\tvars = wo.resizable_vars,\n\t\t\t\t\t$extras = $( c.namespace + '_extra_headers' ),\n\t\t\t\t\t$header = $( event.target ).data( 'header' );\n\n\t\t\t\tcolumn = parseInt( $header.attr( 'data-column' ), 10 );\n\t\t\t\tvars.$target = $header = $header.add( $extras.filter('[data-column=\"' + column + '\"]') );\n\t\t\t\tvars.target = column;\n\n\t\t\t\t// if table is not as wide as it's parent, then resize the table\n\t\t\t\tvars.$next = event.shiftKey || wo.resizable_targetLast ?\n\t\t\t\t\t$header.parent().children().not( '.resizable-false' ).filter( ':last' ) :\n\t\t\t\t\t$header.nextAll( ':not(.resizable-false)' ).eq( 0 );\n\n\t\t\t\tcolumn = parseInt( vars.$next.attr( 'data-column' ), 10 );\n\t\t\t\tvars.$next = vars.$next.add( $extras.filter('[data-column=\"' + column + '\"]') );\n\t\t\t\tvars.next = column;\n\n\t\t\t\tvars.mouseXPosition = event.pageX;\n\t\t\t\tts.resizable.updateStoredSizes( c, wo );\n\t\t\t\tts.resizable.toggleTextSelection(c, wo, true );\n\t\t\t});\n\n\t\t\t$( document )\n\t\t\t\t.bind( 'mousemove' + namespace, function( event ) {\n\t\t\t\t\tvar vars = wo.resizable_vars;\n\t\t\t\t\t// ignore mousemove if no mousedown\n\t\t\t\t\tif ( !vars.disabled || vars.mouseXPosition === 0 || !vars.$target ) { return; }\n\t\t\t\t\tif ( wo.resizable_throttle ) {\n\t\t\t\t\t\tclearTimeout( vars.timer );\n\t\t\t\t\t\tvars.timer = setTimeout( function() {\n\t\t\t\t\t\t\tts.resizable.mouseMove( c, wo, event );\n\t\t\t\t\t\t}, isNaN( wo.resizable_throttle ) ? 5 : wo.resizable_throttle );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tts.resizable.mouseMove( c, wo, event );\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.bind( 'mouseup' + namespace, function() {\n\t\t\t\t\tif (!wo.resizable_vars.disabled) { return; }\n\t\t\t\t\tts.resizable.toggleTextSelection( c, wo, false );\n\t\t\t\t\tts.resizable.stopResize( c, wo );\n\t\t\t\t\tts.resizable.setHandlePosition( c, wo );\n\t\t\t\t});\n\n\t\t\t// resizeEnd event triggered by scroller widget\n\t\t\t$( window ).bind( 'resize' + namespace + ' resizeEnd' + namespace, function() {\n\t\t\t\tts.resizable.setHandlePosition( c, wo );\n\t\t\t});\n\n\t\t\t// right click to reset columns to default widths\n\t\t\tc.$table\n\t\t\t\t.bind( 'columnUpdate pagerComplete resizableUpdate '.split( ' ' ).join( namespace + ' ' ), function() {\n\t\t\t\t\tts.resizable.setHandlePosition( c, wo );\n\t\t\t\t})\n\t\t\t\t.bind( 'resizableReset' + namespace, function() {\n\t\t\t\t\tts.resizableReset( c.table );\n\t\t\t\t})\n\t\t\t\t.find( 'thead:first' )\n\t\t\t\t.add( $( c.namespace + '_extra_table' ).find( 'thead:first' ) )\n\t\t\t\t.bind( 'contextmenu' + namespace, function() {\n\t\t\t\t\t// $.isEmptyObject() needs jQuery 1.4+; allow right click if already reset\n\t\t\t\t\tvar allowClick = wo.resizable_vars.storedSizes.length === 0;\n\t\t\t\t\tts.resizableReset( c.table );\n\t\t\t\t\tts.resizable.setHandlePosition( c, wo );\n\t\t\t\t\two.resizable_vars.storedSizes = [];\n\t\t\t\t\treturn allowClick;\n\t\t\t\t});\n\n\t\t},\n\n\t\tmouseMove : function( c, wo, event ) {\n\t\t\tif ( wo.resizable_vars.mouseXPosition === 0 || !wo.resizable_vars.$target ) { return; }\n\t\t\t// resize columns\n\t\t\tvar column,\n\t\t\t\ttotal = 0,\n\t\t\t\tvars = wo.resizable_vars,\n\t\t\t\t$next = vars.$next,\n\t\t\t\ttar = vars.storedSizes[ vars.target ],\n\t\t\t\tleftEdge = event.pageX - vars.mouseXPosition;\n\t\t\tif ( vars.overflow ) {\n\t\t\t\tif ( tar + leftEdge > 0 ) {\n\t\t\t\t\tvars.storedSizes[ vars.target ] += leftEdge;\n\t\t\t\t\tts.resizable.setWidth( vars.$target, vars.storedSizes[ vars.target ], true );\n\t\t\t\t\t// update the entire table width\n\t\t\t\t\tfor ( column = 0; column < c.columns; column++ ) {\n\t\t\t\t\t\ttotal += vars.storedSizes[ column ];\n\t\t\t\t\t}\n\t\t\t\t\tts.resizable.setWidth( c.$table.add( $( c.namespace + '_extra_table' ) ), total );\n\t\t\t\t}\n\t\t\t\tif ( !$next.length ) {\n\t\t\t\t\t// if expanding right-most column, scroll the wrapper\n\t\t\t\t\tvars.$wrap[0].scrollLeft = c.$table.width();\n\t\t\t\t}\n\t\t\t} else if ( vars.fullWidth ) {\n\t\t\t\tvars.storedSizes[ vars.target ] += leftEdge;\n\t\t\t\tvars.storedSizes[ vars.next ] -= leftEdge;\n\t\t\t\tts.resizable.setWidths( c, wo );\n\t\t\t} else {\n\t\t\t\tvars.storedSizes[ vars.target ] += leftEdge;\n\t\t\t\tts.resizable.setWidths( c, wo );\n\t\t\t}\n\t\t\tvars.mouseXPosition = event.pageX;\n\t\t\t// dynamically update sticky header widths\n\t\t\tc.$table.triggerHandler('stickyHeadersUpdate');\n\t\t},\n\n\t\tstopResize : function( c, wo ) {\n\t\t\tvar vars = wo.resizable_vars;\n\t\t\tts.resizable.updateStoredSizes( c, wo );\n\t\t\tif ( vars.useStorage ) {\n\t\t\t\t// save all column widths\n\t\t\t\tts.storage( c.table, ts.css.resizableStorage, vars.storedSizes );\n\t\t\t\tts.storage( c.table, 'tablesorter-table-resized-width', c.$table.width() );\n\t\t\t}\n\t\t\tvars.mouseXPosition = 0;\n\t\t\tvars.$target = vars.$next = null;\n\t\t\t// will update stickyHeaders, just in case, see #912\n\t\t\tc.$table.triggerHandler('stickyHeadersUpdate');\n\t\t}\n\t};\n\n\t// this widget saves the column widths if\n\t// $.tablesorter.storage function is included\n\t// **************************\n\tts.addWidget({\n\t\tid: 'resizable',\n\t\tpriority: 40,\n\t\toptions: {\n\t\t\tresizable : true, // save column widths to storage\n\t\t\tresizable_addLastColumn : false,\n\t\t\tresizable_widths : [],\n\t\t\tresizable_throttle : false, // set to true (5ms) or any number 0-10 range\n\t\t\tresizable_targetLast : false,\n\t\t\tresizable_fullWidth : null\n\t\t},\n\t\tinit: function(table, thisWidget, c, wo) {\n\t\t\tts.resizable.init( c, wo );\n\t\t},\n\t\tformat: function( table, c, wo ) {\n\t\t\tts.resizable.setHandlePosition( c, wo );\n\t\t},\n\t\tremove: function( table, c, wo, refreshing ) {\n\t\t\tif (wo.$resizable_container) {\n\t\t\t\tvar namespace = c.namespace + 'tsresize';\n\t\t\t\tc.$table.add( $( c.namespace + '_extra_table' ) )\n\t\t\t\t\t.removeClass('hasResizable')\n\t\t\t\t\t.children( 'thead' )\n\t\t\t\t\t.unbind( 'contextmenu' + namespace );\n\n\t\t\t\two.$resizable_container.remove();\n\t\t\t\tts.resizable.toggleTextSelection( c, wo, false );\n\t\t\t\tts.resizableReset( table, refreshing );\n\t\t\t\t$( document ).unbind( 'mousemove' + namespace + ' mouseup' + namespace );\n\t\t\t}\n\t\t}\n\t});\n\n\tts.resizableReset = function( table, refreshing ) {\n\t\t$( table ).each(function(){\n\t\t\tvar index, $t,\n\t\t\t\tc = this.config,\n\t\t\t\two = c && c.widgetOptions,\n\t\t\t\tvars = wo.resizable_vars;\n\t\t\tif ( table && c && c.$headerIndexed.length ) {\n\t\t\t\t// restore the initial table width\n\t\t\t\tif ( vars.overflow && vars.tableWidth ) {\n\t\t\t\t\tts.resizable.setWidth( c.$table, vars.tableWidth, true );\n\t\t\t\t\tif ( vars.useStorage ) {\n\t\t\t\t\t\tts.storage( table, 'tablesorter-table-resized-width', 'auto' );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor ( index = 0; index < c.columns; index++ ) {\n\t\t\t\t\t$t = c.$headerIndexed[ index ];\n\t\t\t\t\tif ( wo.resizable_widths && wo.resizable_widths[ index ] ) {\n\t\t\t\t\t\tts.resizable.setWidth( $t, wo.resizable_widths[ index ], vars.overflow );\n\t\t\t\t\t} else if ( !$t.hasClass( 'resizable-false' ) ) {\n\t\t\t\t\t\t// don't clear the width of any column that is not resizable\n\t\t\t\t\t\tts.resizable.setWidth( $t, '', vars.overflow );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// reset stickyHeader widths\n\t\t\t\tc.$table.triggerHandler( 'stickyHeadersUpdate' );\n\t\t\t\tif ( ts.storage && !refreshing ) {\n\t\t\t\t\tts.storage( this, ts.css.resizableStorage, {} );\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n})( jQuery, window );\n\n/*! Widget: saveSort - updated 10/31/2015 (v2.24.0) *//*\n* Requires tablesorter v2.16+\n* by Rob Garrison\n*/\n;(function ($) {\n\t'use strict';\n\tvar ts = $.tablesorter || {};\n\n\t// this widget saves the last sort only if the\n\t// saveSort widget option is true AND the\n\t// $.tablesorter.storage function is included\n\t// **************************\n\tts.addWidget({\n\t\tid: 'saveSort',\n\t\tpriority: 20,\n\t\toptions: {\n\t\t\tsaveSort : true\n\t\t},\n\t\tinit: function(table, thisWidget, c, wo) {\n\t\t\t// run widget format before all other widgets are applied to the table\n\t\t\tthisWidget.format(table, c, wo, true);\n\t\t},\n\t\tformat: function(table, c, wo, init) {\n\t\t\tvar stored, time,\n\t\t\t\t$table = c.$table,\n\t\t\t\tsaveSort = wo.saveSort !== false, // make saveSort active/inactive; default to true\n\t\t\t\tsortList = { 'sortList' : c.sortList };\n\t\t\tif (c.debug) {\n\t\t\t\ttime = new Date();\n\t\t\t}\n\t\t\tif ($table.hasClass('hasSaveSort')) {\n\t\t\t\tif (saveSort && table.hasInitialized && ts.storage) {\n\t\t\t\t\tts.storage( table, 'tablesorter-savesort', sortList );\n\t\t\t\t\tif (c.debug) {\n\t\t\t\t\t\tconsole.log('saveSort widget: Saving last sort: ' + c.sortList + ts.benchmark(time));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// set table sort on initial run of the widget\n\t\t\t\t$table.addClass('hasSaveSort');\n\t\t\t\tsortList = '';\n\t\t\t\t// get data\n\t\t\t\tif (ts.storage) {\n\t\t\t\t\tstored = ts.storage( table, 'tablesorter-savesort' );\n\t\t\t\t\tsortList = (stored && stored.hasOwnProperty('sortList') && $.isArray(stored.sortList)) ? stored.sortList : '';\n\t\t\t\t\tif (c.debug) {\n\t\t\t\t\t\tconsole.log('saveSort: Last sort loaded: \"' + sortList + '\"' + ts.benchmark(time));\n\t\t\t\t\t}\n\t\t\t\t\t$table.bind('saveSortReset', function(event) {\n\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\tts.storage( table, 'tablesorter-savesort', '' );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// init is true when widget init is run, this will run this widget before all other widgets have initialized\n\t\t\t\t// this method allows using this widget in the original tablesorter plugin; but then it will run all widgets twice.\n\t\t\t\tif (init && sortList && sortList.length > 0) {\n\t\t\t\t\tc.sortList = sortList;\n\t\t\t\t} else if (table.hasInitialized && sortList && sortList.length > 0) {\n\t\t\t\t\t// update sort change\n\t\t\t\t\tts.sortOn( c, sortList );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tremove: function(table, c) {\n\t\t\tc.$table.removeClass('hasSaveSort');\n\t\t\t// clear storage\n\t\t\tif (ts.storage) { ts.storage( table, 'tablesorter-savesort', '' ); }\n\t\t}\n\t});\n\n})(jQuery);\n\nreturn jQuery.tablesorter;\n}));\n","/*! Widget: grouping - updated 11/26/2016 (v2.28.0) */\n!function(a){\"use strict\";var b=a.tablesorter,c=b.grouping={types:{number:function(a,c,d,e){var f,g=c.hasClass(b.css.sortAsc);return e>1&&\"\"!==d?(f=g?Math.floor(parseFloat(d)/e)*e:Math.ceil(parseFloat(d)/e)*e,f+=\" - \"+(f+(e-1)*(g?1:-1))):f=parseFloat(d)||d,f},separator:function(b,c,d,e){var f=(d+\"\").split(b.widgetOptions.group_separator);return a.trim(f[e-1]||\"\")},text:function(a,b,c){return c},word:function(a,b,c,d){var e=(c+\" \").match(/\\w+/g)||[];return e[d-1]||\"\"},letter:function(a,b,c,d){return c?(c+\" \").substring(0,d):\"\"},date:function(a,b,d,e,f){var g,h,i=a.widgetOptions,j=new Date(d||\"\");return j instanceof Date&&isFinite(j)?(g=j.getFullYear(),h=c.findMonth(i,j.getMonth()),\"year\"===e?g:\"month\"===e?h:\"monthyear\"===e?h+\" \"+g:\"day\"===e?h+\" \"+j.getDate():\"week\"===e?c.findWeek(i,j.getDay()):\"time\"===e?c.findTime(i,j):\"hour\"===e?c.findTime(i,j,\"hour\"):i.group_dateString(j,a,b)):i.group_dateInvalid}},findMonth:function(a,b){return a.group_months[b+(\"\"===(a.group_months[0]||\"\")?1:0)]},findWeek:function(b,c){if(a.isArray(b.group_week))return b.group_week[c];if(!a.isEmptyObject(b.group_week)){var d=[\"sun\",\"mon\",\"tue\",\"wed\",\"thu\",\"fri\",\"sat\"];return b.group_week[d[c]]}},findTime:function(a,b,c){var d,e=a.group_time.am&&a.group_time.pm,f=b.getHours(),g=f>=12?1:0,h=a.group_time24Hour&&f>12?f-12:a.group_time24Hour&&0===f?f+12:f,i=(\"00\"+h).slice(-2),j=(\"00\"+b.getMinutes()).slice(-2);return d=a.group_time[e?[\"am\",\"pm\"][g]:g],\"hour\"===c?i:i+\":\"+j+(a.group_time24Hour?\"\":\" \"+(d||\"\"))},update:function(b){if(!a.isEmptyObject(b.config.cache)){var d=b.config,e=d.widgetOptions,f=\"undefined\"!=typeof d.sortList[0],g={},h=a.isArray(e.group_forceColumn)&&\"undefined\"!=typeof e.group_forceColumn[0]?e.group_enforceSort&&!f?-1:e.group_forceColumn[0]:f?d.sortList[0][0]:-1;d.$table.find(\"tr.group-hidden\").removeClass(\"group-hidden\").end().find(\"tr.group-header\").remove(),e.group_collapsible&&d.$table.data(\"pagerSavedHeight\",0),h>=0&&h<d.columns&&!d.$headerIndexed[h].hasClass(\"group-false\")&&(e.group_collapsedGroup=\"\",e.group_collapsedGroups={},g.column=h,g.groupClass=(d.$headerIndexed[h].attr(\"class\")||\"\").match(/(group-\\w+(-\\w+)?)/g),g.grouping=g.groupClass?g.groupClass[0].split(\"-\"):[\"group\",\"letter\",1],g.savedGroup=c.saveCurrentGrouping(d,e,g),c.findColumnGroups(d,e,g),c.processHeaders(d,e,g),d.$table.triggerHandler(e.group_complete))}},processHeaders:function(b,c,d){var e,f,g,h,i,j,k=b.$table.find(\"tr.group-header\"),l=k.length;for(k.bind(\"selectstart\",!1),e=0;e<l;e++)j=k.eq(e),i=j.nextUntil(\"tr.group-header\").filter(\":visible\"),(c.group_count||a.isFunction(c.group_callback))&&(g=j.find(\".group-count\"),g.length&&(c.group_count&&g.html(c.group_count.toString().replace(/\\{num\\}/g,i.length)),a.isFunction(c.group_callback)&&c.group_callback(j.find(\"td\"),i,d.column,b.table))),c.group_saveGroups&&!a.isEmptyObject(c.group_collapsedGroups)&&c.group_collapsedGroups[c.group_collapsedGroup].length?(h=j.find(\".group-name\").text().toLowerCase()+j.attr(\"data-group-index\"),f=a.inArray(h,c.group_collapsedGroups[c.group_collapsedGroup])>-1,j.toggleClass(\"collapsed\",f),i.toggleClass(\"group-hidden\",f)):c.group_collapsed&&c.group_collapsible&&(j.addClass(\"collapsed\"),i.addClass(\"group-hidden\"))},groupHeaderHTML:function(a,b,c){var d=(c.currentGroup||\"\").toString().replace(/</g,\"<\").replace(/>/g,\">\");return'<tr class=\"group-header '+a.selectorRemove.slice(1)+'\" unselectable=\"on\" '+(a.tabIndex?'tabindex=\"0\" ':\"\")+'data-group-index=\"'+c.groupIndex+'\"><td colspan=\"'+a.columns+'\">'+(b.group_collapsible?\"<i/>\":\"\")+'<span class=\"group-name\">'+d+'</span><span class=\"group-count\"></span></td></tr>'},saveCurrentGrouping:function(a,c,d){var e,f,g=!1;return c.group_collapsible&&c.group_saveGroups&&(c.group_collapsedGroups=b.storage&&b.storage(a.table,\"tablesorter-groups\")||{},f=\"dir\"+a.sortList[0][1],e=c.group_collapsedGroup=\"\"+a.sortList[0][0]+f+d.grouping.join(\"\"),c.group_collapsedGroups[e]?g=!0:c.group_collapsedGroups[e]=[]),g},findColumnGroups:function(a,d,e){var f,g,h,i,j,k=b.hasWidget(a.table,\"pager\"),l=a.pager||{};for(e.groupIndex=0,f=0;f<a.$tbodies.length;f++)for(g=a.cache[f].normalized,e.group=j,h=k&&!l.ajax?l.startRow-1:0,i=k?l.endRow-(l.ajax?l.startRow:0):g.length;h<i;h++)e.rowData=g[h],e.rowData&&(e.$row=e.rowData[a.columns].$row,e.$row.is(\":visible\")&&c.types[e.grouping[1]]&&c.insertGroupHeader(a,d,e))},insertGroupHeader:function(b,d,e){var f=b.$headerIndexed[e.column],g=e.rowData[e.column],h=/date/.test(e.groupClass)?e.grouping[2]:parseInt(e.grouping[2]||1,10)||1;e.currentGroup=e.rowData?c.types[e.grouping[1]](b,f,g,h,e.group):e.currentGroup,e.group!==e.currentGroup&&(e.group=e.currentGroup,a.isFunction(d.group_formatter)&&(e.currentGroup=d.group_formatter((e.group||\"\").toString(),e.column,b.table,b,d,e)||e.group),e.$row.first().before(c.groupHeaderHTML(b,d,e)),d.group_saveGroups&&!e.savedGroup&&d.group_collapsed&&d.group_collapsible&&d.group_collapsedGroups[d.group_collapsedGroup].push(e.currentGroup+e.groupIndex),e.groupIndex++)},bindEvents:function(d,e,f){f.group_collapsible&&(f.group_collapsedGroups=[],e.$table.on(\"click toggleGroup keyup\",\"tr.group-header\",function(c){if(c.stopPropagation(),\"keyup\"!==c.type||13===c.which){var g,h,i,j=a(this),k=j.find(\".group-name\").text().toLowerCase()+j.attr(\"data-group-index\");!c.shiftKey||\"click\"!==c.type&&\"keyup\"!==c.type||j.siblings(\".group-header\").trigger(\"toggleGroup\"),j.toggleClass(\"collapsed\"),j.nextUntil(\"tr.group-header\").toggleClass(\"group-hidden\",j.hasClass(\"collapsed\")),g=j.hasClass(\"collapsed\"),!g&&b.hasWidget(e.$table,\"zebra\")&&b.applyWidgetId(e.$table,\"zebra\"),f.group_saveGroups&&b.storage&&(h=e.$table.find(\".group-header\"),f.group_collapsedGroups[f.group_collapsedGroup]||(f.group_collapsedGroups[f.group_collapsedGroup]=[]),g&&f.group_collapsedGroup?f.group_collapsedGroups[f.group_collapsedGroup].push(k):f.group_collapsedGroup&&(i=a.inArray(k,f.group_collapsedGroups[f.group_collapsedGroup]),i>-1&&f.group_collapsedGroups[f.group_collapsedGroup].splice(i,1)),b.storage(d,\"tablesorter-groups\",f.group_collapsedGroups))}})),a(f.group_saveReset).on(\"click\",function(){c.clearSavedGroups(d)}),e.$table.on(\"pagerChange.tsgrouping\",function(){c.update(d)})},clearSavedGroups:function(a){a&&b.storage&&(b.storage(a,\"tablesorter-groups\",\"\"),c.update(a))}};b.addWidget({id:\"group\",priority:100,options:{group_collapsible:!0,group_collapsed:!1,group_saveGroups:!0,group_saveReset:null,group_count:\" ({num})\",group_separator:\"-\",group_formatter:null,group_callback:null,group_complete:\"groupingComplete\",group_forceColumn:[],group_enforceSort:!0,group_checkbox:[\"checked\",\"unchecked\"],group_months:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],group_week:[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"],group_time:[\"AM\",\"PM\"],group_time24Hour:!1,group_dateInvalid:\"Invalid Date\",group_dateString:function(a){return a.toLocaleString()}},init:function(a,b,d,e){c.bindEvents(a,d,e)},format:function(a,b,d){c.update(a)},remove:function(a,b,c){b.$table.off(\"click\",\"tr.group-header\").off(\"pagerChange.tsgrouping\").find(\".group-hidden\").removeClass(\"group-hidden\").end().find(\"tr.group-header\").remove()}})}(jQuery);","/*! Widget: uitheme - updated 12/8/2016 (v2.28.1) */\n!function(a){\"use strict\";var b=a.tablesorter||{};b.themes={bootstrap:{table:\"table table-bordered table-striped\",caption:\"caption\",header:\"bootstrap-header\",sortNone:\"\",sortAsc:\"\",sortDesc:\"\",active:\"\",hover:\"\",icons:\"\",iconSortNone:\"bootstrap-icon-unsorted\",iconSortAsc:\"icon-chevron-up glyphicon glyphicon-chevron-up\",iconSortDesc:\"icon-chevron-down glyphicon glyphicon-chevron-down\",filterRow:\"\",footerRow:\"\",footerCells:\"\",even:\"\",odd:\"\"},jui:{table:\"ui-widget ui-widget-content ui-corner-all\",caption:\"ui-widget-content\",header:\"ui-widget-header ui-corner-all ui-state-default\",sortNone:\"\",sortAsc:\"\",sortDesc:\"\",active:\"ui-state-active\",hover:\"ui-state-hover\",icons:\"ui-icon\",iconSortNone:\"ui-icon-carat-2-n-s ui-icon-caret-2-n-s\",iconSortAsc:\"ui-icon-carat-1-n ui-icon-caret-1-n\",iconSortDesc:\"ui-icon-carat-1-s ui-icon-caret-1-s\",filterRow:\"\",footerRow:\"\",footerCells:\"\",even:\"ui-widget-content\",odd:\"ui-state-default\"}},a.extend(b.css,{wrapper:\"tablesorter-wrapper\"}),b.addWidget({id:\"uitheme\",priority:10,format:function(c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q,r,s=b.themes,t=d.$table.add(a(d.namespace+\"_extra_table\")),u=d.$headers.add(a(d.namespace+\"_extra_headers\")),v=d.theme||\"jui\",w=s[v]||{},x=a.trim([w.sortNone,w.sortDesc,w.sortAsc,w.active].join(\" \")),y=a.trim([w.iconSortNone,w.iconSortDesc,w.iconSortAsc].join(\" \"));for(d.debug&&(j=new Date),t.hasClass(\"tablesorter-\"+v)&&d.theme===d.appliedTheme&&e.uitheme_applied||(e.uitheme_applied=!0,o=s[d.appliedTheme]||{},r=!a.isEmptyObject(o),p=r?[o.sortNone,o.sortDesc,o.sortAsc,o.active].join(\" \"):\"\",q=r?[o.iconSortNone,o.iconSortDesc,o.iconSortAsc].join(\" \"):\"\",r&&(e.zebra[0]=a.trim(\" \"+e.zebra[0].replace(\" \"+o.even,\"\")),e.zebra[1]=a.trim(\" \"+e.zebra[1].replace(\" \"+o.odd,\"\")),d.$tbodies.children().removeClass([o.even,o.odd].join(\" \"))),w.even&&(e.zebra[0]+=\" \"+w.even),w.odd&&(e.zebra[1]+=\" \"+w.odd),t.children(\"caption\").removeClass(o.caption||\"\").addClass(w.caption),m=t.removeClass((d.appliedTheme?\"tablesorter-\"+(d.appliedTheme||\"\"):\"\")+\" \"+(o.table||\"\")).addClass(\"tablesorter-\"+v+\" \"+(w.table||\"\")).children(\"tfoot\"),d.appliedTheme=d.theme,m.length&&m.children(\"tr\").removeClass(o.footerRow||\"\").addClass(w.footerRow).children(\"th, td\").removeClass(o.footerCells||\"\").addClass(w.footerCells),u.removeClass((r?[o.header,o.hover,p].join(\" \"):\"\")||\"\").addClass(w.header).not(\".sorter-false\").unbind(\"mouseenter.tsuitheme mouseleave.tsuitheme\").bind(\"mouseenter.tsuitheme mouseleave.tsuitheme\",function(b){a(this)[\"mouseenter\"===b.type?\"addClass\":\"removeClass\"](w.hover||\"\")}),u.each(function(){var c=a(this);c.find(\".\"+b.css.wrapper).length||c.wrapInner('<div class=\"'+b.css.wrapper+'\" style=\"position:relative;height:100%;width:100%\"></div>')}),d.cssIcon&&u.find(\".\"+b.css.icon).removeClass(r?[o.icons,q].join(\" \"):\"\").addClass(w.icons||\"\"),b.hasWidget(d.table,\"filter\")&&(g=function(){t.children(\"thead\").children(\".\"+b.css.filterRow).removeClass(r?o.filterRow||\"\":\"\").addClass(w.filterRow||\"\")},e.filter_initialized?g():t.one(\"filterInit\",function(){g()}))),f=0;f<d.columns;f++)k=d.$headers.add(a(d.namespace+\"_extra_headers\")).not(\".sorter-false\").filter('[data-column=\"'+f+'\"]'),l=b.css.icon?k.find(\".\"+b.css.icon):a(),n=u.not(\".sorter-false\").filter('[data-column=\"'+f+'\"]:last'),n.length&&(k.removeClass(x),l.removeClass(y),n[0].sortDisabled?l.removeClass(w.icons||\"\"):(h=w.sortNone,i=w.iconSortNone,n.hasClass(b.css.sortAsc)?(h=[w.sortAsc,w.active].join(\" \"),i=w.iconSortAsc):n.hasClass(b.css.sortDesc)&&(h=[w.sortDesc,w.active].join(\" \"),i=w.iconSortDesc),k.addClass(h),l.addClass(i||\"\")));d.debug&&console.log(\"Applying \"+v+\" theme\"+b.benchmark(j))},remove:function(a,c,d,e){if(d.uitheme_applied){var f=c.$table,g=c.appliedTheme||\"jui\",h=b.themes[g]||b.themes.jui,i=f.children(\"thead\").children(),j=h.sortNone+\" \"+h.sortDesc+\" \"+h.sortAsc,k=h.iconSortNone+\" \"+h.iconSortDesc+\" \"+h.iconSortAsc;f.removeClass(\"tablesorter-\"+g+\" \"+h.table),d.uitheme_applied=!1,e||(f.find(b.css.header).removeClass(h.header),i.unbind(\"mouseenter.tsuitheme mouseleave.tsuitheme\").removeClass(h.hover+\" \"+j+\" \"+h.active).filter(\".\"+b.css.filterRow).removeClass(h.filterRow),i.find(\".\"+b.css.icon).removeClass(h.icons+\" \"+k))}}})}(jQuery);","/*! Widget: filter - updated 12/8/2016 (v2.28.1) */\n!function(a){\"use strict\";var b,c,d=a.tablesorter||{},e=d.css,f=d.keyCodes;a.extend(e,{filterRow:\"tablesorter-filter-row\",filter:\"tablesorter-filter\",filterDisabled:\"disabled\",filterRowHide:\"hideme\"}),a.extend(f,{backSpace:8,escape:27,space:32,left:37,down:40}),d.addWidget({id:\"filter\",priority:50,options:{filter_cellFilter:\"\",filter_childRows:!1,filter_childByColumn:!1,filter_childWithSibs:!0,filter_columnAnyMatch:!0,filter_columnFilters:!0,filter_cssFilter:\"\",filter_defaultAttrib:\"data-value\",filter_defaultFilter:{},filter_excludeFilter:{},filter_external:\"\",filter_filteredRow:\"filtered\",filter_formatter:null,filter_functions:null,filter_hideEmpty:!0,filter_hideFilters:!1,filter_ignoreCase:!0,filter_liveSearch:!0,filter_matchType:{input:\"exact\",select:\"exact\"},filter_onlyAvail:\"filter-onlyAvail\",filter_placeholder:{search:\"\",select:\"\"},filter_reset:null,filter_resetOnEsc:!0,filter_saveFilters:!1,filter_searchDelay:300,filter_searchFiltered:!0,filter_selectSource:null,filter_selectSourceSeparator:\"|\",filter_serversideFiltering:!1,filter_startsWith:!1,filter_useParsedData:!1},format:function(a,c,d){c.$table.hasClass(\"hasFilters\")||b.init(a,c,d)},remove:function(b,c,f,g){var h,i,j=c.$table,k=c.$tbodies,l=\"addRows updateCell update updateRows updateComplete appendCache filterReset filterEnd search \".split(\" \").join(c.namespace+\"filter \");if(j.removeClass(\"hasFilters\").unbind(l.replace(d.regex.spaces,\" \")).find(\".\"+e.filterRow).remove(),f.filter_initialized=!1,!g){for(h=0;h<k.length;h++)i=d.processTbody(b,k.eq(h),!0),i.children().removeClass(f.filter_filteredRow).show(),d.processTbody(b,i,!1);f.filter_reset&&a(document).undelegate(f.filter_reset,\"click\"+c.namespace+\"filter\")}}}),b=d.filter={regex:{regex:/^\\/((?:\\\\\\/|[^\\/])+)\\/([migyu]{0,5})?$/,child:/tablesorter-childRow/,filtered:/filtered/,type:/undefined|number/,exact:/(^[\\\"\\'=]+)|([\\\"\\'=]+$)/g,operators:/[<>=]/g,query:\"(q|query)\",wild01:/\\?/g,wild0More:/\\*/g,quote:/\\\"/g,isNeg1:/(>=?\\s*-\\d)/,isNeg2:/(<=?\\s*\\d)/},types:{or:function(d,e,f){if((c.orTest.test(e.iFilter)||c.orSplit.test(e.filter))&&!c.regex.test(e.filter)){var g,h,i,j,k=a.extend({},e),l=e.filter.split(c.orSplit),m=e.iFilter.split(c.orSplit),n=l.length;for(g=0;g<n;g++){k.nestedFilters=!0,k.filter=\"\"+(b.parseFilter(d,l[g],e)||\"\"),k.iFilter=\"\"+(b.parseFilter(d,m[g],e)||\"\"),i=\"(\"+(b.parseFilter(d,k.filter,e)||\"\")+\")\";try{if(j=new RegExp(e.isMatch?i:\"^\"+i+\"$\",d.widgetOptions.filter_ignoreCase?\"i\":\"\"),h=j.test(k.exact)||b.processTypes(d,k,f))return h}catch(a){return null}}return h||!1}return null},and:function(d,e,f){if(c.andTest.test(e.filter)){var g,h,i,j,k,l=a.extend({},e),m=e.filter.split(c.andSplit),n=e.iFilter.split(c.andSplit),o=m.length;for(g=0;g<o;g++){l.nestedFilters=!0,l.filter=\"\"+(b.parseFilter(d,m[g],e)||\"\"),l.iFilter=\"\"+(b.parseFilter(d,n[g],e)||\"\"),j=(\"(\"+(b.parseFilter(d,l.filter,e)||\"\")+\")\").replace(c.wild01,\"\\\\S{1}\").replace(c.wild0More,\"\\\\S*\");try{k=new RegExp(e.isMatch?j:\"^\"+j+\"$\",d.widgetOptions.filter_ignoreCase?\"i\":\"\"),i=k.test(l.exact)||b.processTypes(d,l,f),h=0===g?i:h&&i}catch(a){return null}}return h||!1}return null},regex:function(a,b){if(c.regex.test(b.filter)){var d,e=b.filter_regexCache[b.index]||c.regex.exec(b.filter),f=e instanceof RegExp;try{f||(b.filter_regexCache[b.index]=e=new RegExp(e[1],e[2])),d=e.test(b.exact)}catch(a){d=!1}return d}return null},operators:function(e,f){if(c.operTest.test(f.iFilter)&&\"\"!==f.iExact){var g,h,i,j=e.table,k=f.parsed[f.index],l=d.formatFloat(f.iFilter.replace(c.operators,\"\"),j),m=e.parsers[f.index]||{},n=l;return(k||\"numeric\"===m.type)&&(i=a.trim(\"\"+f.iFilter.replace(c.operators,\"\")),h=b.parseFilter(e,i,f,!0),l=\"number\"!=typeof h||\"\"===h||isNaN(h)?l:h),!k&&\"numeric\"!==m.type||isNaN(l)||\"undefined\"==typeof f.cache?(i=isNaN(f.iExact)?f.iExact.replace(d.regex.nondigit,\"\"):f.iExact,g=d.formatFloat(i,j)):g=f.cache,c.gtTest.test(f.iFilter)?h=c.gteTest.test(f.iFilter)?g>=l:g>l:c.ltTest.test(f.iFilter)&&(h=c.lteTest.test(f.iFilter)?g<=l:g<l),h||\"\"!==n||(h=!0),h}return null},notMatch:function(d,e){if(c.notTest.test(e.iFilter)){var f,g=e.iFilter.replace(\"!\",\"\"),h=b.parseFilter(d,g,e)||\"\";return c.exact.test(h)?(h=h.replace(c.exact,\"\"),\"\"===h||a.trim(h)!==e.iExact):(f=e.iExact.search(a.trim(h)),\"\"===h||(e.anyMatch?f<0:!(d.widgetOptions.filter_startsWith?0===f:f>=0)))}return null},exact:function(d,e){if(c.exact.test(e.iFilter)){var f=e.iFilter.replace(c.exact,\"\"),g=b.parseFilter(d,f,e)||\"\";return e.anyMatch?a.inArray(g,e.rowArray)>=0:g==e.iExact}return null},range:function(a,e){if(c.toTest.test(e.iFilter)){var f,g,h,i,j=a.table,k=e.index,l=e.parsed[k],m=e.iFilter.split(c.toSplit);return g=m[0].replace(d.regex.nondigit,\"\")||\"\",h=d.formatFloat(b.parseFilter(a,g,e),j),g=m[1].replace(d.regex.nondigit,\"\")||\"\",i=d.formatFloat(b.parseFilter(a,g,e),j),(l||\"numeric\"===a.parsers[k].type)&&(f=a.parsers[k].format(\"\"+m[0],j,a.$headers.eq(k),k),h=\"\"===f||isNaN(f)?h:f,f=a.parsers[k].format(\"\"+m[1],j,a.$headers.eq(k),k),i=\"\"===f||isNaN(f)?i:f),!l&&\"numeric\"!==a.parsers[k].type||isNaN(h)||isNaN(i)?(g=isNaN(e.iExact)?e.iExact.replace(d.regex.nondigit,\"\"):e.iExact,f=d.formatFloat(g,j)):f=e.cache,h>i&&(g=h,h=i,i=g),f>=h&&f<=i||\"\"===h||\"\"===i}return null},wild:function(a,d){if(c.wildOrTest.test(d.iFilter)){var e=\"\"+(b.parseFilter(a,d.iFilter,d)||\"\");!c.wildTest.test(e)&&d.nestedFilters&&(e=d.isMatch?e:\"^(\"+e+\")$\");try{return new RegExp(e.replace(c.wild01,\"\\\\S{1}\").replace(c.wild0More,\"\\\\S*\"),a.widgetOptions.filter_ignoreCase?\"i\":\"\").test(d.exact)}catch(a){return null}}return null},fuzzy:function(a,d){if(c.fuzzyTest.test(d.iFilter)){var e,f=0,g=d.iExact.length,h=d.iFilter.slice(1),i=b.parseFilter(a,h,d)||\"\";for(e=0;e<g;e++)d.iExact[e]===i[f]&&(f+=1);return f===i.length}return null}},init:function(f){d.language=a.extend(!0,{},{to:\"to\",or:\"or\",and:\"and\"},d.language);var g,h,i,j,k,l,m,n,o=f.config,p=o.widgetOptions;if(o.$table.addClass(\"hasFilters\"),o.lastSearch=[],p.filter_searchTimer=null,p.filter_initTimer=null,p.filter_formatterCount=0,p.filter_formatterInit=[],p.filter_anyColumnSelector='[data-column=\"all\"],[data-column=\"any\"]',p.filter_multipleColumnSelector='[data-column*=\"-\"],[data-column*=\",\"]',l=\"\\\\{\"+c.query+\"\\\\}\",a.extend(c,{child:new RegExp(o.cssChildRow),filtered:new RegExp(p.filter_filteredRow),alreadyFiltered:new RegExp(\"(\\\\s+(\"+d.language.or+\"|-|\"+d.language.to+\")\\\\s+)\",\"i\"),toTest:new RegExp(\"\\\\s+(-|\"+d.language.to+\")\\\\s+\",\"i\"),toSplit:new RegExp(\"(?:\\\\s+(?:-|\"+d.language.to+\")\\\\s+)\",\"gi\"),andTest:new RegExp(\"\\\\s+(\"+d.language.and+\"|&&)\\\\s+\",\"i\"),andSplit:new RegExp(\"(?:\\\\s+(?:\"+d.language.and+\"|&&)\\\\s+)\",\"gi\"),orTest:new RegExp(\"(\\\\||\\\\s+\"+d.language.or+\"\\\\s+)\",\"i\"),orSplit:new RegExp(\"(?:\\\\s+(?:\"+d.language.or+\")\\\\s+|\\\\|)\",\"gi\"),iQuery:new RegExp(l,\"i\"),igQuery:new RegExp(l,\"ig\"),operTest:/^[<>]=?/,gtTest:/>/,gteTest:/>=/,ltTest:/</,lteTest:/<=/,notTest:/^\\!/,wildOrTest:/[\\?\\*\\|]/,wildTest:/\\?\\*/,fuzzyTest:/^~/,exactTest:/[=\\\"\\|!]/}),l=o.$headers.filter(\".filter-false, .parser-false\").length,p.filter_columnFilters!==!1&&l!==o.$headers.length&&b.buildRow(f,o,p),i=\"addRows updateCell update updateRows updateComplete appendCache filterReset \"+\"filterResetSaved filterEnd search \".split(\" \").join(o.namespace+\"filter \"),o.$table.bind(i,function(c,g){return l=p.filter_hideEmpty&&a.isEmptyObject(o.cache)&&!(o.delayInit&&\"appendCache\"===c.type),o.$table.find(\".\"+e.filterRow).toggleClass(p.filter_filteredRow,l),/(search|filter)/.test(c.type)||(c.stopPropagation(),b.buildDefault(f,!0)),\"filterReset\"===c.type?(o.$table.find(\".\"+e.filter).add(p.filter_$externalFilters).val(\"\"),b.searching(f,[])):\"filterResetSaved\"===c.type?d.storage(f,\"tablesorter-filters\",\"\"):\"filterEnd\"===c.type?b.buildDefault(f,!0):(g=\"search\"===c.type?g:\"updateComplete\"===c.type?o.$table.data(\"lastSearch\"):\"\",/(update|add)/.test(c.type)&&\"updateComplete\"!==c.type&&(o.lastCombinedFilter=null,o.lastSearch=[],setTimeout(function(){o.$table.triggerHandler(\"filterFomatterUpdate\")},100)),b.searching(f,g,!0)),!1}),p.filter_reset&&(p.filter_reset instanceof a?p.filter_reset.click(function(){o.$table.triggerHandler(\"filterReset\")}):a(p.filter_reset).length&&a(document).undelegate(p.filter_reset,\"click\"+o.namespace+\"filter\").delegate(p.filter_reset,\"click\"+o.namespace+\"filter\",function(){o.$table.triggerHandler(\"filterReset\")})),p.filter_functions)for(k=0;k<o.columns;k++)if(m=d.getColumnData(f,p.filter_functions,k))if(j=o.$headerIndexed[k].removeClass(\"filter-select\"),n=!(j.hasClass(\"filter-false\")||j.hasClass(\"parser-false\")),g=\"\",m===!0&&n)b.buildSelect(f,k);else if(\"object\"==typeof m&&n){for(h in m)\"string\"==typeof h&&(g+=\"\"===g?'<option value=\"\">'+(j.data(\"placeholder\")||j.attr(\"data-placeholder\")||p.filter_placeholder.select||\"\")+\"</option>\":\"\",l=h,i=h,h.indexOf(p.filter_selectSourceSeparator)>=0&&(l=h.split(p.filter_selectSourceSeparator),i=l[1],l=l[0]),g+=\"<option \"+(i===l?\"\":'data-function-name=\"'+h+'\" ')+'value=\"'+l+'\">'+i+\"</option>\");o.$table.find(\"thead\").find(\"select.\"+e.filter+'[data-column=\"'+k+'\"]').append(g),i=p.filter_selectSource,m=\"function\"==typeof i||d.getColumnData(f,i,k),m&&b.buildSelect(o.table,k,\"\",!0,j.hasClass(p.filter_onlyAvail))}b.buildDefault(f,!0),b.bindSearch(f,o.$table.find(\".\"+e.filter),!0),p.filter_external&&b.bindSearch(f,p.filter_external),p.filter_hideFilters&&b.hideFilters(o),o.showProcessing&&(i=\"filterStart filterEnd \".split(\" \").join(o.namespace+\"filter \"),o.$table.unbind(i.replace(d.regex.spaces,\" \")).bind(i,function(b,c){j=c?o.$table.find(\".\"+e.header).filter(\"[data-column]\").filter(function(){return\"\"!==c[a(this).data(\"column\")]}):\"\",d.isProcessing(f,\"filterStart\"===b.type,c?j:\"\")})),o.filteredRows=o.totalRows,i=\"tablesorter-initialized pagerBeforeInitialized \".split(\" \").join(o.namespace+\"filter \"),o.$table.unbind(i.replace(d.regex.spaces,\" \")).bind(i,function(){b.completeInit(this)}),o.pager&&o.pager.initialized&&!p.filter_initialized?(o.$table.triggerHandler(\"filterFomatterUpdate\"),setTimeout(function(){b.filterInitComplete(o)},100)):p.filter_initialized||b.completeInit(f)},completeInit:function(a){var c=a.config,e=c.widgetOptions,f=b.setDefaults(a,c,e)||[];f.length&&(c.delayInit&&\"\"===f.join(\"\")||d.setFilters(a,f,!0)),c.$table.triggerHandler(\"filterFomatterUpdate\"),setTimeout(function(){e.filter_initialized||b.filterInitComplete(c)},100)},formatterUpdated:function(a,b){var c=a&&a.closest(\"table\")[0].config.widgetOptions;c&&!c.filter_initialized&&(c.filter_formatterInit[b]=1)},filterInitComplete:function(c){var d,e,f=c.widgetOptions,g=0,h=function(){f.filter_initialized=!0,c.lastSearch=c.$table.data(\"lastSearch\"),c.$table.triggerHandler(\"filterInit\",c),b.findRows(c.table,c.lastSearch||[])};if(a.isEmptyObject(f.filter_formatter))h();else{for(e=f.filter_formatterInit.length,d=0;d<e;d++)1===f.filter_formatterInit[d]&&g++;clearTimeout(f.filter_initTimer),f.filter_initialized||g!==f.filter_formatterCount?f.filter_initialized||(f.filter_initTimer=setTimeout(function(){h()},500)):h()}},processFilters:function(a,b){var c,d=[],e=b?encodeURIComponent:decodeURIComponent,f=a.length;for(c=0;c<f;c++)a[c]&&(d[c]=e(a[c]));return d},setDefaults:function(c,e,f){var g,h,i,j,k,l=d.getFilters(c)||[];if(f.filter_saveFilters&&d.storage&&(h=d.storage(c,\"tablesorter-filters\")||[],g=a.isArray(h),g&&\"\"===h.join(\"\")||!g||(l=b.processFilters(h))),\"\"===l.join(\"\"))for(k=e.$headers.add(f.filter_$externalFilters).filter(\"[\"+f.filter_defaultAttrib+\"]\"),i=0;i<=e.columns;i++)j=i===e.columns?\"all\":i,l[i]=k.filter('[data-column=\"'+j+'\"]').attr(f.filter_defaultAttrib)||l[i]||\"\";return e.$table.data(\"lastSearch\",l),l},parseFilter:function(a,b,c,d){return d||c.parsed[c.index]?a.parsers[c.index].format(b,a.table,[],c.index):b},buildRow:function(c,f,g){var h,i,j,k,l,m,n,o,p,q=g.filter_cellFilter,r=f.columns,s=a.isArray(q),t='<tr role=\"row\" class=\"'+e.filterRow+\" \"+f.cssIgnoreRow+'\">';for(j=0;j<r;j++)f.$headerIndexed[j].length&&(p=f.$headerIndexed[j]&&f.$headerIndexed[j][0].colSpan||0,t+=p>1?'<td data-column=\"'+j+\"-\"+(j+p-1)+'\" colspan=\"'+p+'\"':'<td data-column=\"'+j+'\"',t+=s?q[j]?' class=\"'+q[j]+'\"':\"\":\"\"!==q?' class=\"'+q+'\"':\"\",t+=\"></td>\");for(f.$filters=a(t+=\"</tr>\").appendTo(f.$table.children(\"thead\").eq(0)).children(\"td\"),j=0;j<r;j++)m=!1,k=f.$headerIndexed[j],k&&k.length&&(h=b.getColumnElm(f,f.$filters,j),o=d.getColumnData(c,g.filter_functions,j),l=g.filter_functions&&o&&\"function\"!=typeof o||k.hasClass(\"filter-select\"),i=d.getColumnData(c,f.headers,j),m=\"false\"===d.getData(k[0],i,\"filter\")||\"false\"===d.getData(k[0],i,\"parser\"),l?t=a(\"<select>\").appendTo(h):(o=d.getColumnData(c,g.filter_formatter,j),o?(g.filter_formatterCount++,t=o(h,j),t&&0===t.length&&(t=h.children(\"input\")),t&&(0===t.parent().length||t.parent().length&&t.parent()[0]!==h[0])&&h.append(t)):t=a('<input type=\"search\">').appendTo(h),t&&(p=k.data(\"placeholder\")||k.attr(\"data-placeholder\")||g.filter_placeholder.search||\"\",t.attr(\"placeholder\",p))),t&&(n=(a.isArray(g.filter_cssFilter)?\"undefined\"!=typeof g.filter_cssFilter[j]?g.filter_cssFilter[j]||\"\":\"\":g.filter_cssFilter)||\"\",t.addClass(e.filter+\" \"+n).attr(\"data-column\",h.attr(\"data-column\")),m&&(t.attr(\"placeholder\",\"\").addClass(e.filterDisabled)[0].disabled=!0)))},bindSearch:function(c,e,g){if(c=a(c)[0],e=a(e),e.length){var h,i=c.config,j=i.widgetOptions,k=i.namespace+\"filter\",l=j.filter_$externalFilters;g!==!0&&(h=j.filter_anyColumnSelector+\",\"+j.filter_multipleColumnSelector,j.filter_$anyMatch=e.filter(h),l&&l.length?j.filter_$externalFilters=j.filter_$externalFilters.add(e):j.filter_$externalFilters=e,d.setFilters(c,i.$table.data(\"lastSearch\")||[],g===!1)),h=\"keypress keyup keydown search change input \".split(\" \").join(k+\" \"),e.attr(\"data-lastSearchTime\",(new Date).getTime()).unbind(h.replace(d.regex.spaces,\" \")).bind(\"keydown\"+k,function(a){if(a.which===f.escape&&!c.config.widgetOptions.filter_resetOnEsc)return!1}).bind(\"keyup\"+k,function(e){j=c.config.widgetOptions;var g=parseInt(a(this).attr(\"data-column\"),10),h=\"boolean\"==typeof j.filter_liveSearch?j.filter_liveSearch:d.getColumnData(c,j.filter_liveSearch,g);if(\"undefined\"==typeof h&&(h=j.filter_liveSearch.fallback||!1),a(this).attr(\"data-lastSearchTime\",(new Date).getTime()),e.which===f.escape)this.value=j.filter_resetOnEsc?\"\":i.lastSearch[g];else{if(h===!1)return;if(\"\"!==this.value&&(\"number\"==typeof h&&this.value.length<h||e.which!==f.enter&&e.which!==f.backSpace&&(e.which<f.space||e.which>=f.left&&e.which<=f.down)))return}b.searching(c,!0,!0,g)}).bind(\"search change keypress input \".split(\" \").join(k+\" \"),function(e){var g=parseInt(a(this).attr(\"data-column\"),10),h=\"boolean\"==typeof j.filter_liveSearch?j.filter_liveSearch:d.getColumnData(c,j.filter_liveSearch,g);!c.config.widgetOptions.filter_initialized||e.which!==f.enter&&\"search\"!==e.type&&(\"change\"!==e.type&&\"input\"!==e.type||h!==!0||this.value===i.lastSearch[g])||(e.preventDefault(),a(this).attr(\"data-lastSearchTime\",(new Date).getTime()),b.searching(c,\"keypress\"!==e.type,!0,g))})}},searching:function(a,c,e,f){var g,h=a.config.widgetOptions;\"undefined\"==typeof f?g=!1:(g=\"boolean\"==typeof h.filter_liveSearch?h.filter_liveSearch:d.getColumnData(a,h.filter_liveSearch,f),\"undefined\"==typeof g&&(g=h.filter_liveSearch.fallback||!1)),clearTimeout(h.filter_searchTimer),\"undefined\"==typeof c||c===!0?h.filter_searchTimer=setTimeout(function(){b.checkFilters(a,c,e)},g?h.filter_searchDelay:10):b.checkFilters(a,c,e)},checkFilters:function(c,f,g){var h=c.config,i=h.widgetOptions,j=a.isArray(f),k=j?f:d.getFilters(c,!0),l=(k||[]).join(\"\");return a.isEmptyObject(h.cache)?void(h.delayInit&&(!h.pager||h.pager&&h.pager.initialized)&&d.updateCache(h,function(){b.checkFilters(c,!1,g)})):(j&&(d.setFilters(c,k,!1,g!==!0),i.filter_initialized||(h.lastCombinedFilter=\"\")),i.filter_hideFilters&&h.$table.find(\".\"+e.filterRow).triggerHandler(b.hideFiltersCheck(h)?\"mouseleave\":\"mouseenter\"),h.lastCombinedFilter!==l||f===!1?(f===!1&&(h.lastCombinedFilter=null,h.lastSearch=[]),k=k||[],k=Array.prototype.map?k.map(String):k.join(\"<22>\").split(\"<22>\"),i.filter_initialized&&h.$table.triggerHandler(\"filterStart\",[k]),h.showProcessing?void setTimeout(function(){return b.findRows(c,k,l),!1},30):(b.findRows(c,k,l),!1)):void 0)},hideFiltersCheck:function(a){if(\"function\"==typeof a.widgetOptions.filter_hideFilters){var b=a.widgetOptions.filter_hideFilters(a);if(\"boolean\"==typeof b)return b}return\"\"===d.getFilters(a.$table).join(\"\")},hideFilters:function(c,d){var f;(d||c.$table).find(\".\"+e.filterRow).addClass(e.filterRowHide).bind(\"mouseenter mouseleave\",function(d){var g=d,h=a(this);clearTimeout(f),f=setTimeout(function(){/enter|over/.test(g.type)?h.removeClass(e.filterRowHide):a(document.activeElement).closest(\"tr\")[0]!==h[0]&&h.toggleClass(e.filterRowHide,b.hideFiltersCheck(c))},200)}).find(\"input, select\").bind(\"focus blur\",function(d){var g=d,h=a(this).closest(\"tr\");clearTimeout(f),f=setTimeout(function(){clearTimeout(f),h.toggleClass(e.filterRowHide,b.hideFiltersCheck(c)&&\"focus\"!==g.type)},200)})},defaultFilter:function(b,d){if(\"\"===b)return b;var e=c.iQuery,f=d.match(c.igQuery).length,g=f>1?a.trim(b).split(/\\s/):[a.trim(b)],h=g.length-1,i=0,j=d;for(h<1&&f>1&&(g[1]=g[0]);e.test(j);)j=j.replace(e,g[i++]||\"\"),e.test(j)&&i<h&&\"\"!==(g[i]||\"\")&&(j=d.replace(e,j));return j},getLatestSearch:function(b){return b?b.sort(function(b,c){return a(c).attr(\"data-lastSearchTime\")-a(b).attr(\"data-lastSearchTime\")}):b||a()},findRange:function(a,b,c){var d,e,f,g,h,i,j,k,l,m=[];if(/^[0-9]+$/.test(b))return[parseInt(b,10)];if(!c&&/-/.test(b))for(e=b.match(/(\\d+)\\s*-\\s*(\\d+)/g),l=e?e.length:0,k=0;k<l;k++){for(f=e[k].split(/\\s*-\\s*/),g=parseInt(f[0],10)||0,h=parseInt(f[1],10)||a.columns-1,g>h&&(d=g,g=h,h=d),h>=a.columns&&(h=a.columns-1);g<=h;g++)m[m.length]=g;b=b.replace(e[k],\"\")}if(!c&&/,/.test(b))for(i=b.split(/\\s*,\\s*/),l=i.length,j=0;j<l;j++)\"\"!==i[j]&&(k=parseInt(i[j],10),k<a.columns&&(m[m.length]=k));if(!m.length)for(k=0;k<a.columns;k++)m[m.length]=k;return m},getColumnElm:function(c,d,e){return d.filter(function(){var d=b.findRange(c,a(this).attr(\"data-column\"));return a.inArray(e,d)>-1})},multipleColumns:function(c,d){var e=c.widgetOptions,f=e.filter_initialized||!d.filter(e.filter_anyColumnSelector).length,g=a.trim(b.getLatestSearch(d).attr(\"data-column\")||\"\");return b.findRange(c,g,!f)},processTypes:function(c,d,e){var f,g=null,h=null;for(f in b.types)a.inArray(f,e.excludeMatch)<0&&null===h&&(h=b.types[f](c,d,e),null!==h&&(g=h));return g},matchType:function(a,b){var c,d=a.widgetOptions,f=a.$headerIndexed[b];return f.hasClass(\"filter-exact\")?c=!1:f.hasClass(\"filter-match\")?c=!0:(d.filter_columnFilters?f=a.$filters.find(\".\"+e.filter).add(d.filter_$externalFilters).filter('[data-column=\"'+b+'\"]'):d.filter_$externalFilters&&(f=d.filter_$externalFilters.filter('[data-column=\"'+b+'\"]')),c=!!f.length&&\"match\"===a.widgetOptions.filter_matchType[(f[0].nodeName||\"\").toLowerCase()]),c},processRow:function(e,f,g){var h,i,j,k,l,m=e.widgetOptions,n=!0,o=m.filter_$anyMatch&&m.filter_$anyMatch.length,p=m.filter_$anyMatch&&m.filter_$anyMatch.length?b.multipleColumns(e,m.filter_$anyMatch):[];if(f.$cells=f.$row.children(),f.anyMatchFlag&&p.length>1||f.anyMatchFilter&&!o){if(f.anyMatch=!0,f.isMatch=!0,f.rowArray=f.$cells.map(function(b){if(a.inArray(b,p)>-1||f.anyMatchFilter&&!o)return f.parsed[b]?l=f.cacheArray[b]:(l=f.rawArray[b],l=a.trim(m.filter_ignoreCase?l.toLowerCase():l),e.sortLocaleCompare&&(l=d.replaceAccents(l))),l}).get(),f.filter=f.anyMatchFilter,f.iFilter=f.iAnyMatchFilter,f.exact=f.rowArray.join(\" \"),f.iExact=m.filter_ignoreCase?f.exact.toLowerCase():f.exact,f.cache=f.cacheArray.slice(0,-1).join(\" \"),g.excludeMatch=g.noAnyMatch,i=b.processTypes(e,f,g),null!==i)n=i;else if(m.filter_startsWith)for(n=!1,p=Math.min(e.columns,f.rowArray.length);!n&&p>0;)p--,n=n||0===f.rowArray[p].indexOf(f.iFilter);else n=(f.iExact+f.childRowText).indexOf(f.iFilter)>=0;if(f.anyMatch=!1,f.filters.join(\"\")===f.filter)return n}for(p=0;p<e.columns;p++)f.filter=f.filters[p],f.index=p,g.excludeMatch=g.excludeFilter[p],f.filter&&(f.cache=f.cacheArray[p],h=f.parsed[p]?f.cache:f.rawArray[p]||\"\",f.exact=e.sortLocaleCompare?d.replaceAccents(h):h,f.iExact=!c.type.test(typeof f.exact)&&m.filter_ignoreCase?f.exact.toLowerCase():f.exact,f.isMatch=b.matchType(e,p),h=n,k=m.filter_columnFilters?e.$filters.add(m.filter_$externalFilters).filter('[data-column=\"'+p+'\"]').find(\"select option:selected\").attr(\"data-function-name\")||\"\":\"\",e.sortLocaleCompare&&(f.filter=d.replaceAccents(f.filter)),m.filter_defaultFilter&&c.iQuery.test(g.defaultColFilter[p])&&(f.filter=b.defaultFilter(f.filter,g.defaultColFilter[p])),f.iFilter=m.filter_ignoreCase?(f.filter||\"\").toLowerCase():f.filter,j=g.functions[p],i=null,j&&(j===!0?i=f.isMatch?(\"\"+f.iExact).search(f.iFilter)>=0:f.filter===f.exact:\"function\"==typeof j?i=j(f.exact,f.cache,f.filter,p,f.$row,e,f):\"function\"==typeof j[k||f.filter]&&(l=k||f.filter,i=j[l](f.exact,f.cache,f.filter,p,f.$row,e,f))),null===i?(i=b.processTypes(e,f,g),null!==i?h=i:(l=(f.iExact+f.childRowText).indexOf(b.parseFilter(e,f.iFilter,f)),h=!m.filter_startsWith&&l>=0||m.filter_startsWith&&0===l)):h=i,n=!!h&&n);return n},findRows:function(e,f,g){if(e.config.lastCombinedFilter!==g&&e.config.widgetOptions.filter_initialized){var h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F=a.extend([],f),G=e.config,H=G.widgetOptions,I={anyMatch:!1,filters:f,filter_regexCache:[]},J={noAnyMatch:[\"range\",\"operators\"],functions:[],excludeFilter:[],defaultColFilter:[],defaultAnyFilter:d.getColumnData(e,H.filter_defaultFilter,G.columns,!0)||\"\"};for(I.parsed=[],p=0;p<G.columns;p++)I.parsed[p]=H.filter_useParsedData||G.parsers&&G.parsers[p]&&G.parsers[p].parsed||d.getData&&\"parsed\"===d.getData(G.$headerIndexed[p],d.getColumnData(e,G.headers,p),\"filter\")||G.$headerIndexed[p].hasClass(\"filter-parsed\"),J.functions[p]=d.getColumnData(e,H.filter_functions,p)||G.$headerIndexed[p].hasClass(\"filter-select\"),J.defaultColFilter[p]=d.getColumnData(e,H.filter_defaultFilter,p)||\"\",J.excludeFilter[p]=(d.getColumnData(e,H.filter_excludeFilter,p,!0)||\"\").split(/\\s+/);for(G.debug&&(console.log(\"Filter: Starting filter widget search\",f),v=new Date),G.filteredRows=0,G.totalRows=0,g=(F||[]).join(\"\"),n=0;n<G.$tbodies.length;n++){if(o=d.processTbody(e,G.$tbodies.eq(n),!0),p=G.columns,i=G.cache[n].normalized,k=a(a.map(i,function(a){return a[p].$row.get()})),\"\"===g||H.filter_serversideFiltering)k.removeClass(H.filter_filteredRow).not(\".\"+G.cssChildRow).css(\"display\",\"\");else{if(k=k.not(\".\"+G.cssChildRow),h=k.length,(H.filter_$anyMatch&&H.filter_$anyMatch.length||\"undefined\"!=typeof f[G.columns])&&(I.anyMatchFlag=!0,I.anyMatchFilter=\"\"+(f[G.columns]||H.filter_$anyMatch&&b.getLatestSearch(H.filter_$anyMatch).val()||\"\"),H.filter_columnAnyMatch)){for(A=I.anyMatchFilter.split(c.andSplit),B=!1,x=0;x<A.length;x++)C=A[x].split(\":\"),C.length>1&&(isNaN(C[0])?a.each(G.headerContent,function(a,b){b.toLowerCase().indexOf(C[0])>-1&&(D=a,f[D]=C[1])}):D=parseInt(C[0],10)-1,D>=0&&D<G.columns&&(f[D]=C[1],A.splice(x,1),x--,B=!0));B&&(I.anyMatchFilter=A.join(\" && \"))}if(z=H.filter_searchFiltered,s=G.lastSearch||G.$table.data(\"lastSearch\")||[],z)for(x=0;x<p+1;x++)w=f[x]||\"\",z||(x=p),z=z&&s.length&&0===w.indexOf(s[x]||\"\")&&!c.alreadyFiltered.test(w)&&!c.exactTest.test(w)&&!(c.isNeg1.test(w)||c.isNeg2.test(w))&&!(\"\"!==w&&G.$filters&&G.$filters.filter('[data-column=\"'+x+'\"]').find(\"select\").length&&!b.matchType(G,x));for(y=k.not(\".\"+H.filter_filteredRow).length,z&&0===y&&(z=!1),G.debug&&console.log(\"Filter: Searching through \"+(z&&y<h?y:\"all\")+\" rows\"),I.anyMatchFlag&&(G.sortLocaleCompare&&(I.anyMatchFilter=d.replaceAccents(I.anyMatchFilter)),H.filter_defaultFilter&&c.iQuery.test(J.defaultAnyFilter)&&(I.anyMatchFilter=b.defaultFilter(I.anyMatchFilter,J.defaultAnyFilter),z=!1),I.iAnyMatchFilter=H.filter_ignoreCase&&G.ignoreCase?I.anyMatchFilter.toLowerCase():I.anyMatchFilter),m=0;m<h;m++)if(E=k[m].className,q=m&&c.child.test(E),!(q||z&&c.filtered.test(E))){if(I.$row=k.eq(m),I.rowIndex=m,I.cacheArray=i[m],j=I.cacheArray[G.columns],I.rawArray=j.raw,I.childRowText=\"\",!H.filter_childByColumn){for(E=\"\",r=j.child,x=0;x<r.length;x++)E+=\" \"+r[x].join(\" \")||\"\";I.childRowText=H.filter_childRows?H.filter_ignoreCase?E.toLowerCase():E:\"\"}if(t=!1,u=b.processRow(G,I,J),l=j.$row,w=!!u,r=j.$row.filter(\":gt(0)\"),H.filter_childRows&&r.length){if(H.filter_childByColumn)for(H.filter_childWithSibs||(r.addClass(H.filter_filteredRow),l=l.eq(0)),x=0;x<r.length;x++)I.$row=r.eq(x),I.cacheArray=j.child[x],I.rawArray=I.cacheArray,w=b.processRow(G,I,J),t=t||w,!H.filter_childWithSibs&&w&&r.eq(x).removeClass(H.filter_filteredRow);t=t||u}else t=w;l.toggleClass(H.filter_filteredRow,!t)[0].display=t?\"\":\"none\"}}G.filteredRows+=k.not(\".\"+H.filter_filteredRow).length,G.totalRows+=k.length,d.processTbody(e,o,!1)}G.lastCombinedFilter=g,G.lastSearch=F,G.$table.data(\"lastSearch\",F),H.filter_saveFilters&&d.storage&&d.storage(e,\"tablesorter-filters\",b.processFilters(F,!0)),G.debug&&console.log(\"Completed filter widget search\"+d.benchmark(v)),H.filter_initialized&&(G.$table.triggerHandler(\"filterBeforeEnd\",G),G.$table.triggerHandler(\"filterEnd\",G)),setTimeout(function(){d.applyWidget(G.table)},0)}},getOptionSource:function(c,e,f){c=a(c)[0];var g=c.config,h=g.widgetOptions,i=!1,j=h.filter_selectSource,k=g.$table.data(\"lastSearch\")||[],l=\"function\"==typeof j||d.getColumnData(c,j,e);if(f&&\"\"!==k[e]&&(f=!1),l===!0)i=j(c,e,f);else{if(l instanceof a||\"string\"===a.type(l)&&l.indexOf(\"</option>\")>=0)return l;a.isArray(l)?i=l:\"object\"===a.type(j)&&l&&(i=l(c,e,f))}return i===!1&&(i=b.getOptions(c,e,f)),b.processOptions(c,e,i)},processOptions:function(b,c,e){if(!a.isArray(e))return!1;b=a(b)[0];var f,g,h,i,j,k,l=b.config,m=\"undefined\"!=typeof c&&null!==c&&c>=0&&c<l.columns,n=!!m&&l.$headerIndexed[c].hasClass(\"filter-select-sort-desc\"),o=[];if(e=a.grep(e,function(b,c){return!!b.text||a.inArray(b,e)===c}),m&&l.$headerIndexed[c].hasClass(\"filter-select-nosort\"))return e;for(i=e.length,h=0;h<i;h++)g=e[h],k=g.text?g.text:g,j=(m&&l.parsers&&l.parsers.length&&l.parsers[c].format(k,b,[],c)||k).toString(),j=l.widgetOptions.filter_ignoreCase?j.toLowerCase():j,g.text?(g.parsed=j,o[o.length]=g):o[o.length]={text:g,parsed:j};for(f=l.textSorter||\"\",o.sort(function(a,e){var g=n?e.parsed:a.parsed,h=n?a.parsed:e.parsed;return m&&\"function\"==typeof f?f(g,h,!0,c,b):m&&\"object\"==typeof f&&f.hasOwnProperty(c)?f[c](g,h,!0,c,b):!d.sortNatural||d.sortNatural(g,h)}),e=[],i=o.length,h=0;h<i;h++)e[e.length]=o[h];return e},getOptions:function(b,c,e){b=a(b)[0];var f,g,h,i,j,k,l,m,n=b.config,o=n.widgetOptions,p=[];for(g=0;g<n.$tbodies.length;g++)for(j=n.cache[g],h=n.cache[g].normalized.length,f=0;f<h;f++)if(i=j.row?j.row[f]:j.normalized[f][n.columns].$row[0],!e||!i.className.match(o.filter_filteredRow))if(o.filter_useParsedData||n.parsers[c].parsed||n.$headerIndexed[c].hasClass(\"filter-parsed\")){if(p[p.length]=\"\"+j.normalized[f][c],o.filter_childRows&&o.filter_childByColumn)for(m=j.normalized[f][n.columns].$row.length-1,k=0;k<m;k++)p[p.length]=\"\"+j.normalized[f][n.columns].child[k][c]}else if(p[p.length]=j.normalized[f][n.columns].raw[c],o.filter_childRows&&o.filter_childByColumn)for(m=j.normalized[f][n.columns].$row.length,k=1;k<m;k++)l=j.normalized[f][n.columns].$row.eq(k).children().eq(c),p[p.length]=\"\"+d.getElementText(n,l,c);return p},buildSelect:function(d,f,g,h,i){if(d=a(d)[0],f=parseInt(f,10),d.config.cache&&!a.isEmptyObject(d.config.cache)){var j,k,l,m,n,o,p,q=d.config,r=q.widgetOptions,s=q.$headerIndexed[f],t='<option value=\"\">'+(s.data(\"placeholder\")||s.attr(\"data-placeholder\")||r.filter_placeholder.select||\"\")+\"</option>\",u=q.$table.find(\"thead\").find(\"select.\"+e.filter+'[data-column=\"'+f+'\"]').val();if(\"undefined\"!=typeof g&&\"\"!==g||(g=b.getOptionSource(d,f,i)),a.isArray(g)){for(j=0;j<g.length;j++)if(p=g[j],p.text){p[\"data-function-name\"]=\"undefined\"==typeof p.value?p.text:p.value,t+=\"<option\";for(k in p)p.hasOwnProperty(k)&&\"text\"!==k&&(t+=\" \"+k+'=\"'+p[k]+'\"');p.value||(t+=' value=\"'+p.text+'\"'),t+=\">\"+p.text+\"</option>\"}else\"\"+p!=\"[object Object]\"&&(l=p=(\"\"+p).replace(c.quote,\""\"),k=l,l.indexOf(r.filter_selectSourceSeparator)>=0&&(m=l.split(r.filter_selectSourceSeparator),k=m[0],l=m[1]),t+=\"\"!==p?\"<option \"+(k===l?\"\":'data-function-name=\"'+p+'\" ')+'value=\"'+k+'\">'+l+\"</option>\":\"\");g=[]}n=(q.$filters?q.$filters:q.$table.children(\"thead\")).find(\".\"+e.filter),r.filter_$externalFilters&&(n=n&&n.length?n.add(r.filter_$externalFilters):r.filter_$externalFilters),o=n.filter('select[data-column=\"'+f+'\"]'),o.length&&(o[h?\"html\":\"append\"](t),a.isArray(g)||o.append(g).val(u),o.val(u))}},buildDefault:function(a,c){var e,f,g,h=a.config,i=h.widgetOptions,j=h.columns;for(e=0;e<j;e++)f=h.$headerIndexed[e],g=!(f.hasClass(\"filter-false\")||f.hasClass(\"parser-false\")),(f.hasClass(\"filter-select\")||d.getColumnData(a,i.filter_functions,e)===!0)&&g&&b.buildSelect(a,e,\"\",c,f.hasClass(i.filter_onlyAvail))}},c=b.regex,d.getFilters=function(c,d,f,g){var h,i,j,k,l=[],m=c?a(c)[0].config:\"\",n=m?m.widgetOptions:\"\";if(d!==!0&&n&&!n.filter_columnFilters||a.isArray(f)&&f.join(\"\")===m.lastCombinedFilter)return a(c).data(\"lastSearch\");if(m&&(m.$filters&&(i=m.$filters.find(\".\"+e.filter)),n.filter_$externalFilters&&(i=i&&i.length?i.add(n.filter_$externalFilters):n.filter_$externalFilters),i&&i.length))for(l=f||[],h=0;h<m.columns+1;h++)k=h===m.columns?n.filter_anyColumnSelector+\",\"+n.filter_multipleColumnSelector:'[data-column=\"'+h+'\"]',j=i.filter(k),j.length&&(j=b.getLatestSearch(j),a.isArray(f)?(g&&j.length>1&&(j=j.slice(1)),h===m.columns&&(k=j.filter(n.filter_anyColumnSelector),j=k.length?k:j),j.val(f[h]).trigger(\"change\"+m.namespace)):(l[h]=j.val()||\"\",h===m.columns?j.slice(1).filter('[data-column*=\"'+j.attr(\"data-column\")+'\"]').val(l[h]):j.slice(1).val(l[h])),h===m.columns&&j.length&&(n.filter_$anyMatch=j));return l},d.setFilters=function(c,e,f,g){var h=c?a(c)[0].config:\"\",i=d.getFilters(c,!0,e,g);return\"undefined\"==typeof f&&(f=!0),h&&f&&(h.lastCombinedFilter=null,h.lastSearch=[],b.searching(h.table,e,g),h.$table.triggerHandler(\"filterFomatterUpdate\")),0!==i.length}}(jQuery);"],"sourceRoot":"/source/"} |