Search code examples
jquerytablesorter

From/To filter for numeric columns in jQuery Tablesorter?


Looking at this example:

http://mottie.github.io/tablesorter/docs/example-widget-filter-formatter-1.html

How can I set the From/To filter (with two text input fields) like in the last Date column but in a numbers only column, like Total column in that example above?

As in, I don't want the slider in the Total column, I want the two From/To fields instead. Is that possible? And how? Which plugin/widget do I need to use and with what parameters?

Thanks.


Solution

  • You will end up writing your own custom filter formatter to add two numeric input fields; it isn't that straight-forward, but most of the code from the jQuery UI datepicker (2 inputs) formatter can be copied & modified to suit your needs.

    In a future update, I plan to replace the filter_formatter functions with an option that only needs to return a query value for a column. This change will enable developers to build their own custom filter row with a custom UI and not be limited by the code available for the filter_formatter.


    Ok, here you go (demo)

    /*! Widget: filter formatter functions - created 6/24/2015 *//*
     * requires: tableSorter (FORK) 2.15+ and jQuery 1.4.3+
     *
     * number range - 2 number inputs
     */
    /*jshint browser:true, jquery:true, unused:false */
    /*global jQuery: false */
    ;(function($){
    "use strict";
    
    var ts = $.tablesorter || {},
    
    tsff = ts.filterFormatter = $.extend( {}, ts.filterFormatter, {
    
        /*************************\
        2 number inputs
        \*************************/
        inputs: function($cell, indx, defNumber) {
            var o = $.extend({
                // filter formatter options
                textFrom : 'from',
                textTo : 'to',
                from : 0, // "from" input
                to : 100, // "to" input
                callback: function($cell){}
            }, defNumber),
            closeNumber,
            $shcell = [],
            c = $cell.closest('table')[0].config,
            // Add a hidden input to hold the range values
            $input = $('<input class="numberRange" type="hidden">')
                .appendTo($cell)
                // hidden filter update namespace trigger by filter widget
                .bind('change' + c.namespace + 'filter', function(){
                    var v = this.value;
                    if (v.match(' - ')) {
                        v = v.split(' - ');
                        $cell.find('.numberTo').val(v[1]);
                        closeNumber(v[0]);
                    } else if (v.match('>=')) {
                        closeNumber( v.replace('>=', '') );
                    } else if (v.match('<=')) {
                        closeNumber( v.replace('<=', '') );
                    }
                }),
    
            // make sure we're using parsed numbers in the search
            $hdr = c.$headerIndexed[ indx ].addClass('filter-parsed'),
            // Add range picker
            t = '<label>' + o.textFrom + '</label><input type="number" class="numberFrom" placeholder="' +
                ($hdr.data('placeholderFrom') || $hdr.attr('data-placeholder-from') || c.widgetOptions.filter_placeholder.from || '') + '" />' +
                '<label>' + o.textTo + '</label><input type="number" class="numberTo" placeholder="' +
                ($hdr.data('placeholderTo') || $hdr.attr('data-placeholder-to') || c.widgetOptions.filter_placeholder.to || '') + '" />';
            $(t).appendTo($cell);
    
            closeNumber = function( selectedNumber ) {
                var range,
                    from = $cell.find('.numberFrom').val(),
                    to = $cell.find('.numberTo').val();
                range = from ? ( to ? from + ' - ' + to : '>=' + from ) : (to ? '<=' + to : '');
                $cell.add( $shcell )
                    .find('.numberRange').val(range)
                    .trigger('search');
    
                if (/<=/.test(range)) {
                    $cell.add( $shcell )
                        .find('.numberFrom').val( to || 0 ).end()
                        .find('.numberTo').val( to || 0 );
                } else if (/>=/.test(range)) {
                    $cell.add( $shcell )
                        .find('.numberFrom').val( from || 0 ).end()
                        .find('.numberTo').val( from || 0 );
                } else {
                    $cell.add( $shcell )
                        .find('.numberFrom').val( from || 0 ).end()
                        .find('.numberTo').val( to || 0 );
                }
    
                if (typeof o.callback === 'function') { o.callback($cell); }
            };
    
            $cell.add( $shcell )
                .find('.numberFrom')
                .val( o.from ).end()
                .find('.numberTo')
                .val( o.to ).end()
                .find('.numberFrom, .numberTo')
                .bind('change', function(){
                    closeNumber();
                });
    
            // update date compare from hidden input, in case of saved filters
            c.$table.bind('filterFomatterUpdate', function(){
                var val = $input.val() || '',
                    from = o.from,
                    to = o.to;
                // date range
                if (/\s+-\s+/.test(val)){
                    val = val.split(/\s+-\s+/) || [];
                    from = val[0] || '';
                    to = val[1] || '';
                } else if (/>=/.test(val)) {
                    // greater than date (to date empty)
                    from = val.replace(/>=/, '') || '';
                } else if (/<=/.test(val)) {
                    // less than date (from date empty)
                    to = val.replace(/<=/, '') || '';
                }
    
                $cell.add($shcell).find('.numberFrom').val( from || 0 );
                $cell.add($shcell).find('.numberTo').val( to || 0 );
                // give datepicker time to process
                setTimeout(function(){
                    closeNumber();
                    ts.filter.formatterUpdated($cell, indx);
                }, 0);
            });
    
            // has sticky headers?
            c.$table.bind('stickyHeadersInit', function(){
                $shcell = c.widgetOptions.$sticky.find('.tablesorter-filter-row').children().eq(indx).empty();
                $shcell.append(t);
    
                // add a jQuery datepicker!
                $shcell.find('.numberFrom').val( o.from );
                $shcell.find('.numberTo').val( o.to );
    
            });
    
            // on reset
            $cell.closest('table').bind('filterReset', function(){
                $cell.add($shcell).find('.numberFrom').val( o.from || 0 );
                $cell.add($shcell).find('.numberTo').val( o.to || 0 );
                setTimeout(function(){
                    closeNumber();
                }, 0);
            });
    
            // return the hidden input so the filter widget has a reference to it
            return $input.val( o.from ? ( o.to ? o.from + ' - ' + o.to : '>=' + o.from ) : (o.to ? '<=' + o.to : '') );
        }
    
    });
    
    })(jQuery);