Help adding jQuery AJAX functionality to PHP result

Hi all

I’m currently working with some php code which shows a list of venues base on the category_id.
What I’d like to do is change the result depending on what link I click using AJAX.

Just trying to get a understanding of how things work and how I’d fit everything together using the jQuery Ajax method, or just AJAX not sure if one is better than the other.

Query DB (minimised for viewing)

function getVenueInfo($category_id) {
    static $array;
    if (!$array) {
        $array = array();

        $sql = 'SELECT venue_id,
                       title,
                       category_id,
                       address,
                       FROM tbl_venues';

                $result = mysql_query($sql);
                while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
                $array[$row['category_id']][] = $row;
            }
        }
    return $array[$category_id];
}

I’d like these links to change the result below:

<p class="ajax-links">
            <a href="#" onClick="" > House</a>
            <a href="#" onClick="" > Dance</a>
            <a href="#" onClick="" > Rock</a>
</p>

getVenueInfo is the hook here which will change the result based on category_id selected, could we add this to the links above some how?

<dl class="venues">
            <?php foreach (getVenueInfo('dance') as $info) { ?>
                    <dt>
                        <?= $info['title'] ?>
                    </dt>

                    <dd>
                        <i><?= $info['address'] ?></i>
                    </dd>
            <?php } ?>
</dl>

Any guidance, examples would be great thanks.

cb

Hi,

Probably the simplest way to do this is to have a PHP script that takes the music genre as a POST param and returns the HTML of the dl, which you can then insert into the page via JS.

As an example, the code might look something like this:


// Your script includes / setup here

$genre = $_POST['genre'];

$output = '';
foreach (getVenueInfo($genre) as $info)
{
    $output .= "<dt>{$info['title']}</dt><dd><i>{$info['address']}</i></dd>";
}

echo $output;


<p class="genre-links">
    <a href="#">House</a>
    <a href="#">Dance</a>
    <a href="#">Rock</a>
</p>

<dl class="venues"></dl>

<script>
    $(".genre-links").click(function(event){
        event.preventDefault();
        $( ".venues" ).load( "venue_lists.php", { genre: this.innerHTML } );
    });
</script>

Note that I’ve assumed the use of jQuery, and that the JS script block is placed just before the closing </body> tag of the page.

Thanks a lot fretburner
Appreciate your response, this is exactly what I need :cool:

My old approach was using just PHP to display each genre result within a separate tab.

<div class="tab">
<dl class="venues">    
           <?php foreach (getVenueInfo('dance') as $info) { ?>
...
<div class="tab">
<dl class="venues">    
            <?php foreach (getVenueInfo('rock') as $info) { ?>
...
and so on...

I’d now like to show all the venues as one big list, then as discussed, give the user the option to narrow this down to the genre they like with AJAX. So, if for some reason or other javascript is not available, they’ll still see the full list of venues.

Currently working locally with your code/advice trying to get things setup, post back shortly.

Thanks, cb

If you’re already going to be rendering the page server-side with all venues, wouldn’t it make sense just to hide the venues for all genres but the first, and then show them according to which link is clicked? That’ll be much quicker than an ajax request back to the server. Maybe something along the lines of an accordion effect?

Hi fretburner

I do see your point, though this is what I already have working, but with tabs as I mentioned above.

Take for example a standard e commerce store showing a big list of t-shirts, with links on the side to narrow it down to t-shirts in a color of blue, color of green etc. This is exactly the same approach I’d like but with genre.

I think the easiest approach would be if we can change the genre value

(getVenueInfo('dance') as $info)

which would then update the list, everything is already in place, regarding PHP anyway.

Could we do it this way?

Again, just trying to get a understanding here fretburner.
The way things are going I’ll eventually need to redesign my DB as some venues will be in two genres.

Thanks, cb

What about if the page returns the full list of venues by default, but you can pass a genre in the query string to filter the list, eg. venues.php?genre=rock

Your genre links would then be something like this:


<p class="genre-links">
    <a href="venues.php?genre=house">House</a>
    <a href="venues.php?genre=dance">Dance</a>
    <a href="venues.php?genre=rock">Rock</a>
</p>

and your JS:


$(".genre-links a").click(function(event){
    event.preventDefault();
    $( ".venues" ).load( this.href );
});

This way, the page functions pretty similar for both JS and non-JS users - the JS users will just have the advantage of avoiding a full page reload each time they filter the list.

Your PHP would need to do something like this:


if ( isset($_POST['genre']) {

    // Grab venues for chosen genre

    if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
    {
        $output = '';
        foreach (getVenueInfo($genre) as $info)
        {
            $output .= "<dt>{$info['title']}</dt><dd><i>{$info['address']}</i></dd>";
        }
        
        echo $output;
    }
    
} else {

    // Get all venues
    // Render and return full html page

}

( AJAX request detection from this blog post)

What about if the page returns the full list of venues by default

Exactly fretburner, this is how I want things to start, then use the links to update without page refresh or url change.

The method you mention is a great approach, though I want the page to have a consistent URL so everything is indexed as one full page (seo my main concern), and as you say, the guys with JS will get the benefit. I worked with something similar in the past and after much testing, reviewing analytics data, adding the extra query string was not the way to go. I want things to work as a type of application, well, the feel anyway.

I’m also slightly confused with your code, you keep using isset($_POST[‘genre’], do you mean category_id? This is column name that acts as the genre name in my DB.

And thanks for the link.

Cheers, cb

Hi cb,

If you really want to avoid using a query string, you could use POST, but you’d need to use some sort of form (perhaps with a dropdown, like you mentioned before) so that it would still work for your non-JS users:


<form id="genre-select" method="post">
    <select name="genre">
        <option value="dance">Dance</option>
        <option value="house">House</option>
        <option value="rock">Rock</option>
    </select>
    <input type="submit" value="Update">
</form>

<script>
    $("form#genre-select input").hide();
    $("form#genre-select select").on('change', function(){
        $( ".venues" ).load( 'venues.php', { genre: this.value } );
    });
</script>

In my last example it should actually have been $_GET[‘genre’] - naming it genre was to make it more user-friendly as it was to be visible in the URL. Whatever you name the request param, it wouldn’t cause any problem with your PHP script as once it’s passed into the getVenueInfo function the argument becomes available as $category_id.