Solved

How to use AJAX to save photo IDs so that they can be downloaded later?

Posted on 2010-08-27
26
575 Views
Last Modified: 2013-12-12
Experts,

I have a bunch of photo records in my database which I pull and print to the screen using php.  I'd like to create a scenario in which you can select multiple photos, and have their IDs stored so that you can download them as a group later.

Example Table Structure printed using php:

First Name | Last Name | Photo ID | Add - Delete
John | Smith | 234 | Add - Delete
Barry | Bonds | 298 | Add - Delete
Test | Testerson | 143 | Add - Delete

Example usage:  Site user can select 'add' or 'delete' to add or remove the photo ID to or from the list.  When the user is done selecting photos, the photos are downloaded based on the IDs stored by AJAX.  I envision this process being similar to a 'lightbox' that I have seen before on photo sites such as Dreamstime.com and the like.

Anyone have any easy to implement ideas on how to get this done?  I just don't want the page to continually be refreshing while the user selects add or delete for each photo.

Cheers!

EVibesMusic
0
Comment
Question by:evibesmusic
  • 15
  • 10
26 Comments
 
LVL 40

Accepted Solution

by:
RQuadling earned 500 total points
ID: 33549504

I don't know JQuery, but I do use Prototype (hmm no so good so far).

But, if this was me ...

1 - Attach a click observer to the container of all the Add/Delete buttons. One observer is easier to handle than lots of them.
2 - Give each button a uniqueID such that it is Add_xxx or Delete_xxx, where xxx is the PhotoID.
3 - The click observer will then perform the following steps.
 a - Initiate an AJAX request and pass the button's ID as a parameter called Action_PhotoID (for example).
 b - If the AJAX request passes, do something to the button (maybe hide it and show the other button in the pair)?
 c - If the AJAX request fails, tell the user why. If you have the data to tell them that.

On the server side, take the parameter, maybe $_GET['Action_PhotoID'], split it on the '_' and either add or remove the id from the session.

See snippet.

When you want to download the images, the $_SESSION['PhotoIDs'] contains all the IDs you want.


<?php
// Make sure we have the parameter.
if (isset($_GET['Action_PhotoID']))
	{
	// Get the Action and the ID.
	list($Action, $ID) = explode('_', $_GET['Action_PhotoID']);

	// Validate the ID. +ve non zero integer.
	if ($ID = intval($ID))
		{
		// Handle the action.
		switch($Action)
			{
			// Add the ID to the session.
			case 'Add' :
				session_start();
				if (!in_array($ID, $_SESSION['PhotoIDs']))
					{
					$_SESSION['PhotoIDs'][] = $ID;
					}
				break;

			// Remove the ID from the session.
			case 'Delete' :
				session_start();
				if (in_array($ID, $_SESSION['PhotoIDs']))
					{
					unset($_SESSION['PhotoIDs'][array_search($ID, $_SESSION['PhotoIDs'])]);
					}
				break;
			}
		}
	}
?>

Open in new window

0
 
LVL 27

Expert Comment

by:Lukasz Chmielewski
ID: 33550567
hmm, either way you would have to use SESSION variable... do you mean to add them "to cart" by selecting them with ajax, going to next page maybe and then downloading them from "cart" ?
0
 

Author Comment

by:evibesmusic
ID: 33600144
@RQuadling:

Thanks.  When you are speaking of the 'click observer', do you mean an onclick event handler?  Sorry, but I am new to AJAX.

@Roads_Roads:

Yes, I mean to add them to the 'cart' by selecting them with ajax, so my user could potentially add multiple photos from different searches, then download them all at once.  Does this help?
0
 
LVL 40

Assisted Solution

by:RQuadling
RQuadling earned 500 total points
ID: 33602410
Yes.

I use the Prototype JS library.

In that ...

$('id_of_element_that_you_want_to_click').observe('click', function(ev){
 // Handle the click event here.
});

I would recommend reading http://prototypejs.org/learn/introduction-to-ajax

Take a look, and come back if you need some more help. I'd rather help you adapt your own code rather than just giving you code which you may not understand.
0
 

Author Comment

by:evibesmusic
ID: 33620447
@RQuadling:

Ok...don't laugh.  I've put something together as a starting point but, I am way off apparently as I get no result when I click on my buttons.  I am not trying to tackle the storage of each photo's ID into the session at this point, rather I am just trying to understand how to get AJAX to change the image without reloading the page.

Can you please assist me in my learning?  I've already looked at the article on prototype and the 'introduction to', downloaded and installed prototype.js and created my first script, and here I am.

Installed the 2 scripts in the head tag of my page (ajax.js is attached):
<script type="text/javascript" src="scripts/prototype.js"></script>
<script type="text/javascript" src="ajax.js"></script>

Also, below is my button code which I display using php...so, it is inside a while loop which prints each button with the unique photo id as found in the 'name' tag.  My thoughts were that each button calls to the function 'addPhoto()' which is contained within the ajax.js script...

Like I said...please don't laugh...I am a total newb.
while($getinfo = mysql_fetch_array($result)){
echo '<div id="add_delete">';
echo '<input name="add_'.$getinfo['id'].'" onclick="addPhoto()" type="image" id="add" src="images/add.gif" width="50" height="20" />';
echo '</div>';
}//END WHILE STATEMENT

Open in new window

ajax.js
0
 

Author Comment

by:evibesmusic
ID: 33664667
@Anyone:

Can someone help me figure out this AJAX request?
0
 
LVL 40

Assisted Solution

by:RQuadling
RQuadling earned 500 total points
ID: 33667186
Just looking at your ajax.js (and sorry for not getting back to you sooner), and the principle is OK. I've not checked for syntax errors or the like.

Personally, I would add a few additional callbacks, just to make sure everything is working OK.

Along the lines as described in http://proto-scripty.wikidot.com/prototype:how-to-bulletproof-ajax-requests

There you can see how to monitor the request and report any problems - often the most difficult part.

Your target is set to "add_delete". Do you have an element with that as an ID to receive the update?
0
 

Author Comment

by:evibesmusic
ID: 33675291
@RQuadling:

OK...I've tested the code and I do have a div with and 'id' of "add_delete".

The following code from ajax.js now tells me the request is getting there because it successfully reads the contents of my 'add_photo.php' page, and prints the code in a dialogue box.

addPhoto = function(){ // Updates the contents of a div
                        
                  var url = 'add_photo.php';
                  var pars = '';
                  new Ajax.Updater('add_delete', url, {
                        method:'get',
                        parameters: pars,
                        evalScripts: true,
                        onSuccess: function(transport) {
                              var response = transport.responseText || "no response text";
                              alert("Success! \n\n" + response);
                        },
                        onFailure: function(){ alert('Something went wrong...') }
                  });
            }

Now, if I know the request is getting there because the dialogue box appears, how can it get it to return the contents of 'add_photo.php' and not print it in a dialogue box?

This is the code that is printed in the dialogue box.:

<input name="test" onclick="deletePhoto()" type="image" id="add" src="images/delete.gif" width="50" height="20" />
0
 

Author Comment

by:evibesmusic
ID: 33676185
This is my current ajax.js:

addPhoto = function(){ // Updates the contents of a div      
      var url = 'add_photo.php';
      var pars = 'action='+'add';
      new Ajax.Updater('add_delete', url, {method:'get', parameters: pars});
}


This is my current add_photo.php:

<?php
if ($_GET['action']=="add") {
  echo '<input name="delete" onclick="deletePhoto()" type="image" src="images/delete.gif" width="50" height="20" />';
}
if ($_GET['action']!="add") {
 
}
?>
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33676688
Can you add an onException() callback the same as the onFailure().

Do you have a live URL?

Try ...

var pars={action:'add'};

too.


It looks like it should work. Try it in Firefox with Firebug to see what errors you may be getting.
0
 

Author Comment

by:evibesmusic
ID: 33676798
The following:

addPhoto = function(){ // Updates the contents of a div
                       
                  var url = 'add_photo.php';
                  var pars={action:'add'};
                  new Ajax.Updater('add_delete', url, {
                        method:'get',
                        parameters: pars,
                        evalScripts: true,
                        onSuccess: function(transport) {
                              var response = transport.responseText || "no response text";
                              alert("Success! \n\n" + response);
                        },
                        onFailure: function(){ alert('Failure') },
                                    onException: function(){ alert('Exception') }
                  });
            }

Produces a success dialogue box and then throws the Exception dialogue box.
0
 

Author Comment

by:evibesmusic
ID: 33677009
Firebug says the following error occured:

element.dispatchEvent is not a function
[Break on this error] element.dispatchEvent(event);

link in Firebug takes me to line 4619 of the prototype.js file.
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33677082
Can I see a live URL please?

0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:evibesmusic
ID: 33677092
@RQuadling:

Sorry but, my site is only available via our intranet.  Is there some other way I can assist you with what you would like to see?
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33677574
Using alert() is fine for user's, but no good for debugging.

I want to see the value of the arguments sent to onException/onFailure, along with the callstack.

I can only do that with real access.

What type of control is the ?

Is the control also responsible for triggering the ajax request?

It it is, then it is trying to replace itself. That is going to fail. Seriously fail. All sorts of memory leaks.

Can you show the HTML that is in play here?
0
 

Author Comment

by:evibesmusic
ID: 33679611
@RQuadling:

Thanks for the response.  The control is in a div element, and is not replacing itself.  All of the HTML code that I have is generated after a user searches the database.  The database can return multiple results, so each result has an individual 'name' element.  Please see below.

In the 'while' loop of my php statement which creates a table populated with unique <input> buttons. Note, I do not have my <input> elements inside a <form> element.  Don't know if that matters?:

while(...){
echo '<td align="center">';
echo '<input name="add_'.$getinfo['id'].'" onclick="addPhoto()" type="image" src="images/add.gif" width="50" height="20" />';
echo '</td>';
}
echo'<td>';
echo'<div id="add_delete">';
echo'</div>';
echo'</td>';
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33680413
You need to connect the addPhoto() call to the id in some way.

As you are using an onclick, maybe (Block 1 of the code below)

(Also demonstrating the use of heredoc. NOTE: No escaping of " or ' for the HTML attributes!).

And then, the addPhoto() function (Block 2 of the code below)


And maybe the code tfor the add_photo.php (Block 3).


Using Firebug, what is being returned by the request? Not what is seen in the browser, but in the XHR tab. Takes a bit of clicking to get the response.
=======Block 1=======
echo <<< END_INPUT
<input name="add_{$getinfo['id']}" onclick="addPhoto({$getinfo['id']})" type="image" src="images/add.gif" width="50" height="20" />
END_INPUT;





=======Block 2=======
addPhoto = function(id){ // Updates the contents of a div
                        
                  var url = 'add_photo.php';
                  var pars={action:'add', id:id};
                  new Ajax.Updater('add_delete', url, {
                        method:'get',
                        parameters: pars,
                        evalScripts: true,
                        onSuccess: function(transport) {
                              var response = transport.responseText || "no response text";
                              alert("Success! \n\n" + response);
                        },
                        onFailure: function(){ alert('Failure') },
                                    onException: function(){ alert('Exception') }
                  });
            }



=====Block 3=====
<?php
if ($_GET['action']=="add" && ($ID = intval($_GET['id'])) > 0) {
  echo <<< END_INPUT
<input name="delete" onclick="deletePhoto({$ID})" type="image" src="images/delete.gif" width="50" height="20" />
END_INPUT;
}
if ($_GET['action']!="add") {
  
}
?>

Open in new window

0
 

Author Comment

by:evibesmusic
ID: 33684329
@RQuadling:

I have made your recommended changes as per your code above.  When I click on the add button now it runs through the routines giving me the success message with correct text, then proceeds to exception error.

Firebug Reports:

XHR : Params Tab | action add | id 404
XHR: Response Tab | <input name="delete" onclick="deletePhoto(404)" type="image" src="images/delete.gif" width="50" height="20" />
XHR: HTML Tab | I see the correctly displayed button.

Don't know if you need it but...

XHR: Headers Tab |

GET /dept/photostudio/add_photo.php?action=add&id=404 HTTP/1.1
Host: cnmtzam1036555
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.9) Gecko/20100824 Firefox/3.6.9
Accept: text/javascript, text/html, application/xml, text/xml, */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
X-Requested-With: XMLHttpRequest
X-Prototype-Version: 1.6.1
Referer: http://servername/dept/photostudio/search.php?cmd=go
Cookie: PHPSESSID=pkn8l2bntlvrq2bd6darfaeor0; acopendivids=aboutyou,aboutclinician,photospecs,special,agree; acgroupswithpersist=nada; mvalue/dept/photostudio/=100; mvalue/dept
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33684356
So, it is nearly there. What is the exception?

Can you change ...

onFailure: function(){ alert('Failure') },
onException: function(){ alert('Exception') }

to

onFailure: function(){ console.dir(arguments); },
onException: function(){ console.dir(arguments); }

and the exception should be logged in the console.

You may need to expand things.
0
 

Author Comment

by:evibesmusic
ID: 33684477
@RQuadling:

I changed the code.  Runs the same; nothing changed in the XHR tabs.  I took a look at the Stack, and this is what it reports:

fileName
      "http://servername/d...io/scripts/prototype.js"
 
      
lineNumber
      1661
 
      
message
      "receiver.update is not a function"
 
      
name
      "TypeError"
 
      
stack
      "("<input name=\"delete_404\" onclick=\"deletePhoto(404)\" type=\"image\" src=\"http://servername/dept/photostudio/images/delete.gif\" width=\"50\" height=\"20\" />")@http://servername/dept/photostudio/scripts/prototype.js:1661 ([object Object],null)@http://servername/dept/photostudio/scripts/prototype.js:1640 ([object Object],null)@http://servername/dept/photostudio/scripts/prototype.js:291 (4)@http://servername/dept/photostudio/scripts/prototype.js:1505 ([object Event])@http://servername/dept/photostudio/scripts/prototype.js:1436 ([object Event])@http://servername/dept/photostudio/scripts/prototype.js:291 handleEvent([object Event])@:0 SJOWContentBoundary()@:0 "
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33687453
What version of prototype are you using?

Can you change the target in the request from 'add_delete' to 'bob'

Let's see if this the issue.

But, without seeing the full code and being able to debug it, I'm a bit blind.

0
 

Author Comment

by:evibesmusic
ID: 33695407
@RQuadling:

Ok...just ran into something weird.  When I take the AJAX code out of my dynamically created php page, then run it on a regular HTML page, it works.

Seems to me like there is a problem when creating all of my buttons using php.  Let me play around with it some more and see what I can find out.  Thanks for all your help RQuadling.  You have been very helpful and patient.

EVM
0
 

Author Comment

by:evibesmusic
ID: 33705321
@RQuadling:

Is it possible to update the following code so that the replacement DIV's ID is not static like I have it coded here?

addPhoto = function(id){ // Updates the contents of a div            
  var url = 'add_photo.php';
  var pars={action:'add', id:id};
  new Ajax.Updater('add_delete_404', url, {method:'get', parameters: pars});
}

Instead of using 'add_delete_404' as the updated container, I would like it to be dynamic so that 'add_delete_404' = 'add_delete_id'
0
 

Author Comment

by:evibesmusic
ID: 33705432
@RQuadling:

AWESOME!  Got it to work...seems that some other scripts that were on the page were causing the changes not to go through on the AJAX request.  I have taken those scripts out and it now works...changing the buttons that is.

Cheers to you.  Thanks for all your help.  I have learned a lot and hopefully you have not pulled all of your hair out?

Have a good one...question closed.  Opening another.
0
 

Author Comment

by:evibesmusic
ID: 33705441
Final Code and comments:

Final ajax.js file:

addPhoto = function(id){ // Updates the contents of a div            
  var url = 'add_photo.php';
  var pars={action:'add', id:id};
  new Ajax.Updater('add_delete_'+id, url, {method:'get', parameters: pars});
}

deletePhoto = function(id){ // Updates the contents of a div            
  var url = 'add_photo.php';
  var pars={action:'delete', id:id};
  new Ajax.Updater('add_delete_'+id, url, {method:'get', parameters: pars});
}

Final method used to make the call to the ajax.js script...as appears in my php code:

echo '<div id="add_delete_'.$getinfo['id'].'">';
echo '<input name="add_'.$getinfo['id'].'" onclick="addPhoto('.$getinfo['id'].')" type="image" src="images/add.gif" width="50" height="20" />';
echo '</div>';
0
 
LVL 40

Expert Comment

by:RQuadling
ID: 33710404
No problems on the hair front, I was going bald already.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

OverviewThis article demonstrates a simple search form using AJAX. The purpose of the article is to demonstrate how to use the same code to render a page and javascript (JQuery) and AJAX to make subsequent calls to refine the results. The princip…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now