Creating a hyperlink that works with or without AJAX

The current project I'm working on includes a display page where users can see a list of messages generated for them by the system. Each message consists of an <li> element containing the text of the message followed by a hyperlink labeled "Delete".

I wanted to make it such that you could delete each message without refreshing the page, but still accommodate users who had JavaScript turned off, and without a lot of extra work.

How did I do it? Like so:

<!---Include the jQuery core file--->
<script type="text/javascript" src="/views/JavaScript/jquery-1.2.2.js"></script>

<script language="javascript">
//Set the typical jQuery ready event handler to fire when the document is ready for manipulation
$(document).ready(function () {

//Assign a click event handler for all of the 'delete' hyperlinks (which all have a CSS class of 'deleteLink')
$(".deleteLink").click(function () {

var linkObj= $(this);
//Take the existing URL in the 'href' value and append an additional URL variable
var ajaxURL= linkObj.attr("href") + "&js=1";

//Remove the li list element (the parent) the link belongs to
linkObj.parent().remove();

//Make the Ajax call
$.ajax({
type: "POST",
url: ajaxURL
}); //end of .ajax function

//This statement will prevent the browser from actually navigating to the address in the link
return false;

}); //end of .deleteLink click function
}); //end of document.ready function
</script>


<h2>Your Messages</h2>

<ul>

<cfoutput query="qryMessages">

<li id="#messageId#">

#message#<br />
<a class="deleteLink" href="index.cfm?fuseaction=#xfa.deleteMsg#&msgId=#messageId#">Delete</a>

</li>

</cfoutput>

</ul>

...The only other thing you need to do is put a conditional statement in the page/event that is called by the hyperlink that looks for the presence of the additional URL variable ("js" in this case).

If JavaScript is turned off, that additional variable will not be defined and the page/event will redirect the action back to the calling page once it's done deleting the message data from the database.

If JavaScript is turned on, the page/event will simply delete the message data (no action redirect), and the user simply sees that message item disappear from the list.

Some updates on reordering items with jQuery

If you follow my blog at all, you know I have a keen interest in being able to reorder items in a list and then record that change in order in a database using JavaScript, specifically with the jQuery UI Sortables component. Here's some things I've learned recently regarding the topic:

Reordering Nested Lists

In my last project, I created a tool that allowed my clients to rearrange nested lists of articles and article categories using the jQuery UI Sortables component and the techniques I demonstrated in an earlier blog post.

My clients were very excited about the tool when they saw it in the prototype, but they ran into some difficulty when they tried to use it themselves during the final testing. They found it hard to place an item at either end of a list block because there were no visual cues outlining the borders of the list.

It was also nearly impossible for them to move an item around in the top-most list: if they tried to place it in between sibling items or at the end of the list, the item would almost always get dropped at the end of whatever sublist came at the end of the sibling item above.

Finally, the scrollable <div> element containing the nested lists would not scroll to match the drag movement of the cursor, so if they needed to move an item from one end of the nested lists to the other, the item would have to moved in steps.

I solved all of these problems by abandoning the drag-and-drop technique and replacing it with a version of my "click-to-click move" technique. So now when they need to move an item, they click on an icon associated with each item (hidden until needed), and target <div>s are created above and below each item:

Image of move targets in my last project

They then just click on the target for the place they want the item moved to, and the item is "moved" and the targets are removed (technically, the item is cloned, the clone is put in the new position, and the original item is deleted).

They like the "click-to-click move" version a lot better, so perhaps that's a better means of reordering items when using nested lists. But I recently discovered jTree, a brand-new jQuery plugin someone wrote specifically for sorting nested lists using drag-and-drop. I tried out the demo for it, and it has visual cues to help you position items in the right list, but it does flicker a bit at times. Still, I might play with it the next time I have to deal with nested lists again.

Reordering Table Rows

Lists are nice, but they don't cut it when each item is really a collection of separate items: that's when you need a table. In my current project, I needed a way to reorder the rows in my table as a means of letting the user reorder the data records. The jQuery UI Sortables component, however, does not work on table rows.

I tried to create a pseudo-table by using <div>s within each <li> item to evenly space the data fields in each row. I got it working and looking slightly less than ugly in FireFox, but it didn't fare so well in IE.

I then went browsing through the jQuery UI discussion board on Google Groups and found a post that mentioned a plugin for sorting/rearranging table rows.

It's called TableDnD, and it's a slightly different approach to the challenge. When you click on a row and drag it, there is no drag outline and no gradual movement: if you move up far enough, the content of the row you're dragging and the row above it quickly switch places, and vice-versa if you move downward. It highlights the moving row as you move it so you can keep track of what's happening. The movement is very smooth and you can go as fast as you like.

The only drawbacks I'm aware of so far is that the dragging action will not trigger the scroll bar if you're trying to drag the row beyond the visual limit of the window or scrollable container (much like my original nested list tool), and someone pointed out to me that if you fill all of the cells in a row with other DOM elements such that you cannot click on any of the cells themselves, you won't be able to grab the row and move it. That's not a problem your table cells just contain text, but it's something to keep in mind if you plan on formatting the text with <span> tags or providing input boxes for the user to edtit the cell data.

ColdFusion 8's Image Functions + jQuery= A UI For Adding Text and Color Blocks Into An Image file

One of the new features in ColdFusion 8 is the ability to manipulate images using ColdFusion tags and functions. For example, the code below (all server-side code) will take an image file on the server, overlay it with text, and create a brand new image file in temp space and display it to the browser:

<!---Assign the image file to the carImage variable--->
<cfimage name = "carImage" action="read" source="ferrari.gif"/>
<!---Add the text "Fast car!" to the image and place it 10 pixels from the left and 15 from the top--->
<cfset ImageDrawText(carImage, "Fast car!, 10, 15)>
<!---Display the new image--->
<cfimage source="#carImage#" action="writeToBrowser">

A week ago, an idea popped into my head: "What if you could create a UI tool that would let a user decide what text should appear on the image and where it should appear?"

I decided to try and answer that question. The result: a working proof-of-concept that lets you add text and blocks of color anywhere on a selected image using a UI tool powered by jQuery JavaScript functions. When you're done manipulating the image, you submit the data defining your changes to ColdFusion via an AJAX call, and ColdFusion creates a new image in temp space based on that data and displays it. You can save the new image down to your computer or store the data you submitted in the database so the image you made can be reproduced without permanently storing a new image file.

The fact that it only took me a week to do this (no more than 25 hours) is a testament to both the power and simplicity of ColdFusion and jQuery.

You can try out the proof-of-concept at: http://www.swartzfager.org/captionator

Update: I updated the title as I realized that describing this as an "image captioning program" might be interpreted as simply storing captions to associate with an image, not adding the text onto/into the image.

Changing Individual CSS Styles with jQuery

Back when I was writing my own custom JavaScript functions, I learned that there wasn't a single, simple way to change the individual style settings (like "font-weight:bold") for an HTML element that worked on every browser. My solution was to change the CSS classes assigned to the element instead: I wrote a library function that would allow me to add, remove, or replace any class assigned to an HTML element and simply created as many class definitions as I needed in order to accommodate the style changes. It was actually a pretty effective workaround because it let me effectively change multiple styles with one function call.

When I started using jQuery, I quickly learned about the "addClass" and "removeClass" core functions, which I could use instead of my library function:

$("#missionStatement").addClass("importantTextClass");
$("#userProfile").removeClass("hideTextClass");

...So I continued with my routine of changing styles by changing classes, even though sometimes I only needed to change or remove a single style setting. No harm, no foul.

But changing classes wouldn't work for the wacky little project I've been working on recently: I needed to be able to change several styles for an HTML element individually, and writing a class to handle every permutation of the possible style combinations was impractical.

So I went to the jQuery web site, hopeful that the brilliant folks at jQuery had something that could help me out.

And they did: the "css" core function allows you to read or set any individual style or styles:

if ($("#missionStatement").css("font-weight")== "400" || $("#missionStatement").css("font-weight")== "normal")
{
$("#userProfile").css("display","none");
$("#missionStatement").css({ fontSize:"24px", fontWeight:"bold" });
}

Have I mentioned that I love jQuery? :)

Alpha Releases Out of Updated jQuery UI and Brand-New jQuery Enchant Libraries

As demonstrated from some of my previous posts, I'm a big fan of jQuery, so this news caught my attention.

The new jQuery Enchant library is a library of visual effects: bouncing, shaking, fading, folding, exploding (didn't know what to expect with that one), etc.

Here's the link to the announcement on Google Groups:

Get it while it's hot: jQuery UI 1.5a and jQuery Enchant 1.0a!

In the thread, you'll find the links to the alpha demo pages.

Apparently, there will also be an update to the jQuery core file in order to support these alpha releases (also mentioned in the thread linked above).

Sorting a Nested List Using jQuery And Saving the Changes

A screenshot of the sorting demoA reader asked me if it was possible to sort/rearrange items in nested lists (lists within a main list) using the jQuery UI Sortables code. I told him that it was, and I had actually created a tool for a client recently that made use of that feature.

He wanted to know more about how to do it, so I went ahead and created a downloadable working demo of how to do it.

[More]

How to Create a Countdown Timer in JavaScript

I'm now signed up for two ColdFusion conferences this year: cf.Objective() in early May and CFUnited in late June. While I was looking at the promotional badges for the conferences, I got the idea for making a countdown timer for each one.

I did a Google search to see if there were any countdown functions already out there I could use and simply plug the start date of the conference, but while I found some example timers I couldn't quite find what I wanted, so I decided to roll my own.

[More]

How to Use the Same Server-Side Code to Validate Form Data With or Without AJAX Using jQuery

In any web application, if the user submits information to be stored in a database using a form, you always want to validate that information before it's stored in the database. The majority of users have JavaScript enabled in their web browser, allowing you to use JavaScript functions to validate the data on the client-side before the submission is allowed to proceed. However, there are those rare individuals who have JavaScript turned off, so a conscientious developer will also validate the submitted data on the server side as well as a backup.

The problem with this is that you end up having to maintain two sets of validation functions, which means twice the work if you have to make a change to the submission form or the validation rules themselves. In addition, if you're not experienced with JavaScript, you may find it harder to write the JavaScript validation code than similar code in your server-side programming language of choice.

In an earlier blog post, I wrote about how the latest version of ColdFusion, ColdFusion 8, provides a new tag called <cfajaxproxy> that allows you to make JavaScript calls to functions contained in ColdFusion Component (CFC) files on the server, enabling you to write your validation code within CFC functions and call them for either client-side or server-side validation.

But what if you're not running ColdFusion 8 yet, or you're using another web programming language (like PHP)?

Here's a technique I came up with using the jQuery JavaScript library and the jQuery Form plugin that lets you write your validation and database-update code on the server-side in such a way that you can either call it via AJAX if JavaScript is enabled or run it server-side if JavaScript isn't available:

[More]

UI Tool: Rearranging Items in a List, jQuery-style!

A few weeks ago, as part of an application prototype for a client, I used the fairly new jQuery UI library to create a UI tool where a user could rearrange a list of items by dragging and dropping them into different positions and then save those changes to the database.

I now have a public example posted and available for download--check it out using the link below or via the link in my Downloads list on the right:

List Sort Control (with jQuery)

It works in FireFox, IE, and Opera, and can be used in conjunction with any web application programming language.

Advantages of the jQuery Ready event

I've been working with jQuery for a few weeks now as part of a project, and I love it. I've always preferred to roll my own JavaScript, but from now on I plan to write all of my JavaScript utilizing the features provided by jQuery.

One of the most significant features of jQuery is it's document ready function:

$(document).ready(function(){
// Your code here });

It allows you to assign functions that will execute when an event like a mouse click occurs on the selected HTML element(s) (hyperlinks, divs, buttons, etc.). This allows you to separate the JavaScript calls from the HTML code itself--instead of writing:

<input type="button" id="mainLink" value="Show Picture" onClick="showPic();" />

...you can assign the click event to the mainLink button in a separate JavaScript file (referenced by the HTML file)...

$(document).ready(function(){

$("#mainLink").click (function () {
showPic();
});

});

...and leave the button free of that markup:

<input type="button" id="mainLink" value="Show Picture" />

The other benefit to this technique is that if you have a client that likes to alter the HTML code of the pages you wrote for them, but you're afraid they might screw up the JavaScript calls in the page, you can use jQuery to create all of the event handlers and the client won't have to worry about avoiding JavaScript code in the document.

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.1.004.