AlphabetSearch unknown feature

AlphabetSearch unknown feature

jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

Integral to each of my dataTables is the alphabetSearch feature. I added the following to the global extend defaults...

layout: { top1: 'alphabetSearch', top2: 'paging', bottom: 'info' },
Doing causes a unknown feature error. There is obviously something that I am not doing but I have no clue. I copied the code directly from the three part instructions.

For a test example use this URL: https://www.trgrayson.org/cemeteries-dt

For a live example using dataTable v1 just remove the -dt from the above url.

Thanks in advance for all your help.

jdadwilson

Answers

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    The domain name isn't resolving for me I'm afraid. Is there a typo in it perhaps?

    The error suggests that you aren't loading the AlphabetSearch Javascript file. Or perhaps it is an old one that is being loaded?

    Allan

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    My bad... URL should be... https://www.txgrayson.org/cemeteries-dt

  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948

    Looks like you are loading alphabet search library twice:

    <!-- Primary javascripts for all pages -->
            <!-- dataTables java Script -->
            <script src="java/vendor/datatables-2.0.js"></script>       
            <script src="java/vendor/alphabet_Search-2.0.js"></script>
            <script src="https://code.jquery.com/jquery-migrate-1.4.1.js"></script> 
            
    <!-- Leaflet javascript file v1.9.3 -->
    <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
    
    <!-- Special bootBox Script -->
    <script src="https://www.txgrayson.org/java/vendor/bootbox.min.js"></script>
    <script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js'></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js" type="text/javascript"></script>
    
    <!-- Load the java functions -->
    <script src="java/functions_java/_alphabet_Search.js"></script>
    

    The second one is 1.0.0 which might not work with DT 2.0. Remove it to see if that fixes the problem. If not then tell us where to find the Datatables init code and where you are setting the defaults.

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    I moved the alphabet_Search-x.0 functions from the java_functions directory to the vendor directory on my local system but forgot to delete the file from the main site java_functions directory.

    The DT init code is in the cemeteries-dt.js file.

    The expand default code is at the bottom of the alphabet_Search-2.0.js file. Probably not the best place so add it. Any suggestions as to where.

    This is the code for loading js files. It is a little complex given that I am upgrading a lot of modules to dT-2.0.

    <!-- Primary javascripts for all pages -->
    <?php
    //  Load associated java script for calling script
    $script_Array = explode("/", $_SERVER['SCRIPT_FILENAME']);
    $script_Name  = $script_Array[count($script_Array) - 1];
    $this_Script  = str_replace('.php', '', $script_Name);
    
    //  Load js files based on module name
    switch ( $this_Script ) {
    
        //  Load files for new dataTable structure
        case 'cemeteries-dt':
            ?>
            <!-- dataTables java Script -->
            <script src="java/vendor/datatables-2.0.js"></script>       
            <script src="java/vendor/alphabet_Search-2.0.js"></script>
            <script src="https://code.jquery.com/jquery-migrate-1.4.1.js"></script> 
            <?php
            break;
    
        default:
    
            //  Load files for old dataTables structure
            ?>
            <!-- jQuery 1.12.0 Script -->
            <script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
            
            <!-- Bootstrap 3.3.6 Script -->
            <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
            
            <!-- dataTables 1.10.20 Script -->
            <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script><!-- v22 -->
            <script src="java/vendor/alphabet_Search-1.0.js"></script>  
    
            
            <!-- dataTables colReorder & tableTools Scripts -->
            <script src="https://cdn.datatables.net/colreorder/1.5.0/js/dataTables.colReorder.min.js"></script>
            <script src="<?php echo SERVER_PATH; ?>java/vendor/jquery.dataTables.tableTools.2.2.1-dev.js"></script>
            <script src="//cdn.datatables.net/select/1.3.1/js/dataTables.select.min.js"></script>
            
            <?php
    }   
    
    <?php
    >
    ?>
    
    
    <!-- Leaflet javascript file v1.9.3 -->
    <script src="https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" integrity="sha256-WBkoXOwTeyKclOHuWtc+i2uENFpDZ9YPdf5Hf+D7ewM=" crossorigin=""></script>
    
    <!-- Special bootBox Script -->
    <script src="<?php echo SERVER_PATH; ?>java/vendor/bootbox.min.js"></script>
    <script src='https://api.mapbox.com/mapbox.js/plugins/leaflet-fullscreen/v1.0.1/Leaflet.fullscreen.min.js'></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-ajax/2.1.0/leaflet.ajax.min.js" type="text/javascript"></script>
    
    <!-- Load the java functions -->
    <?php
    $dir = "java/functions_java/";
    $arr = scandir($dir);
    foreach ($arr as &$file) {
        if (strpos($file, ".js") !== false) {
            echo '<script src="' . $dir . $file . '"></script>';
            echo PHP_EOL;
        }
    }
    
    // Specific scripts for each module
    switch ($script_Name) {
        case 'census.php': ?>
            <script src="//cdn.datatables.net/plug-ins/1.10.12/api/sum().js"></script><?php echo PHP_EOL;
            break;
    
        case 'booksonline.php': ?>
            <script src="<?php echo SERVER_PATH; ?>java/vendor/tjpzoom.js"></script><?php echo PHP_EOL; ?>
            <script src="<?php echo SERVER_PATH; ?>java/vendor/tjpzoom_config_Grayson.js"></script><?php echo PHP_EOL;
            break;
    
        case 'article.php':
        case 'cemetery.php':
        case 'church.php':
        case 'memorial.php':
        case 'marker.php':
        case 'school.php':
        case 'town.php':
        case 'maps.php':
        case 'map-all.php':
        case 'neighbors.php':
        case 'view_large_map.php':
                ?><script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAXPvUkWaeVfdwQjtlBZwlZND0-0bcYpZs" defer></script><?php echo PHP_EOL;
                ?><script src="<?php echo SERVER_PATH; ?>java/initMaps.js?v=221211"></script><?php echo PHP_EOL;
                ?><script src="<?php echo SERVER_PATH; ?>java/vendor/mapper.js"></script><?php echo PHP_EOL;
            break;
    } ?>
    
    <!--Load the javascript for the active module -->
    <script src="<?php echo SERVER_PATH; ?>java/<?php echo $this_Script; ?>.js"></script><?php echo PHP_EOL; ?>
    
    <script>
        $('body').on('touchstart.dropdown', '.dropdown-menu', function(e) {
            e.stopPropagation();
        });
    </script>
    
    <!--
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCdWU4-rkKc7qeTcBnt0uF_aD2_75ElWhI" defer></script>
    <?php //echo PHP_EOL; ?>
    -->
    
  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948

    This error is showing in the browser's console.

    Uncaught TypeError: Cannot read properties of undefined (reading 'apply')

    Along with this alert.

    DataTables warning: table id=mainTable - Unknown feature: alphabetSearch

    I believe these two errors are caused by setting the defaults, ie:

        //  Extend certain elements by default
        $.extend( $.fn.dataTable.defaults, {
    
            layout: {
                top1:   'alphabetSearch',
                top2:   'paging',
                bottom: 'info'
            },
    
            paging: {
                type: 'full_numbers'
            },
    
            language: {
                paginate: {
                    first:      'First',
                    previous:   'Prev',
                    next:       'Next',
                    last:       'Last'
                }
            },
    
            ordering: false,
    
            seaching: false
        } );
    

    Inside alphabet_Search-2.0.js before the alphabet search feature has completed initialization and has returned. Move that code to the top of cemeteries-dt.js so it executes after the alphabet search has initialized, for example:

    "use strict";
    //* <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Variables
    
    let oTable;
    let newURL =  window.SERVER_PATH;
    
        //  Extend certain elements by default
        $.extend( $.fn.dataTable.defaults, {
    
            layout: {
                top1:   'alphabetSearch',
                top2:   'paging',
                bottom: 'info'
            },
    
            paging: {
                type: 'full_numbers'
            },
    
            language: {
                paginate: {
                    first:      'First',
                    previous:   'Prev',
                    next:       'Next',
                    last:       'Last'
                }
            },
    
            ordering: false,
    
            seaching: false
        } );
    

    Using the browser's network inspector the JSON response has this for the row data:

    aaData: [
      {
        "num_Cems": 117,
        "num_Ints": "76,036",
        "num_TsIg": "225",
        "num_PsIg": "23",
        "num_ObIg": "0",
        "num_Obit": "311",
        "num_Gpsc": "0"
      }
    ]
    

    But you have defined columns.data like this:

            columns: [  { data: 'cem_name',   className: 'udatal', orderable: false, visible: true },
                        { data: 'cem_county', className: 'udatal', orderable: false, visible: true },
                        { data: 'cem_count',  className: 'udatar', orderable: false, visible: true },
                        { data: 'cem_photos', className: 'udatac', orderable: false, visible: true },
                        { data: 'cem_id',     className: 'udatal', orderable: false, visible: false } ],
    

    They don't match. Possibly the URL is wrong and is fetching the wrong data.

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    I moved the default code to the top of the cemeteries-dt.js file as suggested.

    Still getting the same problem.

    Is there a better place to include the expand defaults code? The purpose of the code is to establish defaults for the dataTables initialization. This site has 53 instances in 27 modules of dataTables. The code should be placed such that it is only needed once not in each of the 27 modules. Could it be placed in a file by itself and loaded after the datatables-2.0.js module but before the cemeteries-dt.js module?

    As for the aaData vs the columns... The aaData is for the stats of the cemeteries which displays above the table and load after the page is loaded. Changing the top1 default to null make everything work fine.

    jdadwilson

  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948

    Is there a better place to include the expand defaults code? The purpose of the code is to establish defaults for the dataTables initialization.

    The defaults code needs to execute after datatables.js and alphabetSearch.js are loaded and before any of the Datatables requiring the default settings are initialized.

    I built a simple test case:
    https://live.datatables.net/giwezonu/1/edit

    This fails with the same error. It seems the CDN link in the blog points to the 1.0.0 version.

    I updated the test case to use the CDN for the 1.1.0 version:

    <script src="https://cdn.datatables.net/plug-ins/2.0.8/features/alphabetSearch/dataTables.alphabetSearch.js"></script>
    

    And it works:
    https://live.datatables.net/mutabape/1/edit

    Try downloading the working CDN and loading it on your page.

    @allan will need to update the blog docs.

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    Alpha bar loads but all letters have 0 count.

    I also made a new file for datatables-globals.js. Load order is...

    datatables-2.0.js
    datatables-globals.js
    alphabetSearch-2.0.js
    

    This works fine.

    jdadwilson

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    Still looking for a reason why the alphabetSearch letter count is zero for all letters...

    txgrayson.org/cemeteries-dt

  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948

    According to this thread you will need to use this.api().alphabetSearch.recalc() in initComplete. The problem is that the alphabetSearch plugin is initialized with the Datatable before the Ajax response fills the table.

    Using this in the console:

    $('#mainTable').DataTable().alphabetSearch.recalc();
    

    resolves the issue:

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    Thanks, it works... but it does raise a question. Is the need for the recalc in the initComplete because of dataTables v2.0? I did not have to do this with v1.0.

  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948
    edited July 3

    The need is due to the timing of initializing the alphabetSearch before the Ajax response. There is no data in the Datatable when alphabetSaerch initializes because the asynchronous ajax response hasn't returned yet.

    I built a test case with the old 1.0.0 alphabetSearch and DT 1.13.11 using ajax loaded data:
    https://live.datatables.net/socirone/6/edit

    The initComplete option is commented out. Due to ajax loaded data it shows 0 records for all letters. Uncomment initComplete and you will see it work properly. For wexample:
    https://live.datatables.net/bogavuti/1/edit

    Did your DT 1.x use HRMl or Javascript sourced data?

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    Both versions use js.

    You can see the difference in this URL...
    txgrayson.org/cemeteries for v1 and
    txgrayson.org/cemeteries-dt for v2.

  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948

    Your v1 version has this initComplete function:

    initComplete: function() { hide_TableAlphaLtrs(this, oTable); },
    

    That function calls that.api().alphabetSearch.recalc();:

    function hide_TableAlphaLtrs ( that, oTable ) {
        let tableInfo = oTable.page.info();
        console.log('Len: ' + tableInfo.length);
        console.log('Tot: ' + tableInfo.recordsTotal);
        
        if (tableInfo.recordsTotal <= tableInfo.length) {
            $('#myAlphabet').hide();
        } else {
            that.api().alphabetSearch.recalc();
            $('#myAlphabet').show();
        }
        oTable.draw();
    }
    

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    So the question is... how do I change the function (and call) in the initComplete to work with dt 2.0? This is call code...

    initComplete: function( oTable ) {
        hide_alphaLtrs( oTable );
    },
    

    And this is the function...

    function hide_alphaLtrs ( sTable ) {
        let tableInfo = sTable.page.info();
        if (tableInfo.recordsTotal <= tableInfo.length) {
            $('div.alphabet').hide();
        } else {
            sTable.api().alphabetSearch.recalc();
            $('#div.alphabet').show();
        }
        sTable.draw();
    }
    

    This doesn't work given that the recalc is never done.

    I have a similar function in the drawCallback area that does a hide/show depending on the recordsDisplay vs length values.

    Thanks for all your help. It is greatly appreciated!!!
    jdadwilson

  • kthorngrenkthorngren Posts: 21,322Questions: 26Answers: 4,948
    edited July 3

    Try this:

    initComplete: function( ) {
        hide_alphaLtrs( this.api() );
    },
    

    Its not guaranteed that the variable ( oTable ) assignment of the Datatables initialization object is complete when initComplete executes. It's like which comes first the chicken or the egg :smile:

    this.api() gives access to the Datatables API in initComplete.

    Kevin

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    That worked!!! I changed the function to...

    function hide_alphaLtrs ( thisApi ) {
        var tableInfo = thisApi.page.info();
        if (tableInfo.recordsTotal <= tableInfo.length) {
            $('div.alphabet').hide();
        } else {
            thisApi.alphabetSearch.recalc();
            $('#div.alphabet').show();
        }
        thisApi.draw();
    }
    

    I'll change the hide_pagingInfo function in the drawCallback area to see what happens there.

    Thanks much!!
    jdadwilson

  • jdadwilsonjdadwilson Posts: 127Questions: 30Answers: 1

    Changes to the hide_pagingInfo function worked great also. You can see the results here...

    txgrayson.org/cemeteries-dt

    Select the letter 'T' and you will note that the paging info does not show. Select another letter (with a count > 16) or 'All' and the paging displays again.

    This is probably a small issue, but an important one for the UI. It seems weird to display the paging info if there are fewer records than the lengthMenu number. Likewise if the recordTotal is less than the lengthMenu why display the Alpha bar.

    Thanks much
    jdadwilson

    p.s. On to my next question. (see next post about globals)

Sign In or Register to comment.