/*! tablesorter Grouping widget - updated 3/7/2014 (core v2.15.6) * Requires tablesorter v2.8+ and jQuery 1.7+ * by Rob Garrison */ /*jshint browser:true, jquery:true, unused:false */ /*global jQuery: false */ ;(function($){ "use strict"; var ts = $.tablesorter; ts.grouping = { types : { number : function(c, $column, txt, num, group){ var value, word; if (num > 1 && txt !== '') { if ($column.hasClass(ts.css.sortAsc)) { value = Math.floor(parseFloat(txt)/num) * num; return value > parseFloat(group || 0) ? value : parseFloat(group || 0); } else { value = Math.ceil(parseFloat(txt)/num) * num; return value < parseFloat(group || num) - value ? parseFloat(group || num) - value : value; } } else { word = (txt + '').match(/\d+/g); return word && word.length >= num ? word[num - 1] : txt || ''; } }, separator : function(c, $column, txt, num){ var word = (txt + '').split(c.widgetOptions.group_separator); return $.trim(word && num > 0 && word.length >= num ? word[(num || 1) - 1] : ''); }, word : function(c, $column, txt, num){ var word = (txt + ' ').match(/\w+/g); return word && word.length >= num ? word[num - 1] : txt || ''; }, letter : function(c, $column, txt, num){ return txt ? (txt + ' ').substring(0, num) : ''; }, date : function(c, $column, txt, part, group){ var wo = c.widgetOptions, time = new Date(txt || ''), hours = time.getHours(); return part === 'year' ? time.getFullYear() : part === 'month' ? wo.group_months[time.getMonth()] : part === 'monthyear' ? wo.group_months[time.getMonth()] + ' ' + time.getFullYear() : part === 'day' ? wo.group_months[time.getMonth()] + ' ' + time.getDate() : part === 'week' ? wo.group_week[time.getDay()] : part === 'time' ? ('00' + (hours > 12 ? hours - 12 : hours === 0 ? hours + 12 : hours)).slice(-2) + ':' + ('00' + time.getMinutes()).slice(-2) + ' ' + ('00' + wo.group_time[hours >= 12 ? 1 : 0]).slice(-2) : wo.group_dateString(time); } }, update : function(table, c, wo){ if ($.isEmptyObject(c.cache)) { return; } var rowIndex, tbodyIndex, currentGroup, $rows, groupClass, grouping, cache, saveName, direction, lang = wo.grouping_language, group = '', savedGroup = false, column = c.sortList[0] ? c.sortList[0][0] : -1; c.$table .find('tr.group-hidden').removeClass('group-hidden').end() .find('tr.group-header').remove(); if (wo.group_collapsible) { // clear pager saved spacer height (in case the rows are collapsed) c.$table.data('pagerSavedHeight', 0); } if (column >= 0 && !c.$headers.filter('[data-column="' + column + '"]:last').hasClass('group-false')) { wo.group_currentGroup = ''; // save current groups wo.group_currentGroups = {}; // group class finds "group-{word/separator/letter/number/date/false}-{optional:#/year/month/day/week/time}" groupClass = (c.$headers.filter('[data-column="' + column + '"]:last').attr('class') || '').match(/(group-\w+(-\w+)?)/g); // grouping = [ 'group', '{word/separator/letter/number/date/false}', '{#/year/month/day/week/time}' ] grouping = groupClass ? groupClass[0].split('-') : ['group','letter',1]; // default to letter 1 // save current grouping if (wo.group_collapsible && wo.group_saveGroups && ts.storage) { wo.group_currentGroups = ts.storage( table, 'tablesorter-groups' ) || {}; // include direction when grouping numbers > 1 (reversed direction shows different range values) direction = (grouping[1] === 'number' && grouping[2] > 1) ? 'dir' + c.sortList[0][1] : ''; // combine column, sort direction & grouping as save key saveName = wo.group_currentGroup = '' + column + direction + grouping.join(''); if (!wo.group_currentGroups[saveName]) { wo.group_currentGroups[saveName] = []; } else { savedGroup = true; } } for (tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++) { cache = c.cache[tbodyIndex].normalized; group = ''; // clear grouping across tbodies $rows = c.$tbodies.eq(tbodyIndex).children('tr').not('.' + c.cssChildRow); for (rowIndex = 0; rowIndex < $rows.length; rowIndex++) { if ( $rows.eq(rowIndex).is(':visible') ) { // fixes #438 if (ts.grouping.types[grouping[1]]) { currentGroup = cache[rowIndex] ? ts.grouping.types[grouping[1]]( c, c.$headers.filter('[data-column="' + column + '"]:last'), cache[rowIndex][column], /date/.test(groupClass) ? grouping[2] : parseInt(grouping[2] || 1, 10) || 1, group, lang ) : currentGroup; if (group !== currentGroup) { group = currentGroup; // show range if number > 1 if (grouping[1] === 'number' && grouping[2] > 1 && currentGroup !== '') { currentGroup += ' - ' + (parseInt(currentGroup, 10) + ((parseInt(grouping[2],10) - 1) * (c.$headers.filter('[data-column="' + column + '"]:last').hasClass(ts.css.sortAsc) ? 1 : -1))); } if ($.isFunction(wo.group_formatter)) { currentGroup = wo.group_formatter((currentGroup || '').toString(), column, table, c, wo) || currentGroup; } $rows.eq(rowIndex).before('