AJAX - update table and selects

JavaScript and client side scripting.

Moderator: General Moderators

User avatar
pickle
Briney Mod
Posts: 6445
Joined: Mon Jan 19, 2004 6:11 pm
Location: 53.01N x 112.48W
Contact:

Re: AJAX - update table and selects

Post by pickle »

Well looking at your code, only 1 of the <a> tags has an ID (incidentally, that same tag is missing a "href" attribute) - that might be your problem.
Real programmers don't comment their code. If it was hard to write, it should be hard to understand.
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Re: AJAX - update table and selects

Post by Stryks »

Hehehe ... yeah ... I know it's a bit hacked, but it was during a testing iteration, which I tend to find myself in constantly with javascript. Basically, I was changing things as I went along trying to find a combination that worked. You know, change the name of one element, mess with the attributes, etc.

What eventually did make it work however was changing this ...

Code: Select all

# <script>
#     $(document).ready(function(){
#         $.getJSON("includes/ajax/tbl_main.php",
#         function(json){
#            
#             // update the chartBox
#             $("#dyn_tbl").html(json.dyn_tbl)
#            
#             // update the nav buttons
#             //$(".navbutton").attr({'id': json.btn_last});
#            
#             // check for row clicks
#             $(".tbl_row").click(function(){
#                 var id = $(this).attr('id');
#                 window.location = 'nmi_view.php?meter='+id;
#             });
#         });
#     });
#     // check for pagination clicks
#     $(".navbutton").click(function(){
#         //var id = $(this).attr('id');
#         alert('Jumping to page #');
#         //$.getJSON("includes/ajax/tbl_main.php", { page: id})  
#     });
# </script>
... to this ...

Code: Select all

# <script>
#     $(document).ready(function(){
#         $.getJSON("includes/ajax/tbl_main.php",
#         function(json){
#            
#             // update the chartBox
#             $("#dyn_tbl").html(json.dyn_tbl)
#            
#             // update the nav buttons
#             //$(".navbutton").attr({'id': json.btn_last});
#            
#             // check for row clicks
#             $(".tbl_row").click(function(){
#                 var id = $(this).attr('id');
#                 window.location = 'nmi_view.php?meter='+id;
#             });
#         });
#         // check for pagination clicks
#         $(".navbutton").click(function(){
#             //var id = $(this).attr('id');
#             alert('Jumping to page #');
#             //$.getJSON("includes/ajax/tbl_main.php", { page: id})  
#         });
#     });
# </script>
The way I showed it really didn't help with spotting that though. I've still got a lot to learn here, I can see that.

But when I get a chance I'm going to extract the elements into a test site which I'll put online somewhere, so it's a bit clearer where I'm going wrong.
User avatar
Stryks
Forum Regular
Posts: 746
Joined: Wed Jan 14, 2004 5:06 pm

Re: AJAX - update table and selects

Post by Stryks »

Well ... I have something working. It's not pretty just now, but this wasn't supposed to be really. Pretty much just designed to test the concept.

This is a fair whack ... sorry. It got a bit out of control.

So, the base HTML / javascript.

Code: Select all

<?php
    if(isset($_POST['id_search'])) {
        if(($_POST['id_search'] == '') && (isset($_SESSION['filter']['search']) && ($_SESSION['filter']['search'] == ''))) unset($_SESSION['filter']['search']);
        else $_GET['search'] = $_POST['id_search'];
    }
    if(isset($_POST['filter_type'])) { $_GET['type'] = $_POST['filter_type']; $_GET['page'] = 1; }
    if(isset($_POST['filter_group'])) $_GET['group'] = $_POST['filter_group'];
 
    include("includes/ajax/ajax_test.php");
    
    $page_prev = $output['curr_page'] - 1;
    if($page_prev < 1) $page_prev = 1;
    $page_next = $output['curr_page'] + 1;
    if($page_next > $output['last_page']) $page_next = $output['last_page'];
 
    
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
 
<title>AJAX_TEST</title>
 
 
<script type="text/javascript" src="includes/javascript/jquery.js"></script>
 
<script type="text/javascript">
 
    
    $(document).ready(function(){
 
        // Draw initial select dropdown for AJAX only functionality
        $("#pg_current").html('<select name="pg_select" id="pg_select"><option value="0">##</option></select>');
 
        // Negate href links on pagination buttons as javascript is available
        $("#pg_bar > a").attr({ href: 'javascript&#058;void(0);' });
        
        // Dispose of buttons - not needed when javascript is present
        $(":submit").remove();
        
        $("#id_search").keypress(function(key) { 
            var value = $(this).val();
            if (48 <= key.which && key.which <= 57) var search = value+String.fromCharCode(key.which);
            else if (key.which == 8) var search = (value.substr(0, value.length -1));
            getData(1, 'ALL', 'ALL', search);
        });
        
        $("#filter_type").change(function() { getData(1, $(this).val(), $("#filter_group").val()); });
        $("#filter_group").change(function(){ getData(1, $("#filter_type").val(), $(this).val());  });
        
        $("#pg_select").change(function(){ getData($(this).val()); });
        
        $(".pg_button").click(function(){
            pg_num = $(this).attr('id');
            pg_cur = $("#pg_select").val();
            pg_end = parseInt($(".pg_last").attr('id')) + 1;
            // If the page click isn't going to put us out of bounds, get new data
            if((pg_cur != pg_num) && ((pg_num > 0) && (pg_num < pg_end))) {
                getData(pg_num);
            }
            //alert('Switching to page #'+pg_num);
            //pg_last = $(".pg_last").attr('id');
            //if((pg_num >= 1) && (pg_num <= $(".pg_last").attr('id'))) loadTable(pg_num);
        });
        
        $("#btn_add").click(function(){
            $("#sel_test").append('<option value="3">option 3</option>');
            //alert('value should be inserted');    
        });        
 
        $('#btn_go').click(function(){
        });
        
        // Modified following to auto-load table
        //$("#btn_test").click(function(){ loadTable(1); });
        getData(1);
    
    
    });
    
    function getData(page_num, type_id, group_id, search_str) {
        //if (typeof page_num == 'undefined' ) page_num = 1;
 
        if (typeof search_str != 'undefined') {
            var args = { type: 'ALL', group: 'ALL', search: search_str };        
        } else if ((typeof type_id != 'undefined') || (typeof group_id != 'undefined')) {
            var args = { page: page_num, type: type_id, group: group_id };
        } else {
            var args = { page: page_num };
        }
        $.getJSON("includes/ajax/ajax_test.php", args , function(data){
            //alert('data: '+data);
            $("#output").html(data.tbl_body);
            
            $(".tbl_row").click(function(){
                alert('you clicked row # '+ $(this).attr('id'));
                //window.location = 'detail.php?user='+$(this).attr('id'); 
            });
            
            // Fill the page selector listbox where last page value is different to the onscreen page count
            if(data.last_page != $("#pg_select > option:last").val()) {
                $("#pg_select").empty(); 
                for(var i = 1; i <= data.last_page; i++) $("#pg_select").append('<option value="'+i+'">'+i+'&nbsp;&nbsp;</option>');
            }
            // Set the current page value in the page selector
            $("#pg_select").val(data.curr_page);
 
            // Set the total page field
            $("#pg_total").text(data.last_page);
 
            // Set destinations for pagination controls - '.pg_first' is always 1
            $(".pg_first").attr({ id: 1  });
            $(".pg_prev").attr({ id: parseInt(data.curr_page) - 1  });
            $(".pg_next").attr({ id: parseInt(data.curr_page) + 1 });
            $(".pg_last").attr({ id: data.last_page });               
 
            // OPTIONAL - update filter items - hey, this nesting deal is pretty sweet
            if (typeof data.type_list != 'undefined' ) 
                $("#filter_type").html('<option value="ALL">All Types&nbsp;&nbsp;</option>').append(data.type_list).val(type_id);
            if (typeof data.group_list != 'undefined' ) 
                $("#filter_group").html('<option value="ALL">All Groups&nbsp;&nbsp;</option>').append(data.group_list).val(group_id);               
        });        
    }
    
</script>
 
<style>
 
.pg_button { border: 0px; vertical-align: top; margin: 0px; }
 
#pg_bar { vertical-align: bottom; }
 
table { width: 400px; background-color:#CCCCCC ; border-spacing: 1px; }
table thead { background-color: cornsilk }
.tbl_row td { padding: 3px; }
.tbl_row.odd { background-color:#FFFFFF; }
.tbl_row.even { background-color:#EFEFEF; }
 
</style>
 
</head>
<body>
    <form name="test_form" method="post">
 
        ID Search:&nbsp;&nbsp; 
        <input type="text" name="id_search" id="id_search" size="5" maxlength="5" value='<?php if(isset($_GET['search'])) echo $_GET['search']; ?>'> <input type="submit" id="btn_search" name="btn_search" value="Search">
        <p>
 
            Filter:&nbsp;&nbsp;
            <select id="filter_type" name="filter_type">
                <option value="ALL"<?php if(isset($_GET['type']) && ($_GET['type'] == 'ALL')) echo ' selected';?>>All Types&nbsp;&nbsp;</option><?php echo $output['type_list']; ?>
            </select>
            <select id="filter_group" name="filter_group">
                <option value="ALL"<?php if(isset($_GET['group']) && ($_GET['group'] == 'ALL')) echo ' selected';?>>All Groups&nbsp;&nbsp;</option><?php echo $output['group_list']; ?>
            </select>
            <input type="submit" id="btn_filter" name="btn_filter" value="Apply Filters">
        </p>
    </form> 
 
    <p>
 
        <table cellpadding="0" cellspacing="0">
            <thead>
                <tr> 
                    <td>USER ID</td>
                    <td>NAME</td>
                    <td>TYPE</td>
                    <td>GROUP</td>
                </tr>
            </thead>
            <tbody id="output"><?php echo $output['tbl_body']; ?></tbody>
        </table>
    </p>
<?php
    $ext = '';
    if(isset($_GET['type'])) $ext .= '&type=' . $_GET['type'];
    if(isset($_GET['group'])) $ext .= '&group=' . $_GET['group'];
    if(isset($_GET['type']) && isset($_GET['group']) && ($_GET['type'] == 'ALL') && ($_GET['group'] == 'ALL')) $ext = '';
    if(isset($_GET['search'])) $ext .= '&search=' . $_GET['search'];
 
?>
        <div id="pg_bar">
            <a href="ajax_test.php?page=1<?php echo $ext; ?>"><img src="/elecman/includes/images/btn_pag_first.png" class="pg_button pg_first" alt="First"></img></a>
            <a href="ajax_test.php?page=<?php echo $page_prev . $ext; ?>"><img src="/elecman/includes/images/btn_pag_prev.png" class="pg_button pg_prev" alt="Previous"></img></a> 
            Page <span id="pg_current"><?php echo $output['curr_page']; ?></span> of <span id="pg_total"><?php echo $output['last_page']; ?></span>
            <a href="ajax_test.php?page=<?php echo $page_next . $ext; ?>"><img src="/elecman/includes/images/btn_pag_next.png" class="pg_button pg_next" alt="Next"></img></a> 
            <a href="ajax_test.php?page=<?php echo $output['last_page'] . $ext; ?>"><img src="/elecman/includes/images/btn_pag_last.png" class="pg_button pg_last" alt="Last"></img></a>
        </div>
    <p>SELECT PC_ID, count(PC_ID) AS count from tbl_meters WHERE MT_ID = 0 AND PC_ID != 0 GROUP BY PC_ID limit 5,5</p>
    <p id="test"><?php print_r($_POST); ?></div>
</body>
</html>
The AJAX file.

Code: Select all

<?php
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')) {
    session_start();
    
    // Prevent IE6 caching content
    header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
 
    $ajax = true;
    $make_filters = false;  // AJAX MODE: Only build type and group lists when needed
} else {
    $ajax = false;
    $make_filters = true;   // HTML MODE: Build type and group lists for every view 
}
    // Determine if there are filters to be applied
     
    if(isset($_GET['search'])) {
        $make_filters = true;
        $_SESSION['filter']['search'] = $_GET['search'];   
    }
    if(isset($_GET['type'])) {
        if(is_numeric($_GET['type'])) { 
            $_SESSION['filter']['type'] = $_GET['type'];
            $make_filters = true;
        } elseif($_GET['type'] == 'ALL') {
            if(isset($_SESSION['filter']['type'])) unset($_SESSION['filter']['type']);
            $make_filters = true;
        } 
    }
    if(isset($_GET['group'])) {
        if(is_numeric($_GET['group'])) { 
            $_SESSION['filter']['group'] = $_GET['group'];
            $make_filters = true;
        } elseif($_GET['group'] == 'ALL') {
            if(isset($_SESSION['filter']['group'])) unset($_SESSION['filter']['group']);
            $make_filters = true;
        }
    }
    
    // Determine the page to be viewed
    if(isset($_GET['page']) && is_numeric($_GET['page'])) $view_page = $_GET['page']; else $view_page = 1; 
 
    // Records per page - set low to begin with to simplify things
    $records_per_page = 2;
 
    // FOR DEMONSTRATION ONLY
        // A small amount of data - would be replaced by a LIMITed database call
        $results[] = array('id'=>120, 'name'=>'Fred', 'type'=>1, 'group'=>1);
        $results[] = array('id'=>121, 'name'=>'Jim', 'type'=>2, 'group'=>1);
        $results[] = array('id'=>122, 'name'=>'Bob', 'type'=>1, 'group'=>1);
        $results[] = array('id'=>123, 'name'=>'Harry', 'type'=>2, 'group'=>2);
        $results[] = array('id'=>124, 'name'=>'Tim', 'type'=>1, 'group'=>2);
        $results[] = array('id'=>125, 'name'=>'Peter', 'type'=>2, 'group'=>2);
        $results[] = array('id'=>130, 'name'=>'Frank', 'type'=>3, 'group'=>2);
        $results[] = array('id'=>131, 'name'=>'Barry', 'type'=>3, 'group'=>2);
        $results[] = array('id'=>132, 'name'=>'Marvin', 'type'=>3, 'group'=>2); 
        // This part filters the results as required
        if(isset($_SESSION['filter']['type']) || isset($_SESSION['filter']['group']) || isset($_SESSION['filter']['search'])) { 
            $filtered = array();
            foreach($results as $result) {
                $match = true; 
                if(isset($_SESSION['filter']['search'])) 
                    if(substr($result['id'], 0, strlen($_SESSION['filter']['search'])) == $_SESSION['filter']['search']) $match = true; else $match = false;
                if(isset($_SESSION['filter']['type']) && ($match)) if($result['type'] == $_SESSION['filter']['type']) $match = true;  else $match = false;
                if(isset($_SESSION['filter']['group']) && ($match)) if($result['group'] == $_SESSION['filter']['group']) $match = true; else $match = false;
 
                if($match) $filtered[] = $result;
            }
            $results = $filtered; 
        }
        // This part splits array data into page chunks - database would just return view range with LIMIT
        if(count($results) > 0) {
            $trans = array_chunk($results, $records_per_page);
            $data = $trans[$view_page - 1];
        } else $data = $results;
        
    // Build dropdown lists
    if($make_filters) {
        foreach($results as $result) { $types[] = $result['type']; $groups[] = $result['group']; } 
        if(isset($types)) { 
            $output['type_list'] = '';
            $types = array_unique($types); sort($types); 
            foreach($types as $type) {
                if((!$ajax) && (isset($_GET['type']) && ($_GET['type'] == $type))) $state = ' selected'; else $state = '';
                $output['type_list'] .= "<option value=\"$type\"$state>Type $type</option>";    
            }
        }
        if(isset($groups)) { 
            $output['group_list'] = ''; 
            $groups = array_unique($groups); sort($groups); 
            foreach($groups as $group) {
                if((!$ajax) && (isset($_GET['group']) && ($_GET['group'] == $group))) $state = ' selected'; else $state = '';
                $output['group_list'] .= "<option value=\"$group\"$state>Group $group</option>";    
            }
        }
    }
    
    // Set some pagination data to be transferred with the table
    $output['curr_page'] = $view_page;
    $output['last_page'] = ceil(count($results) / $records_per_page);
    
    // workaround for testing
    if($output['last_page'] == 0) $output['last_page'] = 1;
    
    $tbl_body = '';
    if(count($data) > 0) {
        foreach($data as $id=>$row) {
            if($id % 2) $row_style ='odd'; else $row_style = 'even';  
            $tbl_body .= "<tr class='tbl_row $row_style' id='{$row['id']}'>";
            $tbl_body .= '<td>' . implode('</td><td>', $row) . '</td>';
            $tbl_body .= '</tr>';
        }
    } else $tbl_body = "<tr><td colspan='4'>No Matching Data Found</td></tr>";
    $output['tbl_body'] = $tbl_body;
 
    if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')) echo json_encode($output);
?>
As you can see, the sample data turned out to be more trouble than it was worth :crazy: .... a simple mysql connection would have been so much easier.

Theres still a few loose ends to chase up of course, and I shudder to think how badly if would fail validation, but it seems to work.

I'd love to hear feedback regarding ... well, anything. In particular, I got a bit creative with the javascript in places, where I'm sure jquery could have been used to much greater effect. Would love to hear how.

You can check it out at a test site HERE

I have some specific questions on how to make this better, but I'll hold off a bit and hope for some comments.

Cheers
Post Reply