Search code examples
tablesorter

Data attribute for (Mottie) Tablesorter filter_selectSource


I have a dynamic table which can contain a status column that can contain a predefined list of status, for example:

0: closed
1: Open
2: Pending
3: ...

The status label is displayed in the table, but the id number is used for actual filtering. I successfully applied tablesorter filter-select to display a select filter, but it either display label (won't filter) or id (not pretty).

I could fix this using filter_selectSource inside javascript, but since my table is dynamic and displayed using Handlebar, I'm looking for an html solution using data attributes.

Is there a data attribute that could be used to set the filter select label/value, similar to how data-text can be used to define unparsed text? Or is there a way to define a custom parser for filter that would return a label/value combo as an array for example?


Solution

  • Based on Mottie reply and tablesorter.filter.getOptions source, I came up with this. Adding the filter-metaselect class to my column(s) th enables the data-value attribute in the cell td to be used as the select options. The parsed/unparsed text can still be used. Note that the child part of getOptions has been omitted since I'm not using feature at the moment.

    Table Cell :

    <td data-value="1">
      Projet actif
    </td>
    

    Select option :

    <option value="1" parsed="projet actif" data-function-name="1">Projet actif</option>
    

    Javascript:

    filter_selectSource: {
        ".filter-metaselect": function (table, column, onlyAvail) {
            table = $( table )[0];
            var rowIndex, tbodyIndex, len, row, cache, indx, child, childLen, colData,
                c = table.config,
                wo = c.widgetOptions,
                arry = [];
            for ( tbodyIndex = 0; tbodyIndex < c.$tbodies.length; tbodyIndex++ ) {
                cache = c.cache[tbodyIndex];
                len = c.cache[tbodyIndex].normalized.length;
                // loop through the rows
                for ( rowIndex = 0; rowIndex < len; rowIndex++ ) {
                    // get cached row from cache.row ( old ) or row data object
                    // ( new; last item in normalized array )
                    row = cache.row ?
                        cache.row[ rowIndex ] :
                        cache.normalized[ rowIndex ][ c.columns ].$row[0];
                    // check if has class filtered
                    if ( onlyAvail && row.className.match( wo.filter_filteredRow ) ) {
                        continue;
                    }
    
                    // Get the column data attributes
                    if (row.getElementsByTagName('td')[column].getAttribute('data-value')) {
                        colData = row.getElementsByTagName('td')[column].getAttribute('data-value');
                    } else {
                        colData = false;
                    }
    
                    // get non-normalized cell content
                    if ( wo.filter_useParsedData ||
                        c.parsers[column].parsed ||
                        c.$headerIndexed[column].hasClass( 'filter-parsed' ) ) {
    
                        arry[ arry.length ] = {
                            value : (colData) ? colData : cache.normalized[ rowIndex ][ column ],
                            text : cache.normalized[ rowIndex ][ column ]
                        };
    
                        // child row parsed data
                        /* TODO */
                    } else {
    
                        arry[ arry.length ] = {
                            value : (colData) ? colData : cache.normalized[ rowIndex ][ c.columns ].raw[ column ],
                            text : cache.normalized[ rowIndex ][ c.columns ].raw[ column ]
                        };
    
                        // child row unparsed data
                        /* TODO */
                    }
                }
            }
    
            // Remove duplicates in `arry` since using an array of objects
            // won't do it automatically
            var arr = {};
    
            for ( var i=0, len=arry.length; i < len; i++ )
                arr[arry[i]['text']] = arry[i];
    
            arry = new Array();
            for ( var key in arr )
                arry.push(arr[key]);
    
            return arry;
        }
    }