Javascript/PHP to update innerHTML of multiple items - php

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.

Related

redirect back to page after php code

I am trying the following code to update external content inside a div named "content1"
ajax.js:
var ajaxdestination="";
function getdata(what,where) { // get data from source (what)
try {
xmlhttp = window.XMLHttpRequest?new XMLHttpRequest():
new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) { /* do nothing */ }
document.getElementById(where).innerHTML ="<center><img src='loading.gif'></center>"; // Define the destination DIV id, must be stored in global variable (ajaxdestination)
ajaxdestination=where;
xmlhttp.onreadystatechange = triggered; // when request finished, call the function to put result to destination DIV
xmlhttp.open("GET", what);
xmlhttp.send(null);
return false;
}
function triggered() { // put data returned by requested URL to selected DIV
if (xmlhttp.readyState == 4) if (xmlhttp.status == 200)
document.getElementById(ajaxdestination).innerHTML =xmlhttp.responseText;
}
Inside my div I include 'page1a.php' with php, wich outputs a value from my database and contains a link to 'code1a.php' where I have a php code that updates this value. (This is just a test and will do more than update a value in the future).
update value
Inside code1a.php where I have a php code that updates my database, after the database has been updated, is there a way to update my div (content1) with 'page1a.php' again?
I have tried everything i could think of and search the web for a few days, but not found a solution to my problem.
The script can be found on: http://www.battrewebbsida.se/index2.php
There are many variants to do this, your solution isn't best to do it, but here's the modified your javascript code, which is that what you want.
By Javascript
var ajaxdestination="";
var tmpcache = '';
function getdata(what,where) { // get data from source (what)
try {
xmlhttp = window.XMLHttpRequest?new XMLHttpRequest():
new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) { /* do nothing */ }
tmpcache = document.getElementById(where).innerHTML;
document.getElementById(where).innerHTML ="<center><img src='loading.gif'></center>"; // Define the destination DIV id, must be stored in global variable (ajaxdestination)
ajaxdestination=where;
xmlhttp.onreadystatechange = triggered; // when request finished, call the function to put result to destination DIV
xmlhttp.open("GET", what);
xmlhttp.send(null);
return false;
}
function triggered() { // put data returned by requested URL to selected DIV
if (xmlhttp.readyState == 4) if (xmlhttp.status == 200)
document.getElementById(ajaxdestination).innerHTML =tmpcache;
}
By PHP
after doing your updates in 'code1a.php' send header location to your first 'page1a.php' file
header("Location: ".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'/page1a.php');
NOTE: dont forget about ob_start() at the top of script.

Ajax to read PHP

I think I'm getting ahead of myself, but I tried AJAX tutorials to read from a PHP file. The PHP file simply has an echo statement for the time, and I want to pass that to initialize a javascript clock.
But this is my first time trying AJAX and I can't even seem to get it to activate a test alert message.
Here is the code, it's at the bottom of my PHP page after all of the PHP.
<script type='text/javascript'>
function CheckForChange(){
//alert("4 and 4");
//if (4 == 1){
//setInterval("alert('Yup, it is 1')", 5000);
//alert('Now it is changed');
//}
var ajaxReady = new XMLHttpRequest();
ajaxReady.onreadystatechange = function(){
if (ajaxReady.readystate == 4){
//Get the data
//document.getElementById('clocktxt').innerHTML = ajaxReady.responseText;
alert("here");
alert(ajaxReady.responseText);
}
}
ajaxReady.open("GET","ServerTime.php",true);
ajaxReady.send(null);
}
setInterval("CheckForChange()", 7000);
</script>
Can somebody tell me why this isn't working? No idea what I'm doing wrong.
The problem in your code is an uncapitalized letter. (Oops!) You check ajaxReady.readystate; you need to check ajaxReady.readyState.
Because ajaxReady.readystate will always be undefined, your alerts never fire.
Here's your code fixed and working.
As an aside, have you considered using a library to handle the ugliness of cross-browser XHR? jQuery is your friend:
function CheckForChange(){
$.get('ServerTime.php', function(data) {
$('#clocktxt').text(data);
});
}
You should probably have something like:
setInterval(CheckForChange, 7000);
On an unrelated note, it's common naming convension in JavaScript to have function and methods names' first letters not capitalized, and the rest is in camelCase. i.e. checkForChange().
I'm not sure the exact problem with your code; here's what I use -- I'm sure it will work for you. (plus, it works with more browsers)
var xhr = false;
function CheckForChange(){
/* Create xhr, which is the making of the object to request an external file */
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else{
if(window.ActiveXObject){
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){}
}
}
/* End creating xhr */
/* Retrieve external file, and go to a function once its loading state has changed. */
if(xhr){
xhr.onreadystatechange = showContents;
xhr.open("GET", "ServerTime.php", true);
xhr.send(null);
}else{
//XMLHTTPRequest was never created. Can create an alert box if wanted.
}
/* End retrieve external file. */
}
function showContents(){
if(xhr.readyState==4){
if(xhr.status==200){
alert(xhr.responseText);
}else{
//Error. Can create an alert box if wanted.
}
}
}
setInterval(CheckForChange, 7000);

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/

AJAX Problem: multiple different requests returning the same response

I'm new to AJAX, and trying to use it to speed up the display of results for a PHP full-text file search. I have about 1700 files to search, so instead of waiting for the server to process everything I want to send just the first 100 to the script and display the results, then the next 100 etc., so users get instant gratification.
To do this, I call a function callftsearch with the names of all the files in a string and some other information needed for the PHP function on the other side to run the search. callftsearch creates arrays of each 100 files, joins them in strings and sends that to ftsearch.php through the javascript function ftsearch. The PHP runs the search and formats the results for display, and sends the HTML string with the table back. addresults() just appends that table onto an existing div on the page.
Here's the javascript:
function GetXmlHttpObject()
{
var xmlHttp=null;
try { xmlHttp=new XMLHttpRequest(); }
catch (e) { try { xmlHttp=new ActiveXObject('Msxml2.XMLHTTP'); }
catch (e) { xmlHttp=new ActiveXObject('Microsoft.XMLHTTP'); } }
return xmlHttp;
}
function callftsearch(allfiles, count, phpfilenames, keywordscore, keywordsboolean, ascii) {
var split_files = allfiles.split("|");
var current_files = new Array();
var i;
for (i = 1; i<=count; i++) {
file = split_files.shift();
current_files.push(file);
if (i%100 == 0 || i == count) {
file_batch = current_files.join('|');
ftsearch(file_batch, phpfilenames, keywordscore, keywordsboolean, ascii);
current_files.length = 0;
}
}
}
function ftsearch(file_batch, phpfilenames, keywordscore, keywordsboolean, ascii)
{
xmlHttp=GetXmlHttpObject();
if (xmlHttp==null) { return; }
// If our 'socket' has changed, send the response to addresults()
xmlHttp.onreadystatechange=addresults;
xmlHttp.open('POST','ftsearch.php', true);
var content_type = 'application/x-www-form-urlencoded';
xmlHttp.setRequestHeader('Content-Type', content_type);
xmlHttp.send('f='+file_batch+'&pfn='+phpfilenames+'&kw='+keywordscore+'&kwb='+keywordsboolean+'&a='+ascii);
}
function addresults()
{
var displayarray = new Array();
if (xmlHttp.readyState==4)
{
var ftsearchresults = xmlHttp.responseText;
$('#result_tables').append(ftsearchresults);
}
}
The problem: the page displays the exact same table repeatedly, with only the first few results. When I add alert(file_batch) to callftsearch it shows that it's sending the correct packets of files in succession. But when I alert(ftsearchresults) in addresults() it shows that it's receiving the same string over and over. I even added a timestamp at one point and it was the same for all of the printed tables.
Why would this happen?
A few things here.
First: it looks like you are already using jQuery since you have the line,
$('#result_tables')
If thsts the case, then why not use jQuerys built in ajax functionality? You could just do something like this,
$.ajax({
type: "POST",
url: "ftsearch.php",
data: 'f='+file_batch+'&pfn='+phpfilenames+'&kw='+keywordscore+'&kwb='+keywordsboolean+'&a='+ascii,
success: function(response){
$('#result_tables').append(response);
}
});
Second: If the output continues to be the same first few items each time, have you tried outputting the information that the ajax page is receiving? If it is receiving the correct information, then that meens there is something wrong with your PHP logic, which you do not have posted.

deleting mysql records with ajax

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.

Categories