Forum Replies Created

Viewing 15 replies - 1 through 15 (of 39 total)
  • Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    yes, I forgot: You are the technical hotline, too. Perhaps there is a simple way to make it proof (e.g. additional info, syntax validation etc.). For me it’s proof enough ;). Thanks again.

    Have a nice day
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    you are right: changing the original code is be the best solution. But I dont’t want to change original code that might lead to unwanted side effects. This is why I am using JS in many cases. Furthermore errors appear on client side and NOT on the server. And – for me – it’s very flexibal, too.

    Confounding “Custom CSS” and “Custom Commands” should not be your problem. You cannot catch all user errors. All in all TablePress is idiot-proof ;).

    Cheers
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    that would be great, really! Perhaps I could create a JS script solving this “problem” but I don’t like “miracles” to make it working. YOU are the expert!

    Thank you πŸ™‚

    Regards
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    what do you handle with inputs that textareas do not support?

    The workaround with copy/paste requires a copy to keep the linebreaks. On the other side copying formatted code includes indentations inline. Do you know if there a way to include a file with the code into DataTables?

    Cheers
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    There perhaps is a workaround:
    https://stackoverflow.com/questions/27290693/how-to-use-rowspan-and-colspan-in-tbody-using-datatable-js/34012324#34012324

    This coueld be useful for your TablePress Plugin.

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    The DataTables JS library simply doesn’t support tables with combined cells (via colspan or rowspan).

    Found this:
    https://wordpress.org/support/topic/datetable-functions-not-visible-if-using-colspan/#post-9610057

    The search input field is shown here though colspan is set. I believe it works because colspan is within thead and not tbody.

    Regards
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    GOT IT! The “Next” button works now.

    Solution:
    You must store the current filter info values of searchColumns, searchRegex and searchSmart. I simply added a dynamically created property to FILTER_INFO[<table-id>].

    Now the code can be read straight forward and should do the job (please please).

    // empty last filter
    let dataTable = jTable
        .DataTable()
        .columns( info.lastSearch.searchColumns )
        .search( '', info.lastSearch.searchRegex, info.lastSearch.searchSmart )
        .draw()
        ;
    
    // search within selected column only
    if (searchColumns.length > 0){
        dataTable = dataTable.columns( searchColumns );
    }
    
    // perform search (at this point with or without searchColumn indices)
    dataTable
        .search( filterValue, searchRegex, searchSmart )
        .draw()
        ;
    
    // store current filter data
    info.lastSearch = {
        searchColumns: searchColumns,
        searchRegex:   searchRegex,
        searchSmart:   searchSmart,
    };
    
    // clear search input
    jInput.val('').keyup();

    Cheers
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    That’s ok. I will look for a solution and post it here.

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    I believe that the last .search() call causes the issue.

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    there still is a bug:
    Currently there are 492 entries. When you select e.g. the first entry you wil get 284 hits. After clicking the “Next” link the compleate is gone and the 492 entries are back.

    See:
    http://www.regionalmuseum-alsfeld.de/dokumente/lexika/bauwerke/

    This is the responsible code:

    let jTable = $('#tablepress-' + tableID);
    let filterValue = 'blah';
    
    if (searchColumns.length > 0){// search single columns
        //jInput.keyup();
        jTable
            .DataTable()
            .search( '' )// remove global columns filter (empties search input field, too)
            .columns( searchColumns )// search within single column only
            .search( filterValue, searchRegex, searchSmart )
            .draw()
            .search( '', searchRegex, searchSmart )// remove single columns filter (but do NOT redraw table)
            ;
    }

    I know that this is my problem with DataTables but maybe YOU can help me :).

    Cheers
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    thank you for the fast response. That doesn’t matter (25 table rows). The table itself works which is more important.

    Have a nice week πŸ™‚
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    See:
    https://tablepress.org/demo/ -> 2nd table.

    If “filter/search” is enabled the search input is missing here, too.

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    that’s it! Thank your very much.

    Remark:
    A further advantage of taking use of the DataTable API is that regular expressions are completely hidden for the user: The search input field will not be filled by selected search terms.

    Once again the code. Now with a short description of the data structure. Removed one bug.

    /*
        FILTER_INFO['table-id-example'] = {
            filterTitle: 'Predef. Search:<br/>', // String (required):  Title. May be empty.
            searchColumns: [ ]                   // Int    (required):  Default col filter index array.
                                                 //                     [ ] := filter all columns
            searchRegex: false,                  // Bool   (required):  Default search regex
            searchSmart: true,                   // Bool   (required):  Default search smart
            options: [                           // Array  (required)
                {
                    name: 'name',                // String (required):  Option name
                    value: 'value',              // String (optional):  Option value. If not set this option will be disabled => "delimiter".
                    searchColumns: '-1',         // Int    (optional):  Overwrites default searchColumns
                    searchRegex: false,          // Bool   (optional):  Overwrites default searchRegex
                    SearchSmart: true            // Bool   (optional):  Overwrites default searchSmartt
                },
    // more options
    //          { ... }
    //          { ... }
            ]
        };
    */
    
    jQuery(document).ready(function($) {
    
        const FILTER_INFO = [];
    
        FILTER_INFO['Dokumente_Lexika_Bauwerke'] = {
            filterTitle: 'Vordefinierte Suche:<br/>',
            searchColumns: [ 0 ],// -1 := filter all columns
            searchRegex: false,
            searchSmart: true,
            options: [
                { name: '[Keine]',          value: '' },
                { name: 'β€” Orte β€”' },
                { name: 'Alsfeld',          value: 'Alsfeld,' },
                { name: 'Altenburg',        value: 'Altenburg,' },
                { name: 'Angenrod',         value: 'Angenrod,' },
                { name: 'Berfa',            value: 'Berfa,' },
                { name: 'Billertshausen',   value: 'Billertshausen,' },
                { name: 'Eifa',             value: 'Eifa,' },
                { name: 'Elbenrod',         value: 'Elbenrod,' },
                { name: 'Eudorf',           value: 'Eudorf,' },
                { name: 'Fischbach',        value: 'Fischbach,' },
                { name: 'Hattendorf',       value: 'Hattendorf,' },
                { name: 'Heidelbach',       value: 'Heidelbach,' },
                { name: 'Leusel',           value: 'Leusel,' },
                { name: 'Liederbach',       value: 'Liederbach,' },
                { name: 'Lingelbach',       value: 'Lingelbach,' },
                { name: 'MΓΌnch-Leusel',     value: 'MΓΌnch-Leusel,' },
                { name: 'Reibertenrod',     value: 'Reibertenrod,' },
                { name: 'Schwabenrod',      value: 'Schwabenrod,' },
                { name: 'β€” Bauwerke β€”' },
                { name: 'Regionalmuseum',   value: 'Regionalmuseum', searchColumns: [ 1 ] },
                { name: 'β€” Sonstiges β€”' },
                { name: 'Routen',           value: 'Route',          searchColumns: [ 1 ] },
            ]
        };
        FILTER_INFO['Dokumente_Lexika_Personen_Buergermeister'] = {
            filterTitle: 'Vordefinierte Suche:<br/>',
            searchColumns: [ 1 ],//-1 := filter all columns
            searchRegex: true,
            searchSmart: true,
            options: [
                { name: '[Keine]',          value: '' },
                { name: 'β€” Jahrhunderte β€”' },
                { name: '2001 – 2100',      value: '(.*(20(0[1-9]|[1-9]\\d)|2100).*)' },
                { name: '1901 – 2000',      value: '(.*(19(0[1-9]|[1-9]\\d)|2000).*)' },
                { name: '1801 – 1900',      value: '(.*(18(0[1-9]|[1-9]\\d)|1900).*)' },
                { name: '1701 – 1800',      value: '(.*(17(0[1-9]|[1-9]\\d)|1800).*)' },
                { name: '1601 – 1700',      value: '(.*(16(0[1-9]|[1-9]\\d)|1700).*)' },
                { name: '1501 – 1600',      value: '(.*(15(0[1-9]|[1-9]\\d)|1600).*)' },
                { name: '1401 – 1500',      value: '(.*(14(0[1-9]|[1-9]\\d)|1500).*)' },
                { name: '1301 – 1400',      value: '(.*(13(0[1-9]|[1-9]\\d)|1400).*)' },
    //            { name: 'β€” Territorien β€”' },
    //            { name: '1567 – 1604',      value: '(.*((15(6[7-9]|[7-9]\\d))|(160(0-4))).*)' },
    //            { name: '1604 – 1806',      value: '(.*((16(0[4-9]|[1-9]\\d))|(17\\d\\d)|(180[0-6])).*)' },
    //            { name: 'β€” Sonstiges β€”' },
    //            { name: 'bis 1574',         value: '(.*((13\\d\\d|14\\d\\d)|(15([0-6]\\d|7[0-4])).*))' },
            ]
        };
    
        /**
         * Creates and adds a <select> tag with <option> tags under the search input field.
         */
        function addFilterSelectTagToDOM( jWrapper, tableID ){
    
            let filterSelectTag = '';
    
            // build <option> tags
            let options = FILTER_INFO[tableID].options;
            for (let i = 0; i < options.length; i++) {
    
                let optionValue = options[i].name;
                let optionAttributes = (options[i].hasOwnProperty('value'))
                    ? ' value="' + options[i].value + '"'
                    : ' disabled="disabled"'
                    ;
    
                filterSelectTag += '<option' + optionAttributes + '>' + optionValue + '</option>';
            }
    
            filterSelectTag = '<select>' + filterSelectTag + '</select>';
    
            // append HTML
            jWrapper.find('.dataTables_filter').after(
                '<div' +
                    ' class="predefined-filter"' +
                    ' style="clear: both; display: block; text-align: right;"' +
                '>' +
                    FILTER_INFO[tableID].filterTitle + filterSelectTag +
                '</div>'
            );
    
            let jSelect = jWrapper.find('.predefined-filter select');
            return jSelect;
        }
    
        /**
         * See: https://datatables.net/examples/api/regex.html
         *      https://datatables.net/reference/api/columns().search()
         */
        function setSearchTableCallbacks( tableID, jInput, jSelect ){
    
            // Search Input field key down => set select option 0
            jInput.keydown( function(){
                if (jSelect.prop('selectedIndex') != '0')
                    jSelect.prop('selectedIndex', '0').change();
            });
    
            // Search Input field key down => run search (will be triggered ALREADY)
            //jInput.keyup( function(){ ... });
    
            // Option change => run search
            jSelect.change( function(){
                return function(){
                    let info = FILTER_INFO[tableID];
                    let option = info.options[ jSelect.prop('selectedIndex') ];
                    
                    // use specifix option property or default options property
                    let searchColIdx = option.hasOwnProperty('searchColumns') ? option.searchColumns : info.searchColumns;
                    let searchRegex  = option.hasOwnProperty('searchRegex')     ? option.searchRegex     : info.searchRegex;
                    let searchSmart  = option.hasOwnProperty('searchSmart')     ? option.searchSmart     : info.searchSmart;
    
                    let jTable = $('#tablepress-' + tableID);
                    let filterValue = $(this).children(":selected").val();
    
                    if (searchColIdx.length > 0)// search single columns
                        jTable
                            .DataTable()
                            .search( '' )// remove global columns filter (empties search input field, too)
                            .columns( searchColIdx )// search within single column only
                            .search( filterValue, searchRegex, searchSmart )
                            .draw()
                            .search( '' )// remove single columns filter (but do NOT redraw table)
                            ;
                    else// search all columns
                        jTable
                            .DataTable()
                            .search( filterValue, searchRegex, searchSmart )
                            .draw()
                            .search( '' )// remove global columns filter (but do NOT redraw table)
                            ;
                };
            }());
        }
    
        /**
         * 
         */
        function main() {
            for (let tableID in FILTER_INFO){
                if (FILTER_INFO.hasOwnProperty(tableID)) {
        
                    let jWrapper = $('#tablepress-' + tableID + '_wrapper');
                    if (jWrapper.length) {
    
                        let jInput = jWrapper.find('.dataTables_filter > label > input[type="search"]');
                        let jSelect = addFilterSelectTagToDOM( jWrapper, tableID );
    
                        setSearchTableCallbacks( tableID, jInput, jSelect );
                    }
                }
            }
        }
    
        main();
    });

    Best wishes
    Sascha

    Thread Starter sesselschwitzer

    (@sesselschwitzer)

    Hello Tobias,

    this simple link has answered my question how to select the table columns to be included during search with regex:
    https://datatables.net/examples/api/regex.html

    The magic lines:

    $(table-id)
    	.DataTable()
    	.column( columnIndex )// searches within this column only
    	.search( filterValue, useRegexSearch, useSmartSearch )
    	.draw()
    	;

    Well, it seems to be restricted to search one or all columns and nothing between but – in my case – it’s ok.

    Awesome:
    – The search input still works without regex!
    – No extra visible column (hidden by CSS) required

    The code:

    jQuery(document).ready(function($) {
    
        const FILTER_INFO = [];
    
        FILTER_INFO['Dokumente_Lexika_Bauwerke'] = {
            filterTitle: 'Vordefinierte Suche:<br/>',
            filterColIdx: 0,// -1 := filter all columns
            searchRegex: false,
            searchSmart: true,
            options: [
                [ '[Leer]',         '' ],
                [ 'β€” Orte β€”',       null ],
                [ 'Alsfeld',        'Alsfeld,' ],
                [ 'Altenburg',      'Altenburg,' ],
                [ 'Angenrod',       'Angenrod,' ],
                [ 'Berfa',          'Berfa,' ],
                [ 'Billertshausen', 'Billertshausen,' ],
                [ 'Eifa',           'Eifa,' ],
                [ 'Elbenrod',       'Elbenrod,' ],
                [ 'Eudorf',         'Eudorf,' ],
                [ 'Fischbach',      'Fischbach,' ],
                [ 'Hattendorf',     'Hattendorf,' ],
                [ 'Heidelbach',     'Heidelbach,' ],
                [ 'Leusel',         'Leusel,' ],
                [ 'Liederbach',     'Liederbach,' ],
                [ 'Lingelbach',     'Lingelbach,' ],
                [ 'MΓΌnch-Leusel',   'MΓΌnch-Leusel,' ],
                [ 'Reibertenrod',   'Reibertenrod,' ],
                [ 'Schwabenrod',    'Schwabenrod,' ],
                [ 'β€” Bauwerke β€”',   null ],
                [ 'Regionalmuseum', 'Regionalmuseum' ],
                [ 'β€” Sonstiges β€”',  null ],
                [ 'Routen',         'Route' ],
            ]
        };
        FILTER_INFO['Dokumente_Lexika_Personen_Buergermeister'] = {
            filterTitle: 'Vordefinierte Suche:<br/>',
            filterColIdx: 1,//-1 := filter all columns
            searchRegex: true,
            searchSmart: true,
            options: [
                [ '[Leer]',   '' ],
                [ 'β€” Jahrhunderte β€”',  null ],
                [ '2001 – 2100',      '(.*(20(0[1-9]|[1-9]\\d)|2100).*)' ],
                [ '1901 – 2000',      '(.*(19(0[1-9]|[1-9]\\d)|2000).*)' ],
                [ '1801 – 1900',      '(.*(18(0[1-9]|[1-9]\\d)|1900).*)' ],
                [ '1701 – 1800',      '(.*(17(0[1-9]|[1-9]\\d)|1800).*)' ],
                [ '1601 – 1700',      '(.*(16(0[1-9]|[1-9]\\d)|1700).*)' ],
                [ '1501 – 1600',      '(.*(15(0[1-9]|[1-9]\\d)|1600).*)' ],
                [ '1401 – 1500',      '(.*(14(0[1-9]|[1-9]\\d)|1500).*)' ],
                [ '1301 – 1400',      '(.*(13(0[1-9]|[1-9]\\d)|1400).*)' ],
                [ 'β€” Territorien β€”',  null ],
                [ '1567 – 1604',      '((15(6[7-9]|[7-9]\\d))|(160(0-4)))' ],
                [ '1604 – 1806',      '((16(0[4-9]|[1-9]\\d))|(180(0-6)))' ],
                [ 'β€” Sonstiges β€”',    null ],
                [ 'bis 1574',         '(15([0-6]\\d|7[0-4]))' ],
            ]
        };
    
        /**
         * Creates and adds a <select> tag with <option> tags under the search input field.
         */
        function addFilterSelectTagToDOM( jWrapper, tableID ){
    
            let filterSelectTag = '';
    
            // build <option> tags
            let options = FILTER_INFO[tableID].options;
            for (let i = 0; i < options.length; i++) {
    
                var optionValue = options[i][0];
                var optionAttributes = (options[i][1] !== null)
                    ? ' value="' + options[i][1] + '"'
                    : ' disabled="disabled"'
                    ;
    
                filterSelectTag += '<option' + optionAttributes + '>' + optionValue + '</option>';
            }
    
            filterSelectTag = '<select>' + filterSelectTag + '</select>';
    
            // append HTML
            jWrapper.find('.dataTables_filter').after(
                '<div' +
                    ' class="predefined-filter"' +
                    ' style="clear: both; display: block; text-align: right;"' +
                '>' +
                    FILTER_INFO[tableID].filterTitle + filterSelectTag +
                '</div>'
            );
    
            let jSelect = jWrapper.find('.predefined-filter select');
            return jSelect;
        }
    
        /**
         * See: https://datatables.net/examples/api/regex.html
         */
        function setSearchTableCallbacks( tableID, jInput, jSelect ){
    
            // Search Input field key down => set select option 0
            jInput.keydown( function(){
                jSelect.prop('selectedIndex', 0).change();
            });
    
            // Search Input field key down => run search (will be triggered ALREADY)
            //jInput.keyup( function(){ ... });
    
            // Option click => empty input field
            jSelect.find('option').click( function(){
                jInput.val('').keyup();
            });
    
            // Option change => run search
            jSelect.change( function(){
                return function(){
                    let info = FILTER_INFO[tableID];
                    let jTable =  $('#tablepress-' + tableID);
                    let filterValue = $(this).children(":selected").val();
    
                    if (info.filterColIdx < 0)// search all columns
                        jTable
                            .DataTable()
                            .search( filterValue, info.searchRegex, info.searchSmart )
                            .draw()
                            ;
                    else
                       jTable
                            .DataTable()
                            .column( info.filterColIdx )// searches within this column only
                            .search( filterValue, info.searchRegex, info.searchSmart )
                            .draw()
                            ;
                };
            }());
        }
    
        /**
         * 
         */
        function main() {
            for (let tableID in FILTER_INFO){
                if (FILTER_INFO.hasOwnProperty(tableID)) {
        
                    let jWrapper = $('#tablepress-' + tableID + '_wrapper');
                    if (jWrapper.length) {
    
                        let jInput = jWrapper.find('.dataTables_filter > label > input[type="search"]');
                        let jSelect = addFilterSelectTagToDOM( jWrapper, tableID );
    
                        setSearchTableCallbacks( tableID, jInput, jSelect );
                    }
                }
            }
        }
    
        main();
    });

    If you find a solution to filter 2 to n-1 column: Please let me know.

    Regards and have a nice weekend πŸ™‚
    Sascha

Viewing 15 replies - 1 through 15 (of 39 total)