deleting mysql records with ajax - php

I would like to know the best way to delete records from a live database and refresh the page instantly. At the moment I am using ajax, with the following javascript method:
function deleterec(layer, pk) {
url = "get_records.php?cmd=deleterec&pk="+pk+"&sid="+Math.random();
update('Layer2', url);
}
if cmd=deleterec on the php page, a delete is done where the primary key = pk. This works fine as in the record is deleted, however the page is not updated.
My update method is pretty simple:
function update(layer, url) {
var xmlHttp=GetXmlHttpObject(); //you have this defined elsewhere
if(xmlHttp==null) {
alert("Your browser is not supported?");
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 || xmlHttp.readyState=="complete") {
document.getElementById(layer).innerHTML=xmlHttp.responseText;
} else if (xmlHttp.readyState==1 || xmlHttp.readyState=="loading") {
document.getElementById(layer).innerHTML="loading";
}
//etc
}
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}
how to delete or alter record, and upate the page.
At the moment my ajax framework works by passing data to a javascript update method, which works fine for selecting different queries to display in different layers.
I want to add the functionality to delete, or alter the records in a certain way.
I am wondering if it is possible when clicking a link to execute a query and then call my update method and refesh tge page. Is there any easy way to do this given my update methods?
I would like to avoid rewriting my update method if possible.
WOuld the simplest method be to have the php page(only in the layer) reload itself after executing a mysql query?
Or to make a new "alterstatus" method, which would pass delete or watch as a paramter, and have the php execute a query accordingly and then update the page?
edit: The links are generated like so. deleterec would be called from an additional link generated.
{
$pk = $row['ARTICLE_NO'];
echo '<tr>' . "\n";
echo '<td>'.$row['USERNAME'].'</td>' . "\n";
echo '<td>'.$row['shortDate'].'</td>' . "\n";
echo '<td>'.$row['ARTICLE_NAME'].'</td>' . "\n";
echo '<td>'.$row['ARTICLE_NAME'].'</td>' . "\n";
echo '</tr>' . "\n";
}
edit: the update method can not be modified, as it is used by the updateByPk and updateBypg methods which need a layer.

Without digging too much into your code specifics, I don't know of any way to update/delete from the server side DB without doing a round trip (either AJAX or a page navigation). I would however recommend using a JavaScript framework (like jQuery, or something else) to handle the AJAX and DOM manipulations. That should, in theory, alleviate any cross-browser troubleshooting on the client side of thinbs.

When you say "update instantly" I presume you mean update the Document via Javascript. Ajax and page refreshes don't go together.
How are you displaying your existing rows of data? Say for example you were listing them like this:
<div id="row1">row 1</div>
<div id="row2">row 2</div>
Where row1 and row2 are rows in your database with primary keys 1 & 2 respectively. Use a simple javascript function to remove the associated div from the DOM:
function deleterec(pk) {
url = "get_records.php?cmd=deleterec&pk="+pk+"&sid="+Math.random();
update(pk, url);
}
function update(pk, url) {
var xmlHttp=GetXmlHttpObject(); //you have this defined elsewhere
if(xmlHttp==null) {
alert("Your browser is not supported?");
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 || xmlHttp.readyState=="complete") {
document.getElementById(layer).innerHTML=xmlHttp.responseText;
removeDomRow(pk); //You may wish to check the response here
} else if (xmlHttp.readyState==1 || xmlHttp.readyState=="loading") {
document.getElementById(layer).innerHTML="loading";
}
}
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}
And the following function to manipulate the DOM:
function removeDomRow(pk){
var row = document.getElementById('row' + pk);
row.parentNode.removeChild(row);
}
If you're using tables:
<tr id="row1">
<td>row 1</td>
</tr>
<tr id="row2">
<td>row 2</td>
</tr>
You could use:
function removeDomRow( id ) { // delete table row
var tr = document.getElementById( 'row' + id );
if ( tr ) {
if ( tr.nodeName == 'TR' ) {
var tbl = tr; // Look up the hierarchy for TABLE
while ( tbl != document && tbl.nodeName != 'TABLE' ) {
tbl = tbl.parentNode;
}
if ( tbl && tbl.nodeName == 'TABLE' ) {
while ( tr.hasChildNodes() ) {
tr.removeChild( tr.lastChild );
}
tr.parentNode.removeChild( tr );
}
}
}
In respect to theraccoonbear's point, if you were to make use of a framework such as Qjuery things would be far easier:
$('#row'+id).remove();

I am wondering if it is possible when clicking a link to execute a query and then call my update method and refesh tge page. Is there any easy way to do this given my update methods?
So, why don't you just submit a form?

You have two choice:
Do a complete round trip, ie don't update the UI until you know the item has been successfully deleted, OR
Lie to your users
If the results of the operation are questionable and important, the use the first option. If you're confident of the result, and people don't need to know the details, use the second.
Really, nothing keeps people happy so much as being successfully lied to.

I would not use a HTTP GET method to delete records from the database, I would use POST. And I would not use Ajax since the interaction you are looking for is clearly synchronous : delete then update. I would use a regular submit (either JS or HTML).
That said, the only remaining solution if you are really committed to use XHR is a callback based on response from the server like suggested by Renzo Kooi.

You could create a callback that at the client side takes care of updating the screen. You can do that within your XHR function.
function update(layer, url) {
var xmlHttp=GetXmlHttpObject(),
callbackFn = function(){
/* ... do thinks to reflect the update on the user screen,
e.g. remove a row from a table ...*/
};
if(xmlHttp==null) {
alert("Your browser is not supported?");
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 || xmlHttp.readyState=="complete") {
/* if the server returns no errors run callback
(so server should send something like 'ok' on successfull
deletion
*/
if (xmlHttp.responseText === 'ok') {
callback();
}
//=>[...rest of code omitted]

To Delete and update DOM:
echo '<td>'.$row['ARTICLE_NAME'].'</td>' . "\n";
function deleterec(row, pk) {
var rowId = row.parentNode.parentNode.rowIndex;
url = "get_records.php?cmd=deleterec&pk="+pk+"&sid="+Math.random();
update(rowId, url);
}
function update(rowId, url) {
var xmlHttp=GetXmlHttpObject(); //you have this defined elsewhere
if(xmlHttp==null) {
alert("Your browser is not supported?");
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 || xmlHttp.readyState=="complete") {
document.getElementById(layer).innerHTML=xmlHttp.responseText;
deleteRow(rowId); //You may wish to check the response here
} else if (xmlHttp.readyState==1 || xmlHttp.readyState=="loading") {
document.getElementById(layer).innerHTML="loading";
}
}
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}
function deleteRow(i){
document.getElementById('myTable').deleteRow(i)
}

I would have voted up one of the other answers that recommended jQuery, but I don't have enough points yet.
I think the easiest way to achieve the "update" you're looking for is to either have your AJAX delete return the relevant post-delete HTML, or you could use jQuery to fire off the delete and then delete the tr, div, etc. from the page.
jQuery.post("get_records.php ", { cmd: "delete", pk: 123 }, function() {
jQuery("tr.row123").remove();
})

I have found that there are three basic operations that one performs with an Ajax based administration page, update, delete and append. Each of these actions changes the DOM in inherently different ways.
You've written a function that can update an existing div in the DOM, but this function won't work well if you want to remove a div from the DOM like you do in this question nor will it work well when you decide that you want to add new records using Ajax.
In order to handle this correctly, you first need to assign an unique id to each row that you output:
$pk = $row['ARTICLE_NO'];
echo '<tr id=\"article_' . $pk . '\">' . "\n";
echo '<td>'.$row['USERNAME'].'</td>' . "\n";
echo '<td>'.$row['shortDate'].'</td>' . "\n";
echo '<td>'.$row['ARTICLE_NAME'].'</td>' . "\n";
echo '<td>'.$row['ARTICLE_NAME'].'</td>' . "\n";
echo '</tr>' . "\n";
And then you need to create a delete function that can remove the table row:
function delete(layer, url) {
var xmlHttp=GetXmlHttpObject(); //you have this defined elsewhere
if(xmlHttp==null) {
alert("Your browser is not supported?");
}
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4 || xmlHttp.readyState=="complete") {
if(xmlHttp.responseText == 'result=true') {
// Here you remove the appropriate element from the DOM rather than trying to update something within the DOM
var row = document.getElementById(layer);
row.parentNode.removeChild(row);
}
} else if (xmlHttp.readyState==1 || xmlHttp.readyState=="loading") {
document.getElementById(layer).innerHTML="loading";
}
//etc
}
xmlHttp.open("GET",url,true);
xmlHttp.send(null);
}
And then lastly adjust your deleterec function:
function deleteRec(layer, pk) {
url = "get_records.php?cmd=deleterec&pk="+pk+"&sid="+Math.random();
delete(layer, url);
}
As a final note I have to echo the sentiments of others that have suggested the usage of a framework. The usage of any framework be it jQuery, Prototype, Dojo or other, is going to have both short term and long term benefits. Additionally, I would NEVER actually use GET to perform an operation of this nature. All that one has to do to force the deletion of an element is hit the appropriate URL and pass in the relevant article number.

Related

Can i send parameter to php controller using javascript but without jquery or ajax?

well the question is enough explained can it be done.
what I am trying to do is to get data from a popup and onclose I want to send the content I retrieved to a php controller for processing.
But I dont want to use jquery library, because it is creating a conflict for me.
Update
window.onbeforeunload = confirmExit;
function confirmExit()
{
var a = document.getElementsByTagName("div");
for (i = 0; i < a.length; i++) {
if(a[i].className == 'Ymacs-frame-content'){
var b = a[i].getElementsByTagName("div").innerHTML;
//alert(b);
}
}
//Ajax should be here
window.onbeforeunload = reloadOpener;
if (top.opener && !top.opener.closed) {
try {
opener.location.reload(1);
}
catch(e) { }
window.close();
}
}
window.ununload=function() {
reloadOpener();
}
You can just use jquery-less AJAX:
var a = new XMLHttpRequest();
a.open("GET","myscript.php?var=foo&othervar=bar",true);
a.onreadystatechange = function() {
if( this.readyState == 4) {
if( this.status == 200) {
// data sent successfully
// response is in this.responseText
}
else alert("HTTP error "+this.status);
}
};
a.send();
Alternatively, you can create an iframe tag and point it to the right page. You can even create a form and post it to the frame if needed.
You can do it in javascript without using jQuery since that is all jQuery does in the background. You will need to look at the different ways IE does it compared to other browsers though.
Yes, XMLHttpRequest, but you'll need to account for differences in browsers, which jQuery does for you.
I just went through this. The only way to use Javascript to pass info to PHP is by using XMLHttpRequest, or at least if there is another way I did not find it. It has to do with the fact that PHP renders on the server side, and Javascript isn't executed until after it is served to the client...unless you use the XHR which is...AJAX.

Javascript/PHP to update innerHTML of multiple items

I'm trying to to use Javascript to update the innerHTML of a webpage after an onclick event. My Javascript (java.js) uses this code to access a PHP page which echoes back the text that goes in the innerHTML. The thing is, I want to update the innerHTML of two items (a "color" table and an "item" table) which are not located next to each other and have different element ID's. Each call from java.js works fine individually (like if one is commented out), but when both of them are run, whichever one is first will get stuck on the "loading" message and the second one will work. Loading "content.php?item='5'&color='5'" in a web browser shows both tables.
I suspect this is something to do with the mechanics of $_GET[] (which I don't totally understand; this is my first time working with PHP). But the calls should happen sequentially and the keys ('item' and 'color') don't conflict, so I can't figure out what's going wrong.
java.js:
function makeActive(active_tab) {
//item table
callAHAH('content.php?item='+active_tab, 'item', 'getting items for tab '+active_tab+'. Wait...', 'Error');
//color table
callAHAH('content.php?color='+active_tab, 'color', 'getting colors for tab '+active_tab+'. Wait...', 'Error');
}
content.php:
if (isset($_GET['color'])) {
require 'color.php';
$index = 1*$_GET['color'];
$arr = $ITEM_TYPES[$index];
echoColorTable($arr); //makes table in color.php
} else {
echo "color not set "; //debug
}
if (isset($_GET['item'])) {
require 'item.php';
$index = 1*$_GET['item'];
echoItemTable($index); //makes table in item.php
} else {
echo "item not set "; //debug
}
The problem is with the callAHAH function you linked to. It doesn't have a var keyword when it declares req. So it is a global variable and there can only ever be one request at once. It also reuses that global variable in the responseAHAH function. In general global variables are a bad idea for reasons like this. I recommend ditching the callAHAH function altogether and using something like this which does the exact same thing without using a global variable:
function loadInto(url, id, loading, error) {
var ajax;
var el = document.getElementById(id);
el.innerHTML = loading;
if (typeof XMLHttpRequest !== 'undefined')
ajax = new XMLHttpRequest();
else // Some people still support IE 6
ajax = new ActiveXObject("Microsoft.XMLHTTP");
ajax.onreadystatechange = function(){
if(ajax.readyState === 4){
if(ajax.status == 200){
el.innerHTML = ajax.responseText;
}else{
el.innerHTML = error;
}
}
};
ajax.open('GET', url);
ajax.send();
}
It's also not named callAHAH, and that's always a plus.

Use Jquery to update a PHP session variable when a link is clicked

I have several divs that a user can Minimize or Expand using the jquery toggle mothod. However, when the page is refreshed the Divs go back to their default state. Is their a way to have browser remember the last state of the div?
For example, if I expand a div with an ID of "my_div", then click on something else on the page, then come back to the original page, I want "my_div" to remain expanded.
I was thinking it would be possible to use session variables for this, perhaps when the user clicks on the expand/minimize button a AJAX request can be sent and toggle a session variable...IDK..any ideas?
There's no need for an ajax request, just store the information in a cookie or in the localstorage.
Here's a library which should help you out: http://www.jstorage.info/
Some sample code (untested):
// stores the toggled position
$('#my_div').click(function() {
$('#my_div').toggle();
$.jStorage.set('my_div', $('#my_div:visible').length);
});
// on page load restores all elements to old position
$(function() {
var elems = $.jStorage.index();
for (var i = 0, l = elems.length; i < l; i++) {
$.jStorage.get(i) ? $('#' + i).show() : hide();
}
});
If you don't need to support old browsers, you can use html5 web storage.
You can do things like this (example taken from w3schools):
The following example counts the number of times a user has visited a
page, in the current session:
<script type="text/javascript">
if (sessionStorage.pagecount) {
sessionStorage.pagecount=Number(sessionStorage.pagecount) +1;
}
else {
sessionStorage.pagecount=1;
}
document.write("Visits "+sessionStorage.pagecount+" time(s) this session.");
</script>
Others have already given valid answers related to cookies and the local storage API, but based on your comment on the question, here's how you would attach a click event handler to a link:
$("#someLinkId").click(function() {
$.post("somewhere.php", function() {
//Done!
});
});
The event handler function will run whenever the element it is attached to is clicked. Inside the event handler, you can run whatever code you like. In this example, a POST request is fired to somewhere.php.
I had something like this and I used cookies based on which user logged in
if you want only the main div don't use the
$('#'+div_id).next().css('display','none');
use
$('#'+div_id).css('display','none');
*Here is the code *
//this is the div
<div id = "<?php echo $user; ?>1" onclick="setCookie(this.id)" ><div>My Content this will hide/show</div></div>
function setCookie(div_id)
{
var value = '';
var x = document.getElementById(div_id);
var x = $('#'+div_id).next().css('display');
if(x == 'none')
{
value = 'block';
}
else
{
value = 'none';
}
console.log(div_id+"="+value+"; expires=15/02/2012 00:00:00;path=/")
//alert(x);
document.cookie = div_id+"="+value+"; expires=15/02/2012 00:00:00;path=/";
}
function getCookie(div_id)
{
console.log( div_id );
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++)
{
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==div_id)
{
return unescape(y);
}
}
}
function set_status()
{
var div_id = '';
for(var i = 1; i <= 9 ; i++)
{
div_id = '<?php echo $user; ?>'+i;
if(getCookie(div_id) == 'none')
{
$('#'+div_id).next().css('display','none');
}
else if(getCookie(div_id) == 'block')
{
$('#'+div_id).next().slideDown();
}
}
}
$(document).ready(function(){
get_status();
});
Look about the JavaScript Cookie Method, you can save the current states of the divs, and restore it if the User comes back on the Site.
There is a nice jQuery Plugin for handling Cookies (http://plugins.jquery.com/project/Cookie)
Hope it helps
Ended up using this. Great Tutorial.
http://www.shopdev.co.uk/blog/cookies-with-jquery-designing-collapsible-layouts/

Javascript with PHP combination

I have a php script that returns an echo of 'Hello' when accessed half the time (just based on a random number).
Is it possible to make a javascript script on a HTML page that will:
Go to the the PHP page,
If 'Hello' is returned it will show an alert of 'Goodbye'
ELSE
It shows 'nothing found'
What do I need to do this?
That is called AJAX. Example:
var msg = 'Nothing found';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText != "Hello" ? msg : "Goodbye");
}
};
xhr.open('GET', 'http://example.com', true);
xhr.send(null);
See also:
https://developer.mozilla.org/en/AJAX/Getting_Started
Best would be to use jQuery and Ajax to fetch the page.
$.ajax({
type:"GET",
url:"file.php",
data:id, // if you want to pass a param, optional
success:function(data){
alert(data);//do something with data
}});
Since the information is not very confidential, I can suggest you to use Cookies (in case you don't want to use AJAX, but I still recommend you to use AJAX). People don't usually take the advantage of Cookies.
So, in PHP file, set the Cookies with your information:
$value = 'Hello';
setcookie("Information", $value);
And get it from HTML using Javascript (from W3School)
function getCookie(c_name)
{
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++)
{
x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
x=x.replace(/^\s+|\s+$/g,"");
if (x==c_name)
{
return unescape(y);
}
}
}
You could also just include the page in an iframe (with or without a meta-refresh) and instead of echoing 'hello' you would echo the javascript alert ;)

How to call multiple AJAX functions (to PHP) without repeating code

I have a little script which uses AJAX and PHP to display an image. You can see below that if I call the function mom() it looks in the PHP file index.php?i=mom and displays the image I'm looking for.
But I need the javascript to be lighter as I have 30 images and for each one I have to modify and copy the script below. Is there not a simpler way to have the functions be different and still call a different page?
<script type="text/javascript">
function mom()
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
HandleResponse(xmlHttp.responseText);
}
}
xmlHttp.open("GET", "index.php?i=mom", true);
xmlHttp.send(null);
}
function HandleResponse(response)
{
document.getElementById('mom').innerHTML = response;
}
</script>
My Trigger is this
<a href="#" onclick='mom();' />Mom</a>
<div id='mom'></div>
You could modify your function so it takes a parameter :
// The function receives the value it should pass to the server
function my_func(param)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
// Pass the received value to the handler
HandleResponse(param, xmlHttp.responseText);
}
}
// Send to the server the value that was passed as a parameter
xmlHttp.open("GET", "index.php?i=" + param, true);
xmlHttp.send(null);
}
And, of course, use that parameter in the second function :
function HandleResponse(param, response)
{
// The handler gets the param too -- and, so, knows where to inject the response
document.getElementById(param).innerHTML = response;
}
And modify your HTML so the function is called with the right parameter :
<!-- for this first call, you'll want the function to work on 'mom' -->
<a href="#" onclick="my_func('mom');" />Mom</a>
<div id='mom'></div>
<!-- for this secondcall, you'll want the function to work on 'blah' -->
<a href="#" onclick="my_func('blah');" />Blah</a>
<div id='blah'></div>
This should work (if I understand correctly)
<script type="text/javascript">
function func(imgName)
{
var xmlHttp = getXMLHttp();
xmlHttp.onreadystatechange = function()
{
if(xmlHttp.readyState == 4)
{
document.getElementById(imgName).innerHTML =
}
}
xmlHttp.open("GET", "index.php?i=mom", true);
xmlHttp.send(null);
}
</script>
MARTIN's solution will work perfectly.
By the way you should use some javascript framework for Ajax handling like jQuery.
It will make your life easy.
If you are having light weight images you preload the images on your page.
I solved this by making an array of in your case xmlHttp and a global variable, so it increments for each request. Then if you repeatedly make calls to the same thing (eg it returns online users, or, whatever) then you can actually resubmit using the same element of the array too.
Added example code:
To convert it to a reoccuring event, make a copy of these 2, and in the got data call, just resubmit using reget
var req_fifo=Array();
var eleID=Array();
var i=0;
function GetAsyncData(myid,url) {
eleID[i]=myid;
if (window.XMLHttpRequest)
{
req_fifo[i] = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
req_fifo[i] = new ActiveXObject("Microsoft.XMLHTTP");
}
req_fifo[i].abort();
req_fifo[i].onreadystatechange = function(index){ return function() { GotAsyncData(index); }; }(i);
req_fifo[i].open("GET", url, true);
req_fifo[i].send(null);
i++;
}
function GotAsyncData(id) {
if (req_fifo[id].readyState != 4 || req_fifo[id].status != 200) {
return;
}
document.getElementById(eleID[id]).innerHTML=
req_fifo[id].responseText;
req_fifo[id]=null;
eleID[id]=null;
return;
}
function reget(id) {
myid=eleID[id];
url=urlID[id];
req_fifo[id].abort();
req_fifo[id].onreadystatechange = function(index){ return function() { GotAsyncData(index); }; }(id);
req_fifo[id].open("GET", url, true);
req_fifo[id].send(null);
}
The suggestions to parameterize your function are correct and would allow you to avoid repeating code.
the jQuery library is also worth considering. http://jquery.com
If you use jQuery, each ajax call would literally be this easy.
$('#mom').load('/index.php?i=mom');
And you could wrap it up as follows if you'd like, since you say you'll be using it many times (and that you want it done when a link is clicked)
function doAjax(imgForAjax) { $('#'+imgForAjax).load('/index.php&i='+imgForAjax);}
doAjax('mom');
It makes the oft-repeated ajax patterns much simpler, and handles the issues between different browsers just as I presume your getXMLhttp function does.
At the website I linked above you can download the library's single 29kb file so you can use it on your pages with a simple <script src='jquery.min.js'></script> There is also a lot of great documentaiton. jQuery is pretty popular and you'll see it has a lot of questions and stuff on SO. ajax is just one of many things that jQuery library/framework (idk the preferred term) can help with.

Categories