Update: jQuery Photo Tagger Plugin For Flickr-Style Photo Tagging

Posted February 5, 2010 at 10:26 AM by Ben Nadel

Tags: ColdFusion, Javascript / DHTML

This morning, I worked on updating my jQuery Flickr-Style Photo Tagger plugin to get rid of some of the limitations with the initial release. I'm still kind of feeling my way through the plugin "best practices", so bear with me.

 
 
 
 
 
 
 
 
 
 

Today, I made the following changes (the latest code can be downloaded from the project page):

  • Hover now works in Internet Explorer. I had to add a transparent GIF background image to the anchor tags to get this to work; hopefully, I'll find a non-linked-file way to deal with this in the future.
  • I removed the use of the CTRL key. Now, to create new tags, you simple click and drag; the caveat here is that "tag creation" has to be turned on (another new feature) in order for this to work.
  • When you create a new tag, you cannot start the tag over an existing tag. This was more about technical issues than anything else - it made the double-click-to-delete and the click-to-drawing easier to program along side one another.
  • Tag creation can be turned on/off by default as well as set manually.
  • Tag deletion can be turned on/off by default as well as set manually.

To see some of these new features, I have updated the demo code:

  • <!DOCTYPE HTML>
  • <html>
  • <head>
  • <title>Flickr-Style Photo Tagging With jQuery And ColdFusion</title>
  • <style type="text/css">
  •  
  • div.photo-column {
  • float: left ;
  • margin-right: 10px ;
  • }
  •  
  • div.photo-container {
  • border: 1px solid #333333 ;
  • margin-bottom: 13px ;
  • }
  •  
  • </style>
  • <script type="text/javascript" src="./jquery-1.4.1.js"></script>
  • <script type="text/javascript" src="./coldfusion.json.js"></script>
  • <script type="text/javascript" src="./phototagger.jquery.js"></script>
  • <script type="text/javascript">
  •  
  • // When the DOM is ready, initialize the scripts.
  • jQuery(function( $ ){
  •  
  • // Set up the photo tagger.
  • $( "div.photo-container" ).photoTagger({
  •  
  • // The API urls.
  • loadURL: "./load_tags.cfm",
  • saveURL: "./save_Tag.cfm",
  • deleteURL: "./delete_tag.cfm",
  •  
  • // Default to turned on.
  • // isTagCreationEnabled: false,
  •  
  • // This will allow us to clean the response from
  • // a ColdFusion server (it will convert the
  • // uppercase keys to lowercase keys expected by
  • // the photoTagger plugin.
  • cleanAJAXResponse: cleanColdFusionJSONResponse
  • });
  •  
  •  
  • // Hook up the enable create links.
  • $( "a.enable-create" ).click(
  • function( event ){
  • // Prevent relocation.
  • event.preventDefault();
  •  
  • // Get the container and enable the tag
  • // creation on it.
  • $( this ).prevAll( "div.photo-container" )
  • .photoTagger( "enableTagCreation" )
  • ;
  • }
  • );
  •  
  •  
  • // Hook up the disabled create links.
  • $( "a.disable-create" ).click(
  • function( event ){
  • // Prevent relocation.
  • event.preventDefault();
  •  
  • // Get the container and enable the tag
  • // creation on it.
  • $( this ).prevAll( "div.photo-container" )
  • .photoTagger( "disableTagCreation" )
  • ;
  • }
  • );
  •  
  •  
  • // Hook up the enable delete links.
  • $( "a.enable-delete" ).click(
  • function( event ){
  • // Prevent relocation.
  • event.preventDefault();
  •  
  • // Get the container and enable the tag
  • // deletion on it.
  • $( this ).prevAll( "div.photo-container" )
  • .photoTagger( "enableTagDeletion" )
  • ;
  • }
  • );
  •  
  •  
  • // Hook up the disabled delete links.
  • $( "a.disable-delete" ).click(
  • function( event ){
  • // Prevent relocation.
  • event.preventDefault();
  •  
  • // Get the container and disabled the tag
  • // deletion on it.
  • $( this ).prevAll( "div.photo-container" )
  • .photoTagger( "disableTagDeletion" )
  • ;
  • }
  • );
  •  
  • });
  •  
  • </script>
  • </head>
  • <body>
  •  
  • <h1>
  • Flickr-Style Photo Tagging With jQuery And ColdFusion
  • </h1>
  •  
  •  
  • <div class="photo-column">
  •  
  • <div class="photo-container">
  • <img
  • id="photo3"
  • src="./sexy3.jpg"
  • width="520"
  • height="347"
  • alt="Sexy woman used for demo."
  • />
  • </div>
  •  
  • <!-- These will toggle the tag ceation. -->
  • <a href="#" class="enable-create">Enable Create</a>
  • &nbsp;|&nbsp;
  • <a href="#" class="disable-create">Disable Create</a>
  •  
  • <br />
  • <br />
  •  
  • <!-- These will toggle the tag deletiong. -->
  • <a href="#" class="enable-delete">Enable Delete</a>
  • &nbsp;|&nbsp;
  • <a href="#" class="disable-delete">Disable Delete</a>
  •  
  • </div>
  •  
  •  
  • <div class="photo-column">
  •  
  • <div class="photo-container">
  • <img
  • id="photo2"
  • src="./sexy2.jpg"
  • width="520"
  • height="347"
  • alt="Sexy woman used for demo."
  • />
  • </div>
  •  
  • <!-- These will toggle the tag ceation. -->
  • <a href="#" class="enable-create">Enable Create</a>
  • &nbsp;|&nbsp;
  • <a href="#" class="disable-create">Disable Create</a>
  •  
  • <br />
  • <br />
  •  
  • <!-- These will toggle the tag deletiong. -->
  • <a href="#" class="enable-delete">Enable Delete</a>
  • &nbsp;|&nbsp;
  • <a href="#" class="disable-delete">Disable Delete</a>
  •  
  • </div>
  •  
  • </body>
  • </html>

As you can see, I tried to follow a sort of jQuery-UI convention where you can use the plugin method to both apply a new plugin as well as invoke methods on an existing plugin. So, for example, if you call the plugin method with an options hash:

.photoTagger( {} );

... it applies the plugin. But, if you call it with a method name:

.photoTagger( "enableTagCreation" );

... it invokes the given method - enableTagCreation - on the photoTagger instances associated with the elements in the given collection.

If you want to try this out for yourself, look at the online demo.




Reader Comments

Feb 5, 2010 at 10:44 AM // reply »
15 Comments

Good work Ben. I have a project coming up and this might be fun to work into it.


Feb 5, 2010 at 11:33 AM // reply »
10,638 Comments

@Robert,

Awesome - when you do, I'd love to hear what you did with it.


Feb 11, 2010 at 12:45 PM // reply »
1 Comments

hi,
thats a real nice feature

im interested for testing it but
im more designer than developer and i only know php ...

Is there a way to make the same functionnality with php, and mysql ?

i need to change The API urls with the path to my php file, right ?

and what i dont know how to replace cleanAJAXResponse: cleanColdFusionJSONResponse
for an apache server...

Thanks for sharing


Feb 11, 2010 at 10:29 PM // reply »
10,638 Comments

@Keusta,

You should be able to set this up in PHP, although you'll have to write the PHP scripts. As far as the function, cleanAJAXResponse(), you won't need it. It is only required for ColdFusion because it is not case sensitive.


Apr 21, 2010 at 10:07 AM // reply »
1 Comments

Hi Ben,

Its a really cool photo tagging plugin. Since i was implementing this is php I was wondering how to store the data and retrieve it back.

Thanks for sharing this wonderful work.


Apr 21, 2010 at 10:50 AM // reply »
10,638 Comments

@Ashish,

I don't have it in front of me, but for this demo, I was probably caching the tagging info in the Application scope (a persistent scope in ColdFusion). Ultimately, though, this is built to be server agnostic. As long as your PHP code can return the JSON, it should be good.


Jun 25, 2010 at 7:33 AM // reply »
4 Comments

Hi, Ben,

I tried to port your design into PHP implementation. It works in my free hosting server.

However, I found my modification has issues in IE and Opera, while yours are fully compatible with most browsers. My Dragonfly is disabled due to some security issues. While Opera error console through out an CSS warning for jQuery zoom:1.

Opera will alert me for "problem in API", just as it can not decode the JSON correctly.

The error console from IE8 told me following:

Message: 'length' is null or not an object
Line: 29
Char: 312
Code: 0
URI: http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js

I have no ideas for all of these. I have tried the jquery-1.4.1.js from your site. The error is same.

So I return to check what is happening in JSON communications between jQuery and backend. I have tried to change the MIME to "application/x-json". It doesn't help. It is interesting that your demo's JSON XHR content-body is hidden from the Firebug tools. I don't know why.

If you happen to see the comment. Would you give me some hints to debug?

My testing implementation is written in PHP functions. The load_tags will read a CSV and encode into JSON. The save_tag will write parameters into CSV file. I wonder if there is anything I should take care of.

My demo locates at:

http://allankliu.66ghz.com/prototype/labs/jquery-photo-tagger/

My source code at:

http://allankliu.66ghz.com/prototype/labs/jquery-photo-tagger/jquery-photo-tagger.zip

Any help is appreciated.

Yours sincerely

Allan K Liu


Jun 25, 2010 at 6:37 PM // reply »
4 Comments

After upgrading my Safari to v5(7533.16), the alert window can not be entered for message. Maybe it is browser bug?


Jun 25, 2010 at 8:02 PM // reply »
4 Comments

Hello, I am coming back. I found that my problem is terrible format in the JSON data with unnecessary comma and missing quote. Now, IE/FF/Opera works, although Safari 5 still works abnormally.

Sorry to bother you. Again, great work for this plug-in.


Jun 29, 2010 at 10:12 AM // reply »
10,638 Comments

@Allankliu,

Sounds like you got it mostly working with the JSON formatting. I am not sure why it would be working abnormally in Safari. Sorry.


Sep 30, 2010 at 11:32 AM // reply »
2 Comments

Hello Ben,
Thank you for sharing such a nice feature.
I have a small problem and i need ure help.
I have a servlet (java) which populates an image and i wish to tag that image, and when i tag the image i wish to store it in the database. i need ure help in understanding the JASON part. Is there a way to solve my problem.


Oct 30, 2011 at 11:30 AM // reply »
1 Comments

Hello Ben,
first, thanks for your nice work.
Before I port your code in PHP, I wanna ask for it because someone already does this work.
Does someone have the PHP-Code from allankliu? Both of his links are dead.

Greetings from germany
Elodrin


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Feb 3, 2012 at 10:49 PM
How I Got Node.js Running On A Linux Micro Instance Using Amazon EC2
Wow this was really helpful! Only thing I would add is you need to update your .bash_profile after you edit the secure_path. This is what I did: $ . ~/.bash_profile Otherwise, NPM won't be found. ... read »
Feb 3, 2012 at 10:14 PM
Pushing Base64-Encoded Images Over HTML5 WebSockets With Pusher And ColdFusion
@Ben, Just wanted to let you know that pusher are soon to start limiting sizes on messages. This was the detail that came through in the Feb dispatch: "However, we will soon be limiting the s ... read »
Feb 3, 2012 at 5:05 PM
Regular Expressions Make CSV Parsing In ColdFusion So Much Easier (And Faster)
I tried using your RegEx in my C# program, but it was matching an extra empty-string at the end and so I would end up with an extra field that doesn't exist, so I changed it to this: (^|,)("(?: ... read »
Feb 3, 2012 at 3:47 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
Josh Cyr posted this on Twitter just a little bit ago. Thought it was appropriate. http://stackoverflow.com/questions/1619152/how-to-create-rest-urls-without-verbs/1619677#1619677 ... read »
Feb 3, 2012 at 2:28 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
@Michael, You definitely make a good point (and extra points for quoting movies - I love movies). When you use a return() statement to define the object's public API, it does provide a consistent a ... read »
Feb 3, 2012 at 2:04 PM
Changing The Execution Context Of Your Self-Executing Function Blocks In JavaScript
To quote Jurassic Park: "Just because you can doesn't mean you should". I completely, utterly disagree with the thought that this is more readable. Consider the current module pattern: if ... read »
Feb 3, 2012 at 1:10 PM
REST API Design Rulebook By Mark Masse
@Jordan, Yeah, WRML was created by Mark Masse (author of the book). I also found it to be a bit convoluted. I suppose it is intended to allow the Client to be able to programmaticaly respond to cha ... read »
Feb 3, 2012 at 1:08 PM
ColdFusion Supports HTTP Verbs PUT And DELETE (As Well As GET And POST)
@Jason, To be honest, I don't have good answers for that kinds of stuff. And, to the point, that is specifically why I *really* liked the REST API Design Rulebook by Mark Masse - he just cuts throu ... read »