Alright, I'm completely new to jQuery, and I'm probably missing something obvious here...
What I am trying to do is:
1) use JavaScript + Ajax + PHP to pull a table via ResponseText from a MySQL database (currently working)
2) use jQuery to perform actions on the table (not working)
The first part (1) of the code looks like this:
<script>
function displayPeople(String) {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else { // code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("People").innerHTML=xmlhttp.responseText;
}
}
var Query = "?String=" + String;
xmlhttp.open("GET","library/display_people.php"+Query,true);
xmlhttp.send();
}
window.onload = displayPeople("");
</script>
<input id="Search_People" placeholder="Search People by Name" size="50" onkeyup="displayTable(this.value)">
<div id="People" style="width:900px; height:200px; overflow-y:scroll;">
The table is dynamically updated while the user types a name in the input field.
The PHP file assembles the Query and returns:
$display_string = "<table>";
while($row = mysqli_fetch_array($Results)){
$display_string .= "<tr>";
$display_string .= "<td>" . $row['FirstName'] . "</td>";
$display_string .= "<td>" . $row['LastName'] . "</td>";
$display_string .= "<td>" . "<button class='editbtn'>edit</button>" . "</td>";
$display_string .= "</tr>";
}
$display_string .= "</table>";
echo $display_string;
NOW, part (2), I would like to perform some action using jQuery on the table entries (the ultimate goal being this: http://www.9lessons.info/2011/04/live-table-edit-delete-with-pagination.html).
To start with, I added this jQuery script to the .html taken from another tutorial (http://jsfiddle.net/tXS6w/) which works great on any "static" table, but has no effect whatsoever on the table above! That is, nothing happens if I click on the button which should instead change label...
$(document).ready(function () {
$('.editbtn').click(function () {
$(this).html($(this).html() == 'edit' ? 'modify' : 'edit');
});
});
How can I make this work?
My knowledge of JavaScript/Ajax/PHP is quite limited, so the simplest solution is the most welcomed!
Thanks!!!
The edit button is generated dynamically so click event wont work as it is a delegated event, so use .on instead of .click
Instead of
$(document).ready(function () {
$('.editbtn').click(function () {
$(this).html($(this).html() == 'edit' ? 'modify' : 'edit');
});
});
use this way
$(document).ready(function () {
$(document).on.('click','.editbtn',function () {
$(this).html($(this).html() == 'edit' ? 'modify' : 'edit');
});
});
now this should work as you intend it to.
for more info on delegated events refer: http://api.jquery.com/on/
I have modified your jsfiddle to showcase delegated events, you can check it.
LIVE DEMO:
http://jsfiddle.net/dreamweiver/tXS6w/291/
Happy Coding :)
try something like this
$('#People').on('click','.editbtn',function () {
$(this).html($(this).html() == 'edit' ? 'modify' : 'edit');
});
Reason :
you fiddle code correctly because table is already present in DOM so click event work on it.
But it will not work on element which is dynamically added to DOM for that you have to use jQuery Delegate or On function.
delegate() http://api.jquery.com/on/
On() http://api.jquery.com/delegate/
The buttons with class .editbtn are not yet in the DOM on document.ready because you load the table contents later. You have to add your click event to the buttons after the ajax request is complete.
Related
Basically, I have a search box that suggests results from a database as user types. It looks like this :
Example
.
I use ajax in a file to make a live search as user types :
<input name="estab" id="estab" type="text" class="estab" />
<div id="result"></div>
<script>
$("#estab").on("input", function(){
$estab = $("#estab").val();
if ($estab.length > 0){
$('#result').show();
$.get("res.php", {"estab":$estab},function($data){
$("#result").html($data);
})
}
});
<script>
Then in another file (res.php) I have a sql request and I display results. I also have my 'onclick' function to replace suggestion in text box :
while($result=$data->fetch_assoc()){
$sortie[] = $result['school'];
}
$sortie2=array_unique($sortie);
echo '<ul>';
foreach($sortie2 as $value){
echo "<script>
function fill(){
document.getElementById('estab').value = '$value';
$('#result').hide();
}
</script>";
echo "<li onclick='fill()'><b>$value</b></li>";
}
echo '</ul>';
My problem is : when i click on any of the suggestion, it is always the last option that is replaced in the text box, in this case "University of Washington".
I have been trying to solve that problem for 2 days now and I can't find the solution.
Any help would be greatly appreciated. Thanks
UPDATE
Found the solution, if someone is interested, here's what I did in res.php:
while($result=$data->fetch_assoc()){
?>
<li onclick='fill("<?php echo $result['school']; ?>")'><?php echo $result['school'];?></li>
<?php
}
?>
</ul>
and in the first file :
<script>
function fill(val){
$('#estab').val(val);
$('#result').hide();
}
$("#estab").on("input", function(){
$estab = $("#estab").val();
if ($estab.length > 0){
$('#result').show();
$.get("res.php", {"estab":$estab},function($data){
$("#result").html($data);
})
}
});
</script>
echo "<script>
function fill(newValue){
document.getElementById('estab').value = '" + newValue + "'" + ;
" $('#result').hide();
}
</script>";
echo '<ul>';
foreach($sortie2 as $value){
echo "<li onclick='fill($value)'><b>$value</b></li>";
}
echo '</ul>';
I wouldn't use the onclick method here. I would use jQuery to assign the events to your list items. But if you must, in your onclick method, try passing this.value like so:
<li onclick="fill(this.value)"><b>$value</b></li>
Then your fill() method could be something like so:
function fill(val){
$('#estab').val(val);
$('#result').hide();
}
EDIT: You are mixing plain JavaScript and jQuery code. I replaced your plain JS line with the jQuery equivalent.
Also, if you are adding the fill() method in the same loop that adds the LIs, then you are adding multiple fill methods, which is incorrect. Just add it once in the same script tag like below.
<script>
function fill(val){
$('#estab').val(val);
$('#result').hide();
}
$("#estab").on("input", function(){
$estab = $("#estab").val();
if ($estab.length > 0){
$('#result').show();
$.get("res.php", {"estab":$estab},function($data){
$("#result").html($data);
})
}
});
<script>
I have 2 dropdownlists. The first contains Car Brands like seat,bmw,audi etc.
The second i want to contain the models from the specific Brand the user selected in list 1.
In my current code state, when i select A brand from List 1 the second list is getting Filled with the same elements from List 1. So I Have a Duplicated List with exactly the same records.
The main file:
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
$css='css.css';
$doc = JFactory::getDocument();
$doc->addStyleSheet('modules/mod_alpha_table/assets/'.$css);
$db= JFactory::getDbo();
$ready = $db->getQuery(true);
$query="SELECT category_name,virtuemart_category_id from uhhu_virtuemart_categories_el_gr INNER JOIN uhhu_virtuemart_category_categories ON uhhu_virtuemart_categories_el_gr.virtuemart_category_id = uhhu_virtuemart_category_categories.category_child_id WHERE uhhu_virtuemart_category_categories.category_parent_id = 105";
$db->setQuery($query);
$options=$db->loadObjectList();
$model="";
?>
<script>
function showUser(str) {
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("txtHint").innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open("GET","query.php?q="+str,true);
xmlhttp.send();
}
</script>
<div class="srchcr">
<div class="srch">
<form name="searchcar">
<form>
<select onchange="showUser(this.value)" name="cats">
<option value="none">Select Make</option>
<?php foreach ($options as $row) {
echo '<option value=' . $row->virtuemart_category_id . '>'. $row->category_name . '</option>';
}
?>
</select>
<select name="subcats" id="txtHint">
<option value="none">Select Model</option>
</select>
</form>
</div>
</div>
query.php file :
<?php
$doc = JFactory::getDocument();
$db= JFactory::getDbo();
$ready = $db->getQuery(true);
$q = htmlspecialchars($_REQUEST['q']);
$query='SELECT category_name,virtuemart_category_id from #__virtuemart_categories_el_gr INNER JOIN #__virtuemart_category_categories ON #__virtuemart_categories_el_gr.virtuemart_category_id = #__virtuemart_category_categories.category_child_id WHERE #__virtuemart_category_categories.category_parent_id = $q';
$db->setQuery($query);
$options=$db->loadObjectList();
foreach ($options as $row) {
echo '<option name='. $q .' value=' . $row->virtuemart_category_id . '>'. $row->category_name . '</option>';
}
?>
Query tested at phpmyAdmin and working fine. It seems somehow the first query is getting executed twice instead of the query inside the $query.php file. I also tried include the code from the external file inside the main but its the same story.I also renamed the second $query as $query2 and executed $query2 but nothing changed.Could someone enlight me on what is going wrong ?
EDIT:
After a break and bit more debugging i think that this is where the problem start:
xmlhttp.open("GET","query.php?q="+str,true);
It seems like the request for some reason, instead of query.php is sent at index.php and triggers the same query again.I added die(); at the start of query.php and nothing happened.So may i need to use a joomla syntax or something ?
Looks like you have a copy-paste-error here. When comparing the creation of your option-tags, I see the exact same code for both the brands and the models, meaning query and dom-creation.
So basically, your code is perfectly fine. But in your query.php you are creating this same brand-list again ;)
Some general comments on your code:
Do not create your own implementation of the XmlHttpRequest, use a library like jquery or mootools
You are vulnerable to sql-injections when using values from userland ($_REQUEST['q']) without sanitizing them. See this question on stackoverflow: Best way to prevent SQL injections in Joomla
if it is true that you gather the information for your 2 lists with the same query, try to implement your logic (user selects brand, model-list is updated) through javascript. So your main.php still creates the brand-list, but renders all model-lists as well. These are shown/hidden when the user changes the brand accordingly. This would avoid the additional roundtrip to the server each time a brand is selected.
When I am building 2 dropdowns filling them from the database, the second dropdown is created when a value is picked from the first dropdown. But then, when I select an option in the second, my ajax is being executed. But when I have only one value in the second dropdown, it won't work. Even if I call the javascript function manualy.
The 2nd dropdown:
<?
include ('../dbconnect.php');
$query = "CALL get_projects(".$userid.",".$q.")";
$result = mysql_query($query);
$countprojects = mysql_num_rows($result);
if ($countprojects != 0){
echo '<select class="form-control" onchange="showContent(this.value)">'."\n";
if ($countprojects > 1){
echo "<option value='none' selected>Select project</option>";
}
while($rowprojecten = mysql_fetch_assoc($result)){
echo '<option value='.$rowprojecten['projectID'].'>'.$rowprojecten['projectname'].'</option>';
$lastvalue = $rowprojecten['projectID']; // see below why i did this
}
echo '</select>';
?>
the javascript function I wrote/copied:
function showContent(str)
{
if (str=="")
{
document.getElementById("project").innerHTML="";
return;
}
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("project").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","./includes/ajax/getcontent.php?q="+str,true);
xmlhttp.send();
}
The phpfile what is called from this javascript:
<?
$q = intval($_GET['q']);
include ('../dbconnect.php');
$query = "CALL get_project(".$userid.",".$q.")";
$return = '<div id="project">';
$return .= $query;
$return .= '</div>';
echo $return;
mysql_close($con);
?>
Why do I see the div 'project' change when I select one, but does'nt it change when it is created?
I tried to call the function manualy with adding this to the first php file. But it also doesn't work.
if ($countprojects == 1){
echo '<script type="text/javascript">
showContent('.$lastvalue.')
</script>';
}
sorry for my bad english, I hope you can help me solve this.
This is because there is only one option in your second drop down list. you cannot fire change event if there is only on or zero options in drop down list. what you can do is add this code where your first Ajax call get fired when selection changes. and place your second Ajax call in inside below code.
if ($('#selectproject').children().length == 1) {
// make sure you have imported latest jquery. if not add this inside HTMl head : <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
var selectedProject = $('#selectproject').children()[0].value;
showContent(selectedProject); // i hope this is the function you are calling when executing. if not please replace your function call here.
}
Having the issue here where my jquery work fine when viewing it as a single page however when I try and include that PHP file in another page either using php include or ajax the jquery doesnt seem to load.
I'm rather new to all this stuff so its very possible I'm doing something silly, any help would be greatly appreciated!
HTML Code
<html>
<head>
<script>
function showUser(str)
{
if (str=="")
{
document.getElementById("txtHint").innerHTML="";
return;
}
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET","getuser.php?q="+str,true);
//xmlhttp.open("GET","jquery.php?q="+str,true);
xmlhttp.send();
}
</script>
</head>
<body>
<form>
<select name="users" ID="option" onChange="showUser(this.value)">
<option value="">Select a person:</option>
<option value="1">ID One</option>
<option value="2">ID Two</option>
<option value="3">ID Three</option>
<option value="4">ID Four</option>
</select>
</form>
<br>
<div id="txtHint"><b>Person info will be listed here.</b></div>
</body>
</html>
PHP/Jquery
<html>
<head>
<link href="../../Styles/tablestyles.css" rel="stylesheet" type="text/css" />
<?php include "db.php" ?>
<script type="text/javascript" src="../../JS/tablesorter/jquery-latest.js"></script>
<script type="text/javascript" src="../../JS/tablesorter/jquery.tablesorter.js"></script>
<script type="text/javascript" src="../../JS/sorter.js"></script>
<script>
$(document).ready(function() {
// call the tablesorter plugin
$("table").tablesorter({
// sort on the first column and third column, order asc
sortList: [[0,0],[2,0]]
});
});
</script>
<?php
$q = intval($_GET['q']);
$result = mysqli_query($db_connection, "SELECT * FROM student WHERE Student_Id = '".$q."' or Student_Id = 7");
echo "<table id=\"myTable\" class=\"tablesorter\">
<thead>
<tr>
<th>Student ID</th>
<th>B-Code</th>
<th>First Name</th>
<th>Second Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
";
while($row = mysqli_fetch_array($result)) {
echo "<tr>";
echo "<td>" . $row['Student_Id'] . "</td>";
echo "<td>" . $row['B-code'] . "</td>";
echo "<td>" . $row['Student_Forename'] . "</td>";
echo "<td>" . $row['Student_Surename'] . "</td>";
echo "<td>" . $row['Student_Email'] . "</td>";
echo "</tr>";
}
echo"</tbody>
</table> ";
mysqli_close($con);
?>
Your AJAX request is going to getuser.php, which is what I'm going to assume your second code block represents? Basically instead of making a call to some PHP code that does your processing and sending you a response, you're actually calling back a PHP script AND an HTML page to boot, then embedding that into an existing page.
I recommend doing the following:
First, remove the HTML from getuser.php so that all you have left is the PHP code.
Then, in the page making the AJAX call, as part of your "success" function, include your sorter function so that it occurs after you've gotten your response and written out the new HTML. Something to the effect of the following:
getuser.php:
<?php include "db.php";
$q = intval($_GET['q']);
$result = mysqli_query($db_connection, "SELECT * FROM student WHERE Student_Id = '".$q."' or Student_Id = 7");
echo "<table id=\"myTable\" class=\"tablesorter\">
<thead>
<tr>
<th>Student ID</th>
<th>B-Code</th>
<th>First Name</th>
<th>Second Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
";
while($row = mysqli_fetch_array($result)) {
echo "<tr>";
echo "<td>" . $row['Student_Id'] . "</td>";
echo "<td>" . $row['B-code'] . "</td>";
echo "<td>" . $row['Student_Forename'] . "</td>";
echo "<td>" . $row['Student_Surename'] . "</td>";
echo "<td>" . $row['Student_Email'] . "</td>";
echo "</tr>";
}
echo"</tbody>
</table> ";
mysqli_close($con);
Then, in your calling page success code:
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
$("table").tablesorter({
// sort on the first column and third column, order asc
sortList: [[0,0],[2,0]]
});
}
}
Also, move your necessary CSS and JavaScript includes to the calling page as well so that you have your jQuery object available, etc. I would also recommend changing that code to use jQuery contructs and functions instead of raw JavaScript. It'll help keep your code clean, consistent, and easier to read :)
NOTE: I typed this up in a hurry, so anyone feel free to call me out and correct me on any mistakes.
Pretty much what I thnk is the issue is that when your jQuery script fires,the default functionality of the selector statements is select and do this on the current instances of this selector.
So if you do:
$(document).ready(function() {
// call the tablesorter plugin
$("table").tablesorter({
// sort on the first column and third column, order asc
sortList: [[0,0],[2,0]]
});
});
That finds all of the table tags on the page, and calls tablesorter on them. But, if additional table tags are added to the page, or the first table tag is added to the page when the page has already loaded, then jquery does not call table sorter onto it because it did not exist previously when it ran the $("table") selector.
This is not tested, but you can try and hook the .tablesorter onto the $("table") selector once everytime ajax finishes loading.
$( document ).ajaxComplete(function() {
$("table").tablesorter({
// sort on the first column and third column, order asc
sortList: [[0,0],[2,0]]
});
});
A similiar situation is when you use something like:
$( "#target" ).click(function() {
alert( "Handler for .click() called." );
});
The .click event is only bound to the #target elements that existed on the page when the page first loaded. Any subsequent #target elements added to the page later on will not have the .click event bound to them.
So say. You have header.php, where your script lives. Then you have index.php, and then you have table.php. If you include header.php inside index.php, the scripts inside header.php will effect the elements in index.php. But if you also include table.php inside of index.php, the scripts in header.php will not effect the elements in table.php unless you use the appropriate event binding like the .on() event below. I think...?
To resolve this, you have to use the .on event:
$( "#target" ).on( "click", function() {
alert( $( this ).text() );
});
The .on event will bind itself to all current, and later instances of the selector, in this example the selector is #target.
I want the browser to play a sound file when a new table row has been added to database.
This is my php file for the table. I'm using ajax for refresh.
I'm thinking that Javascript is going to be my solution. Do you have any ideas how to accomplish this?
show_table.php
<script src="ajax2.js"></script>
<script type="text/javascript"><!--
refreshdiv();
// --></script>
<div id="timediv"></br>
ajax2.js
var seconds = 1;
var divid = "timediv";
var url = "print_table.php";
function refreshdiv(){
var xmlHttp;
try{
xmlHttp=new XMLHttpRequest(); // Firefox, Opera 8.0+, Safari
}
catch (e){
try{
xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); // Internet Explorer
}
catch (e){
try{
xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e){
alert("Your browser does not support AJAX.");
return false;
}
}
}
fetch_unix_timestamp = function()
{
return parseInt(new Date().getTime().toString().substring(0, 10))
}
var timestamp = fetch_unix_timestamp();
var nocacheurl = url+"?t="+timestamp;
xmlHttp.onreadystatechange=function(){
if(xmlHttp.readyState==4){
document.getElementById(divid).innerHTML=xmlHttp.responseText;
setTimeout('refreshdiv()',seconds*1000);
}
}
xmlHttp.open("GET",nocacheurl,true);
xmlHttp.send(null);
}
var seconds;
window.onload = function startrefresh(){
setTimeout('refreshdiv()',seconds*1000);
}
print_table.php
$query = "SELECT * FROM $tablename ORDER BY time DESC LIMIT 50";
$result = mysql_query($query);
echo "<table class='gridtable'>
<tr>
<th>Time</th>
<th>Department</th>
<th>Priority</th>
<th>Destination</th>
<th>Comment</th>
<th>Status</th>
<th>Staff</th>
<th>Confirm</th>
</tr>";
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
echo "<tr>";
echo "<td>" . $row['time'] . "</td>";
echo "<td>" . $row['department'] . "</td>";
echo "<td>" . $row['priority'] . "</td>";
echo "<td>" . $row['destination'] . "</td>";
echo "<td>" . $row['comment'] . "</td>";
echo "<td>" . $row['status'] . "</td>";
echo "<td>" . $row['staff'] . "</td>";
echo "<td>Confirm</td>";
echo "</tr>";
}
echo "</table>";
?>
The Easiest Way
(Read-on below, I break this down)
HTML:
<!-- Include this in the HTML, if we wanted to play a flute sound -->
<audio id="audiotag1" src="audio/flute_c_long_01.wav" preload="auto"></audio>
Javascript:
// Replace: document.getElementById(divid).innerHTML=xmlHttp.responseText; with:
if(document.getElementById(divid).innerHTML != xmlHttp.responseText)
{
// Moving this line inside since there is no reason to update if the content is the same.
document.getElementById(divid).innerHTML=xmlHttp.responseText;
// Play sound
document.getElementById('audiotag1').play();
}
How to see if the table has changed:
If you just wanted to compare the HTML of the current to what is being returned, you could simply check the current contents of the table against the new table response. As an example, you could use something like this before the recursive timed-call to refreshdiv().
// If the table within divid ("timediv") is different, play an alert sound
if(document.getElementById(divid).innerHTML != xmlHttp.responseText)
{
// Play the sound here, the tables are different
}
However, this may not actually answer your question since you specifically asked for adding rows. The above would cover this, but would also register updates to existing rows as well.
You have the lines:
parseInt(new Date().getTime().toString().substring(0, 10))
and
var nocacheurl = url+"?t="+timestamp;
The first line you provided is outputting the current time in seconds since the epoch, using the timezone and date from the client. You are already passing this value per the query string which you can GET in the PHP with $_GET['t'] (second line). You could, in theory, rewrite quite a bit of your PHP code to return only new rows put into the database since that time and the last time polled. By returning only new rows, you could simply check to see if new tags are being sent, and incorporate them accordingly.
Two points of note if you do this:
Make sure to escape or parameterize your query if you pass the query-string through your MySQL query.
Be cautious of dates you are passing, since they are calculated based on the client's date-time. Consider relying on the server side time if possible.
And as for playing the sound
There is some detail on how to play sounds here: Playing audio with Javascript?
To play the audio, the easiest way is to use the audio tag (HTML5). The example given on http://www.storiesinflight.com/html5/audio.html is:
<audio id="audiotag1" src="audio/flute_c_long_01.wav" preload="auto"></audio>
Then you will need to call this audio by getting audio element and calling the play() method on it. So:
document.getElementById('audiotag1').play();