/*! Widget: filter, html5 formatter functions - updated 7/17/2014 (v2.17.5) *//* * requires: tableSorter (FORK) 2.15+ and jQuery 1.4.3+ * * html5Number (spinner) * html5Range (slider) * html5Color (color) */ /*jshint browser:true, jquery:true, unused:false */ /*global jQuery: false */ ;(function($){ 'use strict'; var ts = $.tablesorter || {}, // compare option selector class name (jQuery selector) compareSelect = '.compare-select', tsff = ts.filterFormatter = $.extend( {}, ts.filterFormatter, { addCompare: function($cell, indx, options){ if (options.compare && $.isArray(options.compare) && options.compare.length > 1) { var opt = '', compareSelectClass = [ compareSelect.slice(1), ' ' + compareSelect.slice(1), '' ], txt = options.cellText ? '' : ''; $.each(options.compare, function(i, c){ opt += ''; }); $cell .wrapInner('
') .prepend( txt + '').appendTo($cell), // test if HTML5 number is supported - from Modernizr numberSupported = o.skipTest || $number.attr('type') === 'number' && $number.val() !== 'test', $shcell = [], c = $cell.closest('table')[0].config, updateNumber = function(delayed, notrigger){ var chkd = o.addToggle ? $cell.find('.toggle').is(':checked') : true, v = $cell.find('.number').val(), compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) || '' : true; $input // add equal to the beginning, so we filter exact numbers .val( !o.addToggle || chkd ? (compare ? compare : o.exactMatch ? '=' : '') + v : '' ) .trigger( notrigger ? '' : 'search', searchType ).end() .find('.number').val(v); if ($cell.find('.number').length) { $cell.find('.number')[0].disabled = (o.disabled || !chkd); } // update sticky header cell if ($shcell.length) { $shcell.find('.number').val(v)[0].disabled = (o.disabled || !chkd); $shcell.find(compareSelect).val(compare); if (o.addToggle) { $shcell.find('.toggle')[0].checked = chkd; } } }; $number.remove(); if (numberSupported) { t = o.addToggle ? '
' + '
' : ''; t += ''; // add HTML5 number (spinner) $cell .append(t + '') .find('.toggle, .number').bind('change', function(){ updateNumber(); }) .closest('thead').find('th[data-column=' + indx + ']') .addClass('filter-parsed') // get exact numbers from column // on reset .closest('table').bind('filterReset', function(){ if ($.isArray(o.compare)) { $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); } // turn off the toggle checkbox if (o.addToggle) { $cell.find('.toggle')[0].checked = false; if ($shcell.length) { $shcell.find('.toggle')[0].checked = false; } } $cell.find('.number').val( o.value ); setTimeout(function(){ updateNumber(); }, 0); }); $input = $cell.find('input[type=hidden]').bind('change', function(){ $cell.find('.number').val( this.value ); updateNumber(); }); // update slider from hidden input, in case of saved filters c.$table.bind('filterFomatterUpdate', function(){ var val = tsff.updateCompare($cell, $input, o)[0] || o.value; $cell.find('.number').val( ((val || '') + '').replace(/[><=]/g, '') ); updateNumber(false, true); ts.filter.formatterUpdated($cell, indx); }); if (o.compare) { // add compare select tsff.addCompare($cell, indx, o); $cell.find(compareSelect).bind('change', function(){ updateNumber(); }); } // has sticky headers? c.$table.bind('stickyHeadersInit', function(){ $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); $shcell .append(t) .find('.toggle, .number').bind('change', function(){ $cell.find('.number').val( $(this).val() ); updateNumber(); }); if (o.compare) { // add compare select tsff.addCompare($shcell, indx, o); $shcell.find(compareSelect).bind('change', function(){ $cell.find(compareSelect).val( $(this).val() ); updateNumber(); }); } updateNumber(); }); updateNumber(); } return numberSupported ? $cell.find('input[type="hidden"]') : $(''); }, /**********************\ HTML5 range slider \**********************/ html5Range : function($cell, indx, def5Range) { var o = $.extend({ value : 0, min : 0, max : 100, step : 1, delayed : true, valueToHeader : true, exactMatch : true, cellText : '', compare : '', allText : 'all', skipTest : false }, def5Range), $input, // test browser for HTML5 range support $range = $('').appendTo($cell), // test if HTML5 range is supported - from Modernizr (but I left out the method to detect in Safari 2-4) // see https://github.com/Modernizr/Modernizr/blob/master/feature-detects/inputtypes.js rangeSupported = o.skipTest || $range.attr('type') === 'range' && $range.val() !== 'test', $shcell = [], c = $cell.closest('table')[0].config, updateRange = function(v, delayed, notrigger){ /*jshint eqeqeq:false */ // hidden input changes may include compare symbols v = ( typeof v === 'undefined' ? $input.val() : v ).toString().replace(/[<>=]/g, '') || o.value; var compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || '', t = ' (' + (compare ? compare + v : v == o.min ? o.allText : v) + ')', searchType = c.$table[0].hasInitialized ? (delayed ? delayed : o.delayed) || '' : true; $cell.find('input[type=hidden]') // add equal to the beginning, so we filter exact numbers .val( ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ) ) // ( val == o.min ? '' : val + (o.exactMatch ? '=' : '')) .trigger( notrigger ? '' : 'search', searchType ).end() .find('.range').val(v); // or add current value to the header cell, if desired $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t); // update sticky header cell if ($shcell.length) { $shcell .find('.range').val(v).end() .find(compareSelect).val( compare ); $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curvalue').html(t); } }; $range.remove(); if (rangeSupported) { // add HTML5 range $cell .html('') .closest('thead').find('th[data-column=' + indx + ']') .addClass('filter-parsed') // get exact numbers from column // add span to header for the current slider value .find('.tablesorter-header-inner').append(''); // hidden filter update namespace trigger by filter widget $input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){ /*jshint eqeqeq:false */ var v = this.value, compare = ($.isArray(o.compare) ? $cell.find(compareSelect).val() || o.compare[ o.selected || 0] : o.compare) || ''; if (v !== this.lastValue) { this.lastValue = ( compare ? compare + v : ( v == o.min ? '' : ( o.exactMatch ? '=' : '' ) + v ) ); this.value = this.lastValue; updateRange( v ); } }); $cell.find('.range').bind('change', function(){ updateRange( this.value ); }); // update spinner from hidden input, in case of saved filters c.$table.bind('filterFomatterUpdate', function(){ var val = tsff.updateCompare($cell, $input, o)[0]; $cell.find('.range').val( val ); updateRange(val, false, true); ts.filter.formatterUpdated($cell, indx); }); if (o.compare) { // add compare select tsff.addCompare($cell, indx, o); $cell.find(compareSelect).bind('change', function(){ updateRange(); }); } // has sticky headers? c.$table.bind('stickyHeadersInit', function(){ $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty(); $shcell .html('') .find('.range').bind('change', function(){ updateRange( $shcell.find('.range').val() ); }); updateRange(); if (o.compare) { // add compare select tsff.addCompare($shcell, indx, o); $shcell.find(compareSelect).bind('change', function(){ $cell.find(compareSelect).val( $(this).val() ); updateRange(); }); } }); // on reset $cell.closest('table').bind('filterReset', function(){ if ($.isArray(o.compare)) { $cell.add($shcell).find(compareSelect).val( o.compare[ o.selected || 0 ] ); } setTimeout(function(){ updateRange(o.value, false, true); }, 0); }); updateRange(); } return rangeSupported ? $cell.find('input[type="hidden"]') : $(''); }, /**********************\ HTML5 Color picker \**********************/ html5Color: function($cell, indx, defColor) { var t, o = $.extend({ value : '#000000', disabled : false, addToggle : true, exactMatch : true, valueToHeader : false, skipTest : false }, defColor), $input, // Add a hidden input to hold the range values $color = $('').appendTo($cell), // test if HTML5 color is supported - from Modernizr colorSupported = o.skipTest || $color.attr('type') === 'color' && $color.val() !== 'test', $shcell = [], c = $cell.closest('table')[0].config, updateColor = function(v, notrigger) { v = ( typeof v === 'undefined' ? $input.val() : v ).toString().replace('=', '') || o.value; var chkd = true, t = ' (' + v + ')'; if (o.addToggle) { chkd = $cell.find('.toggle').is(':checked'); } if ($cell.find('.colorpicker').length) { $cell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); } $input .val( chkd ? v + (o.exactMatch ? '=' : '') : '' ) .trigger( !c.$table[0].hasInitialized || notrigger ? '' : 'search' ); if (o.valueToHeader) { // add current color to the header cell $cell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); } else { // current color to span in cell $cell.find('.currentColor').html(t); } // update sticky header cell if ($shcell.length) { $shcell.find('.colorpicker').val(v)[0].disabled = (o.disabled || !chkd); if (o.addToggle) { $shcell.find('.toggle')[0].checked = chkd; } if (o.valueToHeader) { // add current color to the header cell $shcell.closest('thead').find('th[data-column=' + indx + ']').find('.curcolor').html(t); } else { // current color to span in cell $shcell.find('.currentColor').html(t); } } }; $color.remove(); if (colorSupported) { t = '' + indx + Math.round(Math.random() * 100); // add HTML5 color picker t = '
' + (o.addToggle ? '
' : '') + '' + (o.valueToHeader ? '' : '(#000000)') + '
'; $cell.html(t); // add span to header for the current color value - only works if the line in the updateColor() function is also un-commented out if (o.valueToHeader) { $cell.closest('thead').find('th[data-column=' + indx + ']').find('.tablesorter-header-inner').append(''); } $cell.find('.toggle, .colorpicker').bind('change', function(){ updateColor( $cell.find('.colorpicker').val() ); }); // hidden filter update namespace trigger by filter widget $input = $cell.find('input[type=hidden]').bind('change' + c.namespace + 'filter', function(){ updateColor( this.value ); }); // update slider from hidden input, in case of saved filters c.$table.bind('filterFomatterUpdate', function(){ updateColor( $input.val(), true ); ts.filter.formatterUpdated($cell, indx); }); // on reset $cell.closest('table').bind('filterReset', function(){ // just turn off the colorpicker if (o.addToggle) { $cell.find('.toggle')[0].checked = false; } // delay needed because default color needs to be set in the filter // there is no compare option here, so if addToggle = false, // default color is #000000 (even with no value set) setTimeout(function(){ updateColor(); }, 0); }); // has sticky headers? c.$table.bind('stickyHeadersInit', function(){ $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx); $shcell .html(t) .find('.toggle, .colorpicker').bind('change', function(){ updateColor( $shcell.find('.colorpicker').val() ); }); updateColor( $shcell.find('.colorpicker').val() ); }); updateColor( o.value ); } return colorSupported ? $cell.find('input[type="hidden"]') : $(''); } }); })(jQuery);