JQuery effect doesnt work for ajax content - php

I've got a table which is listing orders and I want to add the possiblity to filter results. Therefore I created a select field and an onchange effect in Jquery which is loading the same table with those filtered results into my Div. Therefore I used Ajax to update this "new Content" to my div. The problem is, that this table has several JQuery effects (for example a slide down when you click on a row) which doesn't work when the Content got created by the AjaxRequest. I have read some things already here in Stackoverflow and in other boards, but there was so many specific cases that I couldn't use any. I've heared something about a "init-function" which I need to call somewhere, so the JQuery things will also work on my Ajax generated content.
This is my Ajax Request:
$('.category').on('change', function (e) {
var optionSelected = $("option:selected", this);
var valueSelected = this.value;
$.ajax({
type: "POST",
url: "includes/listorders.php",
data: "filter=" + valueSelected,
success: function( data ) {
$( "#latestOrders" ).html(data);
}
});
});
This is what my listorders.php basically returns (probably not necessary to know to fix my issue):
$filter = $_POST['filter'];
//Prepare Queries
$lastOrders = "SELECT * FROM Orders ORDER BY dateAdded DESC LIMIT 0,48";
$ps_orders = $db->query($lastOrders);
$data = $ps_orders->fetchAll();
foreach($data as $row)
{
$orderid =$row['id'];
$username = $row['name'];
$done = $row['refsDone'];
$quantity = $row['quantity'];
$running =$row['refsRunning'];
$untouched = $quantity - ($done+$running);
?>
<tr class="header mySlideToggler" data-id="<? echo $orderid ?>">
<td class="align-center">TEST<? echo $username ?></td>
<td>0 %</td>
<td>22 Aug 2014</td>
<td><? echo $done . " / " . $quantity ?></td>
<td><? echo $running ?></td>
<td><? echo $untouched ?></td>
<td>
</td>
</tr><tr style="padding: 0"><td colspan="7" style="padding: 0">
<div class="accounts" style="display: none">
</div>
</td></tr>
<?
}
?>
My Slide effect including another Ajax request for the content which should be displayed into the slided div:
// Slide effect for listing account information to an order
$('.mySlideToggler').click(function( event ){
event.preventDefault();
event.stopPropagation();
var id = $(this).data('id');
var div = $(this).closest('tr').next().find('.accounts');
$.ajax({
type: "POST",
url: "includes/listaccounts.php",
data: "orderid=" + id,
success: function( data ) {
div.html(data);
}
});
$(this).closest('tr').next().find('.accounts').slideToggle();
});

You need to make sure to use the new live version of event listeners, to work with content loaded asynchronously
$('body').on('click', '.my-class', function(){
//handle click event for .my-class here
});
The above code is not specific to your situation, since you have not posted the js code that is not working on async content. It's just a sample of how you manage live event listeners.
Specific answer after reviewing your code update:
$('body').on('click', '.mySlideToggler', function(event){
//do toggle stuff here
});
Why?
The jQuery .click does not support events happening on content loaded asynchronously. The same problem applies to using the following code:
$('.mySlideToggler').on('click', function(event){
//THIS WONT WORK WITH ASYNC CONTENT
});
This is why jQuery has allowed us to register the event on a parent element that was not loaded asynchronously and the provide a second argument to .on that tells us which child of that element to listen for as a target or said event. This works with all events, click|change|focus|blur|etc...
Why $('body')
I generally attach these live handlers to the body of the html document because the body is rarely reloaded via async content, as reloading the entire content would probably warrant a new page load, however it's not necessary to use body. You can attach to any parent element that is static on the page, including document or window
Nice to know
jQuery formerly used the method .live() which has been deprecated for a while now, I think since 1.7
I suggest you read more about the change to .live here: http://api.jquery.com/live/
I hope this has sufficiently answered your question. Let me know if you're still having trouble.
Performance Concern
Attaching the parent object of the .on event as close to the child element as possible will increase performance if you are using a large number of these events, as jQuery doesn't have to traverse as far down the DOM Tree to find the child element.
More info here: http://api.jquery.com/on/#event-performance

Related

Codeigniter 3 application: update MySQL table column and the corresponding view through Ajax

I am working on a Register and Login application with CodeIgniter 3 and Twitter Bootstrap.
I have a "users" MySQL table and a corresponding "users.php" view that renders the "users" table in an HTML format, like the image below illustrates:
The "Actions" column in the Bootstrap table has, on each row, an "Enable" or "Disable" button, depending on the state of he user. The code for this part of the view is:
// Status column
<td>
<?php if ($user->active == 1) {
echo '<span class="text-success">' . 'Enabled' . '</span>';
} else {
echo '<span class="text-danger">' . 'Disabled' . '</span>';
}
?>
</td>
// Enable/Disable buttons
<?php if ($user->active == 1) { ?>
<span class="glyphicon glyphicon-ban-circle"></span> Disable
<?php } else { ?>
<span class="glyphicon glyphicon-ok"></span> Enable
<?php } ?>
I activate/deactivate users without page refresh, via AJAX:
$('.state-change').on('click', function(evt) {
evt.preventDefault();
var id = $(this).data('id');
var role = $(this).data('role');
if (role == "activate") {
var stateUrl = 'users/activate/';
} else {
var stateUrl = 'users/deactivate/';
}
$.ajax({
url: stateUrl + id,
method: 'GET',
dataType: 'php',
success: function(){
console.log(id);
console.log(role);
}
});
});
The problem is that the data regarding the state of the user does not come back to the view and the columns "Status" and "Actions" do not render correctly.
I wish I didn't have to update the view "statically" from the success callback, with jQuery's html() method or something similar.
function(){
console.log(id);
console.log(role);
//change columns html here
}
What shall I do to update the view "dynamically"?
The above answers are adequate - you must use JavaScript given your scenario. It seems the trouble lies in making the leap from dynamic web pages to dynamic HTML.
Read the last line of the summary here:
https://en.wikipedia.org/wiki/Dynamic_HTML
You will need to use javascript to modify your table after you get the data back. Since you're already using jQuery, you have tools to make that pretty simple.
Your problem can be broken into two steps: Identify the right part of the page to update, and then modify the cells of interest.
Identifying the right cells is simplified because the mouse event passed to your function includes a reference to the thing that was clicked.
To make finding the right parts of the table easier, it's good to give each <td> a class:
// Status column
<td class="status-column">
// your php status stuff from above
</td>
// Button column
<td class="activate-column">
// your php button-drawing stuff from above
</td>
Now it will be easy to find what you're looking for to modify.
Here's your ajax call with a few additions to redraw the cells in question:
$('.state-change').on('click', function(evt) {
evt.preventDefault();
var id = $(this).data('id');
var role = $(this).data('role');
if (role == "activate") {
var stateUrl = 'users/activate/';
} else {
var stateUrl = 'users/deactivate/';
}
$.ajax({
url: stateUrl + id,
method: 'GET',
dataType: 'php',
success: function(){
console.log(id);
console.log(role);
// find the row that is the parent of the clicked button - http://api.jquery.com/parent/
var row = evt.target.parent('tr');
// use the class of the table cell to identify it. http://api.jquery.com/find/
var statusCell = row.find('.status-column').first();
// now put in the new status. http://api.jquery.com/html/
if (role == "activate") {
statusCell.html('<span class="text-success">Enabled</span>');
} else {
statusCell.html('<span class="text-danger">Disabled</span>');
}
}
});
});
I'll leave the button column for you to practice with :).
Edit: you can also manipulate the DOM with non-jQuery methods that are perhaps more to your liking. This is what jQuery is doing under the hood anyway.
You can read more about them at MDN.
// build the new DOM node
var newStatusCellContent = document.createElement('span');
newStatusCellContent.setAttribute('class', role == 'activate' ? 'text-enabled' : 'text-danger');
newStatusCellContent.textContent = role == 'activate' ? 'Enabled' : 'Disabled';
// get the parent <td> node from the jQuery object
var statusCell = row.find('.status-column').get(0);
// swap the old contents for the new
var oldChild = statusCell.childNodes[0]
statusCell.replaceNode(newStatusCellContent, oldChild);
Careful study of the documentation at the above link will probably reveal ways to make that more efficient for your particular case. Keep in mind that this is the same thing the jQuery html() method does — or Angular or any other — and that while it keeps you away from HTML, it doesn't really improve your code in this case. I really hate HTML, but it's the tool we're given.
Note that php also has DOM libraries; if you wanted, you could use those to build your original page as well, and be done with HTML forever. But I don't recommend it except in certain cases.

jQuery / php / mysql - how to manipulate a mysqli_query without reloading the page?

I have a table containing data read from a MySQL database via PHP. The first column holds all item names. Now, on clicking a td element in the first column of the table would link to a page with more detailed information about the item contained in the td.
Now I came up with the following idea:
$(document).ready(function() {
$('#table td:first-child').click(function() {
$('div.main').animate({
height: "50px"
}, 600);
setTimeout(function() {
$('div.data').fadeIn(1000);
}, 600);
});
});
div.main is the div-container that has the table included. What I want to do now is to slide that container up and fade a new div-container in, right below it, the new container include()s a PHP page which holds a dynamic query (pseudocode, no string escaping, simplified version):
SELECT detail FROM items WHERE items.name = $_GET['name'];
What I couldn't figure out is if and how I can tell the PHP file that is included in the in-fading div-container which item name it has to grab details for, off the database.
Right now I can read the item name via JavaScript/jQuery, but I couldn't figure a way out to pass that value to the PHP file without having to reload the page.
Any ideas or suggestions welcome!
I think what you're looking for is asynchronous JavaScript and XML (AJAX). It sounds intimidating, but fortunately jQuery makes it very easy.
You can call $.ajax() directly, but for most cases, you can use one of the convenience wrappers. In this case, I think $.load() will meet your needs.
So, let's say your PHP file is called detail_ajax.php and it returns the HTML you wish to put in your div (with class data). All you would have to do then is this:
$('div.data').load( '/detail_ajax.php', function(data){
$(this).html(data);
});
If you want to pass data TO detail_ajax.php, you can pass it along this way:
$('div.data').load( '/detail_ajax.php', { 'someField' : 'someValue' },
function(data) {
$(this).html(data);
}
});
In detail_ajax.php, if you examine $_POST['someField'], you will see the value passed in.
You can do this by using ajax. Output your query on a separate page in JSON format then fetch it using jquery ajax
you need to use ajax to do the same thing. create an event like onclick and call a
method on click call ajax set variable in js and pass it to and do as you want,
show data in particular div in response. Hope it will help you.
You are looking for $.ajax(). However, 3 things will need to take place for this to happen as you intend.
First, we need a reference held in the HTML that is generated by the table so we can streamline the server request. When you generate the table, add a unique data-name string to the TD.
<td data-name="<?php echo $row['name']; ?>">
If, for instance, the td's were generated in a foreach loop, where we expect an array to be returned.
Now, we need to detect the request on our page so we can properly return the data to the browser, we'll look for $_GET['name'] as per your example.
<?php
if(isset($_GET['name'])):
$mysqli = new mysqli('host', 'user', 'pass', 'db');
$ret;
if($stmt = $mysqli->prepare('SELECT detail FROM items WHERE items.name = ?')):
$stmt ->bind_param('s', $_GET['name']);
$stmt ->execute();
$stmt ->bind_result($details); // we only want one column
$stmt ->fetch(); //get our row
$ret['success'] = TRUE;
$ret['html'] = '<div>'. $details .'</div>';
else:
$ret['success'] = FALSE;
endif;
echo json_encode($ret); //return to the browser
endif;
?>
Now we need to employ ajax to bridge the gap between the server and the browser.
Edit - I forgot to modify the click function.
$('#table td:first-child').click(function() {
$('div.main').animate({
height:'0px'
}, function(){
//once the animation completes
$.ajax({
url: '/',
type: 'GET', //this is default anyway
data:{name: $(this).data('name')}, //send the name from the td clicked
dataType: 'json', //what we expect back from the server
success: function(data){ //will fire when complete. data is the servers response
if(data.success !== false){
$('div').html(data.html);
$('div.main').animate({
height: "50px"
}, 600);
}else{
alert("Something went wrong");
}
}
});
}, 600);
});

Opening jQuery UI Dialog box with dynamic content

I have a question about jQuery UI Dialog boxes and showing dynamic content from a database.
So I got a webapplication where I also need to make a admin module to manage all users and other information. I created a page that shows all users in a list, in every row I also made an edit button. I wanted to make it so that when you press on a users' edit button, a dialog box opens and shows all the user information and stuff in the dialog box.
So my question is, what is the best way to do this? I was thinking about making a PHP page where I execute the MySQL Query and show that in the dialog box, but I am sure there are better ways..
EDIT: Here is the code for the page as it is right now. I added a small placeholder dialogbox that I used for testing purposes.
Javascript:
script type="text/javascript">
jQuery(document).ready( function(){
jQuery(".edit-button").click( showDialog );
//variable to reference window
$myWindow = jQuery('#myDiv');
//instantiate the dialog
$myWindow.dialog({ height: 600,
width: 800,
modal: true,
position: 'center',
autoOpen:false,
title:'Bewerk therapeut',
overlay: { opacity: 0.5, background: 'black'}
});
}
);
//function to show dialog
var showDialog = function() {
$myWindow.show();
//open the dialog
$myWindow.dialog("open");
}
var closeDialog = function() {
$myWindow.dialog("close");
}
PHP:
<?php
//LEFT OUTER JOIN Vragen ON Vragen.bsn_nummer = Gebruikers.bsn_nummer
include_once 'classes/class.mysql.php';
$db = new Mysql();
$dbUsers = new Mysql();
$db->Query("SELECT * FROM USERS_users ORDER BY username ASC");
$db->MoveFirst();
echo "<table>";
echo "<tr><th> </th><th> </th><th>BSN Nummer</th><th>Gebruikersnaam</th> <th>Voornaam</th><th>Achternaam</th></tr>";
while(! $db->EndOfSeek()) {
$row = $db->Row();
$dbUsers->Query("SELECT * FROM Gebruikers WHERE user_idnr = '{$row->user_idnr}'");
$rowUser = $dbUsers->Row();
echo "<tr><td><a class='del-button' href='#'><img src='afbeeldingen/edit-delete.png' /></a></td>
<td><a class='edit-button' href='#'><img src='afbeeldingen/edit.png' /></a> </td>
<td>".#$rowUser->bsn_nummer."</td>
<td>".#$row->username."</td>
<td>".#$rowUser->voornaam."</td>
<td>".#$rowUser->achternaam."</td></tr>";
}
echo "</table>";
?>
<div id="myDiv" style="display: none">
<p>Gebruiker bewerken</p>
</div>
Nope. Sounds like you've got it right.
placeholder for the popup ->
<div id="popup"></div>
jQuery ui dialog ->
$('#popup').dialog({
autoOpen: 'false',
modal: 'true',
minHeight: '300px',
minWidth: '300px',
buttons: {
'Save Changes': function(){
$.ajax({
url: 'path/to/my/page.ext',
type: 'POST',
data: $(this).find('form').serialize(),
success: function(data){
//some logic to show that the data was updated
//then close the window
$(this).dialog('close');
}
});
},
'Discard & Exit' : function(){
$(this).dialog('close');
}
}
});
Now that the default settings have been created, send a ajax request for the data from the php file, and update the content in the 'popup' div.
$('.edit').click(function(e){
e.preventDefault();
$.ajax({
url: 'path/to/my/page.ext',
type: 'GET',
data: //send some unique piece of data like the ID to retrieve the corresponding user information
success: function(data){
//construct the data however, update the HTML of the popup div
$('#popup').html(data);
$('#popup').dialog('open');
}
});
});
in the PHP page, construct a form to be sent back ->
<?php
if(isset($_GET['id'])){
//build the query, do your mysql stuff
$query = mysql_query(sprintf("SELECT * FROM sometable WHERE id = %d", $_GET['id']));
//construct constant objects outside of the array
?>
<form>
<?php
while($row = mysql_fetch_array($query)){
?>
<tr>
<td>
<input type="text" name="<?php echo $row['id']?>" value="<?php echo $row['name'] ?>" />
</td>
</tr>
<?php
}
?>
</form>
<?php
}
?>
I am sure there are better ways..
No, that's about it.
You'll need a PHP script to give you the user's current details, and a second in which you should combine adding a new user, or updating an existing user.
Use AJAX to obtain the list of users, and likewise have the "current detail" page send back an JSON blob containing the information.
Use the client side Javascript to populate the dialog itself.
The hardest part is making sure that only authorised users can talk to the backend scripts.
Here's what I would do:
when creating the list of users, I know the id (unique) for each user. Then attach an event handler for the edit button that will make an ajax request to a server side script with that user id, the server side script will send you user details in JSON format.
have a template, for example a div, that has all the fields you need for updating user details (with classes attached or ids so you will know how to find them with selectors). when you receive data from the server you set the value of the fields in your template to the data in the response of the server then open the dialog (which is pre populated now with the data you need).
updating user details can also be done by ajax, to keep things simple. (grabbing the values in the inputs, and send a request to the server, sending also the id of the user you want to change details.
So... good luck!
The simplest way would be to get the information in the database using PHP, and populate the UI tables like that. The major downside would be loading time. If you find that the page is taking too long to load, then you may want to look into jQuery's .ajax()

jquery and ajax page refreshing issue

I am fetching a problem though I know it's not a big issue, but something is different to me as I new. I have a page which has a list of records, fetching from a database. Now one button is there , after clicking the records, one pop up will be opened up along with some data. Inside that pop up one another link is there called "restore", whenever , that linked will be clicked out the database has been updated. Now up to this its okay for me. But whenever, I close the pop up, my list of records should automatically changed as some records have been restored. But I am not getting the result until and unless I do not refresh the page. so how can I do this, please help me ....
$(function() {
$(".delete").click(function() {
$('#load').fadeIn();
var commentContainer = $(this).parent();
var id = $(this).attr("id");
var string = 'id='+ id ;
$.ajax({
type: "POST",
url: "restore-request-process.php",
data: string,
cache: false,
success: function(){
commentContainer.slideUp('slow', function() {$(this).remove();});
$('#load').fadeOut();
}
});
//return false;
});
});
in the restore-request-process.php page I just update the database and echo the id.
After the database update, call a function to update the front end or simply reload page using location.reload()
you need to have declared global function in parent window
function Update(){
//global function in parent, update div
}
on popup window call function
window.opener.Update();
that will automatic reload your div, and not all page, If it's not necessary
Suppose this is your listing format
<table>
<?php
foreach($results as $result) { ?>
<tr id="my_div">
<td><?php echo $result->name?></td>
<td class="delete" id="<?php echo $result->id?>"><img src="delete.png"/></td>
</tr>
<?php } ?>
</table>
In restore-request-process.php write a query which fetch all the result from database and just echo the result like this
$result = mysql_query("SELECT * FROM my_table");
while($row = mysql_fetch_array($result))
{
echo '<td>'. echo $row["name"].'</td>
<td class="delete" id="'. echo $row["id"].'"><img src="delete.png"/></td>' ;
}
and onsuccess replaced all the content inside the my_div with response text
CODE IS NOT TESTED
for more references you can go through this link

Stop jQuery animations

My JavaScript is as follows:
$.get("/<page>.php", "userid='.$userid.'&"+status, function(data){
$("#status").show("fast").html(data).delay(4000).hide("fast");
});
I have many links on a page that will load this jQuery AJAX and display the status in a div correctly. It all works fine, except if a user click many of the links really fast. The data changes correctly, but the animations are delayed. I've tried including the jQuery stop() and stop(true) and stop(true, true) before the .show but it doesn't seem to help much. Animations can continue long after the last click; for example, if a user clicks 20 times, and then pauses, the hide animations seem to continue long afterwards, despite the stop(). What I want is if a user clicks on another link that causes the AJAX to cause a status display, the basically "resets" the status animations.
Any ideas?
Here's the full relevant JavaScript:
<script type="text/javascript">
...
$(document).ready(function () {
$("#entry a.styled").live("click", function(event){
var status = $(this).attr("rel")+"&game="+$(this).attr("name");
var teamid = $(this).attr("rel");
var gameid = $(this).attr("name");
$("[name="+gameid+"]").show(1);
$(this).hide(1);
$("[rel=t"+teamid.replace("pick=", "")+"]").removeClass();
$("[name=t"+gameid+"]").removeClass();
$("#t"+teamid.replace("pick=", "")).addClass("hilite");
$.get("/<filename>.php", "userid=1&"+status, function(data){
$("#status").stop(true, true).show("fast").html(data).delay(4000).hide("fast");
});
});
</script>
and some relevant HTML, this is within a larger table:
<tr class="row-a">
<td>8-man</td>
<td>1:00 pm</td>
<td class="hilite" id="t298" rel="t233" name="t3235">La Veta</td>
<td>Pick</td>
<td><img src="/images/delete.png" height="12" width="12" /></td>
<td>Pick</td>
<td id="t233" rel="t298" name="t3235">South Park**</td>
<td> </td>
</tr>
The user would click on the "Pick" link or the delete Image which calls the jQuery AJAX get.
Any other improvements to my (limited shown) code are appreciated as well.
jquery version:1.4.2
jqueryui version:1.7.2
Maybe stop() doesn't clear the delay() -- have you tried the .clearQueue() method?
alternatively, you could try with setTimeout rather than delay()...
// animInProgress and animDelay are global variabes
var animInProgress = false;
var animDelay;
//later, in your $.get success function...
$("#status").show("fast").html(data);
if(animInProgress) {
clearTimeout(animDelay);
}
animInProgress = true;
animDelay = setTimeout(function() {
$("#status").hide("fast");
animInProgress = false;
}, 4000);

Categories