PHP + MYSQL filter query results dynamically (without sending back to the server)
Hello, I have a database I am trying to perform some filtering on. The default display is all of the records (working - or was before I tried what I'm about to post), and I have some inputs (drop downs, text fields) I'd like to change the state of and have the results update - hopefully without the use of a submit button. Here's basically what I'm trying to do.
function theAFunction()
{
// trying incorrectly to get the values of the fields as they are changed,
// obviously $_POST doesn't work but this is where my problem is
$a = $_POST['A'];
}
function theBFunction()
{
$b = $_POST['B'];
}
.
.
.
The above code returns errors on the $_POST lines (to be expected since nothing has been sent to the server).
I'm more used to the javascript DOM, and it seems like I do need to pass the results back to javascript somehow to do this without submitting a form - but then I think I will run in to a problem with getting js to update the query results from the database.
__________________
Found a flower or bug and don't know what it is ? agrozoo.net galery
if you don't spot search button at once, there is search form: agrozoo.net galery search
Last edited by BubikolRamios; 12-09-2012 at 09:45 AM..
Yes, it does. He is simply *testing* the logic. As he stated
Quote:
The default display is all of the records ...
and
Quote:
$a = '%'; // Setting the variables to match all the records first
And that WHERE clause (and the subsequent parts of it) will do exactly that.
****************
His problem is simple, he calls theAfunction( ) in doing that first echo, which I assume does what it is supposed to do by setting the value of $a to match $_POST["A"], but then he turns around *AFTER THAT* and *RESETS* $a back to $.
I *think* he just needs to put the initialization of $a, $b, etc. *BEFORE* that first call to theAfunction().
But maybe not. I don't follow the logic (or illogic) of this page, at all.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
You've nailed it Old Pedant, but for the last part, where I call the function is where it falls over. I could, in that function set $a = 'something' just not a $_POST[]. With php, $_POST causes the parser to expect there to be some data that was sent to the server using the same method, and tries to return it. I may have confused the issue there, but my intent was to show the hoped-for end-result.
The problem is basically that I have data fetched from a table using php, but I'd like to perform client side filtering on it via javascript (edit: well, preferably php but from the responses here js looks like the best bet). I need some tool to requery the data client side after it is fetched with php. AJAX will apparently do it (as BubikolRamios) pointed out, but I'm considering JQuery as well. I've been putting off tackling JQuery, so this might be a good time to start.
You see it? If there's no a=value in the querystring (or in the post data, as the case may be), then $a defaults to %. If there is a value, $a receives it, same with $b.
It's probably a TINY bit more efficient to code those as
Ummm...AJAX doesn't do any filtering unless you write it. For that matter, neither does jQuery.
Yea this is the key, I think I'm going to have to write it. One of the things I want to do is filter the data without the need to send a new query to the server. I'll do some poking at it and see how easy it is with JQuery/AJAX, if I can't get it I'll fall back on posting form data.
So I've added a variable that I can increment in my while loop to give each <tr> and <td> a unique id and removed the calls to the php functions, I'm wondering if I can write the functions in javascript and do some logic to set the css display property of rows I want to hide. something like this:
That part works so far, it gives each <tr> and <td> the correct id. The next step is to use those functions (now in my js) to do the logic and hide the rows I don't want to see.
And I'm sure there is a better way to do what I am about to show you. In PHP, I think you can create an array of objects and then call a method that will produce the same array in JS code in JSON notation. But since I don't know how to do that, I'll use brute force.
But first, let's use a real world example, instead of your hokey "aye" and "bee".
Back later.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
FWIW, I was able to achieve my goal (obviously without sorting) using jquery. I don't think it would have been much more difficult using vanilla js though. I wrote a function that loops through the rows, if the innerHTML of a column in the row doesn't match the selected index of the drop down it changes the class of the row and hides it.
This won't really make sense since I haven't modified it to match my example, but here it is for now:
Code:
function threadSearch()
{
var thfil = 0;
var thS0 = document.getElementById('threadFilter');
$("tr.rowhid").attr("class","rowfil"); //set the class of all the rows
$("tr.rowfil").show(); //show all the rows
for (var i=0;i=document.getElementById('a_th_' + thfil);i++)
{
var th2 = document.getElementById('a_th_' + thfil);
if (thS0.options[thS0.selectedIndex].text !== th2.innerHTML)
{
//alert("200"); - used for testing
// change the class of the row I want to hide
$("tr#rowfil_" + thfil + "").attr("class","rowhid");
$("tr.rowhid").hide(); //hide the row
// i++; superfluous
thfil++;
if (thS0.options[thS0.selectedIndex].text == '')
{
$("tr.rowhid").attr("class","rowfil");
$("tr.rowfil").show();
}
}
else
{
// i++; superfluous
thfil++;
}
}
}
edit: added another 'if' statement in case the user sets the drop down to blank - behavior is to show all the records.
Okay...here is the HTML and JavaScript code. Have to go to Dr. appointment. Back later to show you how to integrate PHP into it.
In the mean time, copy/paste it to your own machine and try it out. Click on the column headings. Click the same one again. Change the <select> choice. Play with it.
Does it do what you would want?
Code:
<!DOCTYPE html>
<html>
<head>
<title>Sort and Filter Demo</title>
<style type="text/css">
thead th {
background-color: lightblue;
cursor: pointer;
}
</style>
</head>
<body>
<form>
Show only people in
<select id="filterDept">
<option>All</option>
<option>Admin</option>
<option>Engineering</option>
<option>Sales</option>
</select> department(s)
<br/>
<table id="myData" border="1" cellpadding="5">
<thead>
<tr>
<th id="sortName">Name</th>
<th id="sortDept">Department</th>
<th id="sortStart">Start Date</th>
<th id="sortSalary">Salary</th>
</tr>
</thead>
<tbody></tbody>
</table>
<script type="text/javascript">
(
function( )
{
// ********************************************************************
// DATA DEFINITION
// ********************************************************************
// Constructor for an Employee object...
//
function Employee( nm, dpt, sdate, sal )
{
this.EmployeeName = nm;
this.Department = dpt;
sdate = sdate.split("/");
this.StartDate = new Date( +sdate[2], sdate[0]-1, +sdate[1] );
this.Salary = sal;
// alert("Constructing Employee:\n" + nm + "\n" + dpt + "\n" + sdate + "\n" + sal);
}
// Use PHP (or ASP or JSP or whatever) to create an array of Employees
//
var allEmps = [
new Employee('Ferris, Mary','Engineering','7/20/2008',87200),
new Employee('Forrest, Phil','Sales','1/3/2005',48790),
new Employee('Harrison, Michael','Admin','3/1/2011',53300.5),
new Employee('James, Barry','Admin','4/3/2004',33420),
new Employee('Johnson, Harold','Engineering','10/15/2000',82300),
new Employee('Morris, Jane','Admin','5/20/2009',38764.12),
new Employee('Roberts, Bob','Engineering','8/20/2004',91220),
new Employee('Williams, John','Sales','2/15/2008',42502.73)
];
// ********************************************************************
// SORTING CONTROLS
// ********************************************************************
// We need sort functions for each of the possible fields
// in a pair of Employee objects...
//
function sortByEmployeeName( em1, em2 )
{
if( em1.EmployeeName == em2.EmployeeName ) return 0;
return ( em1.EmployeeName < em2.EmployeeName ) ? sortLT : sortGT;
}
function sortByDepartment( em1, em2 )
{
if( em1.Department == em2.Department ) return 0;
return ( em1.Department < em2.Department ) ? sortLT : sortGT;
}
function sortByStartDate( em1, em2 )
{
if( em1.StartDate == em2.StartDate ) return 0;
return ( em1.StartDate < em2.StartDate ) ? sortLT : sortGT;
}
function sortBySalary( em1, em2 )
{
if( em1.Salary == em2.Salary ) return 0;
return ( em1.Salary < em2.Salary ) ? sortLT : sortGT;
}
// And then a "dictionary" of references to those functions
// will simplify the "sortBy" code:
//
sortFuncs = {
"sortName" : sortByEmployeeName,
"sortDept" : sortByDepartment,
"sortStart" : sortByStartDate,
"sortSalary" : sortBySalary
};
// Helper function to make dates readable
//
mNames = new Array( " Jan "," Feb "," Mar "," Apr "," May "," Jun ",
" Jul "," Aug "," Sep "," Oct "," Nov "," Dec " );
function showDate( when )
{
return "" + when.getDate() + mNames[when.getMonth()] + when.getFullYear();
}
// This function first sorts the array of Employee objects
// by the specified field and then displays the results
// in the table body, filtering as needed in the process
//
// we remember last sort, so if it is hit again we do opposite sort...
//
var lastSortBy = ""; // but start with impossible value
var sortGT = -1; // sort forwards to start
var sortLT = 1; // these can get swapped for reverse sort
var sortStyle = [" sorted <i>in reverse</i> by "," **impossible** "," sorted by "];
var tbl = document.getElementById("myData");
var tbody = tbl.getElementsByTagName("tbody")[0];
function sortBy( )
{
doSort( this.id );
}
function doSort( fldName )
{
// first, clear out any existing rows in the table body:
while ( tbody.hasChildNodes( ) )
{
tbody.removeChild( tbody.lastChild );
}
// check to see if we need to reverse sort prior sort...
if ( fldName != lastSortBy )
{
// no...so set the sort return values to defaults...
sortGT = -1;
sortLT = 1;
lastSortBy = fldName; // remember this
} else {
// resorting on same field...
sortGT = - sortGT;
sortLT = - sortLT; // reverse the sort
}
// sort using the appropriate function
allEmps.sort( sortFuncs[fldName] );
// get the filter value, if any:
var sel = document.getElementById("filterDept");
var filter = null;
if ( sel.selectedIndex != 0 ) { filter = sel.options[sel.selectedIndex].text; }
// and display the results!
for ( var rownum = 0; rownum < allEmps.length; ++rownum )
{
var curItem = allEmps[rownum];
if ( filter == null || filter == curItem.Department )
{
var row = tbody.insertRow();
var cell1 = row.insertCell(-1);
cell1.innerHTML = curItem.EmployeeName;
var cell2 = row.insertCell(-1);
cell2.innerHTML = curItem.Department;
var cell3 = row.insertCell(-1);
cell3.innerHTML = showDate(curItem.StartDate);
var cell4 = row.insertCell(-1);
cell4.innerHTML = "$" + curItem.Salary.toFixed(2);
}
}
}
// *******************************************************
// ATTACH EVENT HANDLERS
// *******************************************************
document.getElementById("sortName").onclick = sortBy;
document.getElementById("sortDept").onclick = sortBy;
document.getElementById("sortStart").onclick = sortBy;
document.getElementById("sortSalary").onclick = sortBy;
document.getElementById("filterDept").onchange = function( )
{
// force a sort by same as last field, but in same ordering:
var sName = lastSortBy;
lastSortBy = "";
doSort( sName );
}
// *******************************************************
// get things started:
// *******************************************************
doSort("sortName");
}
)( );
</script>
</body>
</html>
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.
Last edited by Old Pedant; 12-15-2012 at 02:31 AM..
Okay, so the only part of all that code that PHP needs to be concerned with is here:
Code:
// Use PHP (or ASP or JSP or whatever) to create an array of Employees
//
var allEmps = [
new Employee('Ferris, Mary','Engineering','7/20/2008',87200),
new Employee('Forrest, Phil','Sales','1/3/2005',48790),
new Employee('Harrison, Michael','Admin','3/1/2011',53300.5),
new Employee('James, Barry','Admin','4/3/2004',33420),
new Employee('Johnson, Harold','Engineering','10/15/2000',82300),
new Employee('Morris, Jane','Admin','5/20/2009',38764.12),
new Employee('Roberts, Bob','Engineering','8/20/2004',91220),
new Employee('Williams, John','Sales','2/15/2008',42502.73)
];
And that's not hard.
Again, remembering that I don't use PHP, it should go something like this:
Code:
... all the HTML and JavaScript above this point is untouched ...
// Use PHP (or ASP or JSP or whatever) to create an array of Employees
//
var allEmps = [
<?php
... make your db connection here ...
$sql = "SELECT name, department, DATE_FORMAT(startdate,'%e/%m/%Y') AS start, salary FROM employees";
$result = mysql_query($sql) or die( mysql_error() );
$first = true;
while ($row = mysql_fetch_array($result)
{
if ( ! $first )
{
// for all except first row, end the prior row with comma and newline
echo ",\n";
}
// get the data
$first = false;
$name = $row["name"];
$dept = $row["department"];
$start = $row["start"];
$salary = $row["salary"];
// output one Employee
echo " new Employee('$name','$dept','$start',$salary)";
}
// end of PHP code!
?>
]; // end of the JS allEmps array of Employee objects
... rest of the JS/HTML code unchanged ...
And now you have your web page that allows you to sort on any column in either direction and to filter results.
Naturally, it would be easy to add more filters, if you wanted.
__________________
An optimist sees the glass as half full.
A pessimist sees the glass as half empty.
A realist drinks it no matter how much there is.