0

I have a PHP page with an else statement that filters out data from a SQL database by user input; here is some pseudo code:

NextPage.php

    //Include database configuration file
    include('../dbConfig.php'); 

    if(isset($_POST['pageno']) || isset($_POST['FetchFilters'])) {

        $limit = 10;    
        $pageno = $_POST['pageno'];
        $offset = !empty($pageno) ? $pageno: 1;

        $SQL = "

            SELECT * FROM list WHERE wt >= 2.5

        ";

        if($pageno >= 1) {


            if(isset($_POST["shape"])) {

                $shape_filter = implode("','", $_POST["shape"]);

                $SQL .= "

                    AND stoneshape IN('".$shape_filter."') 

                ";
            }

            if(isset($_POST["color"])) {

                $color_filter = implode("','", $_POST["color"]);

                $SQL .= "

                    AND stonecolor IN('".$color_filter."')

                ";

            }

            $SQL .= "

                ORDER BY wt ASC
                LIMIT 
                    $offset,
                    $limit

            ";

            $result = mysqli_query($db, $SQL);

            $output = '';

            if(isset($_POST["shape"]) && isset($_POST["color"]) && $row = mysqli_fetch_array($result)) {

                while($row = mysqli_fetch_array($result)) {

                    $output .=  '

                        <div class="Listing">

                            <!-- landing page -->
                            <a href="#ItemPage" class="ItemLink">

                                //Item Information goes here

                            </a>

                        </div>

                    ';

                }

            }

        } else {

            $output = '

                <h1 class="Error">
                    NO DATA MATCHES THAT
                </h1>

            ';

        }

        echo $output;

    }

?>

Then I have an AJAX call that paginates when an image (with the ID of #Loader in inView); here is it's pseudo code:

InfiniteScroll.js

$(document).ready(function(){

    $('#Loader').on('inview', function(event, isInView) {

        if (isInView) {

            //Pagination    
            var nextPage = parseInt($('#pageno').val()) + 1;

            //Filters
            var shape = get_filter('shape');
            var color = get_filter('color');

            $.ajax({

                type: 'POST',
                url: 'vendors/php/NextPage.php',
                data: {
                    pageno: nextPage,
                    shape: shape,
                    color: color
                },
                async: true,
                cache: false,
                error: 

                    function(jqXHR, strError) {

                        if(strError == 'timeout') {

                            // Do something. Try again perhaps?
                            alert('Seems like there was an error loading the next page.');

                        }

                    },

                success: 

                    function(data) {

                        $('#Container').append(data); //Container where the NextPage.php data appends to
                        $('#pageno').val(nextPage);

                        if(data != '') { //Here is where my question lyes
                            $('.Error').hide();     //Else statement on NextPage.php should 'hide' as there is data to show
                            $('#Loader').show();    //Show image for pagination
                        } else {
                            $('.Error').show();     //Else statement on NextPage.php should 'show' as there is data to show
                            $('#Loader').hide();    //Hide image for pagination 
                        }

                    },

                timeout: 3000

            });

        }

    });

});

//Gets values of filters for filters variables
function get_filter(class_name) {

    var filter = [];

    $('.'+class_name+':checked').each(function() {
        filter.push($(this).val());
    });

    return filter;

}

My problem is that the else statement on NextPage.php is treated as data so I don't know how to check if $row is showing. I want the .Error class to hide when there are $row(s) being shown else hide #Loader and show .Error. How can I check for .Error in my AJAX call?

  • You should consider returning your data as a JSON, and not as HTML. Then use a template to add it to the site. To return an error check this https://stackoverflow.com/questions/4417690/return-errors-from-php-run-via-ajax – ariel Mar 17 '20 at 17:05
  • Your SQL is vulnerable to SQL injection attacks. You should use parametised queries since you're already using mysqli. – scragar Mar 17 '20 at 17:10
  • @scragar I'm going to use [this](https://www.w3schools.com/php/php_mysql_prepared_statements.asp) tutorial to help me set parameters after I solve this problem. I just don't like working on two issues at the same time. It confuses me lol – Ariel Zabihi Mar 17 '20 at 17:23
  • @ariel Out of curiosity (i'm very new to all of this) what's wrong with returning the data as HTML? – Ariel Zabihi Mar 17 '20 at 18:06

1 Answers1

0

To hide #Loader when there was not more data count the total amount iterations of SQL rows, and put that as a PHP variable alongside the current iteration. I then put both variables in a hidden input inside the PHPs while statement and using jQuery make each of the inputs attributes into a variable where I could then check if the numbers were matching, if so I would hide #Loader.

As for the Error (PHP's else statement) I checked if data had the class .Error and if so I would hide #Loader.

Here is pseudo code:

SQL Query (Window functions work with MySQL 8.0+ only)

...
    SELECT inv.*, COUNT(*) OVER() AS totalrows FROM list inv WHERE wt >= 2.5
...

NextPage.php

...
    $ListingCounter = 0; // Begin counting iterations of while loop

    $Output = '';

        if($RowCount > 0) {

            while($row = mysqli_fetch_array($MySQLiQuery)) {

                $ListingCounter++; // Count iterations
                $ListingCount = $ListingCounter + $Offset; // Continue counting iterations after $Limit

                $output .=  '

                        <div class="Listing">

                            <!-- landing page -->
                            <a href="#ItemPage" class="ItemLink">

                                //Item Information goes here

                            </a>

    <input id="StoneIteration" type="hidden" data-listing="'echo $ListingCount;'" data-totalrows="'echo $row['totalrows'];'">


                        </div>

                    ';
...

InfiniteScroll.js

...

success: 

    function(data) {

        $('#Container').append(data);
        $('#PageNo').val(NextPage);

        // If the hidden input inside each .Stone's data attributes content both match hide #Loader
        $('.Listing').each(function(index, element) {

            var TotalRowCount = $(element).find('[data-totalrows]').data('totalrows');
            var ListingCount = $(element).find('[data-listing]').data('listing');

            if(TotalRowCount != ListingCount) {
                $('#Loader').show();   // Show infinite scroll
            } else {
                $('#Loader').hide();   // Hide infinite scroll
            }

        });

        // If data has .Error hide #Loader
        if(data.indexOf('class="Error"') > -1) {
            $('#Loader').hide();   // Hide infinite scroll
        }

    }
...

I hope this helps someone. If you have any questions please ask!