Quick follow up to Modal Dialog Editing post with jQuery and ColdFusion

This post is more than 2 years old.

This weekend I wrote up a quick blog post that demonstrated using jQuery and jQuery UI for front end editing of database content. ColdFusion was used to store changes made via a jQuery dialog and jQuery did all the handling of data back and forth. Alex asked if it was possible to demonstrate the code using a table instead of the lovely green divs I had created. Here is what I came up with. I'm going to focus on the changes so please be sure to read the previous entry for details on how this all works together. Ok, so first, the template.

<cfset getArt = new artservice().getArt()>

<html> <head> <script src="jquery-ui-1.8.7.custom/js/jquery-1.4.4.min.js"></script> <script src="jquery-ui-1.8.7.custom/js/jquery-ui-1.8.7.custom.min.js"></script> <link rel="stylesheet" href="jquery-ui-1.8.7.custom/css/overcast/jquery-ui-1.8.7.custom.css" /> <script> //credit: http://www.mredkj.com/javascript/numberFormat.html function dollarFormat(nStr){ nStr += ''; x = nStr.split('.'); x1 = x[0]; x2 = x.length > 1 ? '.' + x[1] : ''; var rgx = /(\d+)(\d{3})/; while (rgx.test(x1)) { x1 = x1.replace(rgx, '$1' + ',' + '$2'); } return "$" + x1 + x2; }

$(document).ready(function() {

$(".editLink").click(function(e) {
	var initialRow = $(this).parent().parent();

	//based on which we click, get the current values
	var artid = $(initialRow).data("artid");
	var name = $("td:first", initialRow).text();
	var price = $("td:nth-child(2)", initialRow).data("price");
	console.log(price);
	var desc = $("td:nth-child(3)", initialRow).text();
	desc = $.trim(desc);

	$("#artid").val(artid);		
	$("#namefield").val(name);
	$("#pricefield").val(price);
	$("#descriptionfield").val(desc);
	
	$("#editForm").dialog({
		buttons: {
			"Save": function() {
				var thisDialog = $(this);
				$.post("artservice.cfc?method=saveart", 
				{
					id:$("#artid").val(),
					name:$("#namefield").val(),
					price:$("#pricefield").val(),
					description:$("#descriptionfield").val()
				}, 
				function() {
					//update the initial div
					$("td:first", initialRow).text($("#namefield").val());
					var price = $("#pricefield").val();
					$("td:nth-child(2)", initialRow).data("price", price);
					price = parseInt(price).toFixed(2);
					$("td:nth-child(2)", initialRow).text("Price: "+dollarFormat(price));
					$("td:nth-child(3)", initialRow).text($("#descriptionfield").val());
					$(thisDialog).dialog("close");
				});
			}
		}
	});
	
	e.preventDefault();
});

}); </script> <style> .artdiv { padding: 5px; margin: 5px; background-color: #80ff80; } #editForm { display:none; } </style> </head>

<body>

<table width="100%" border="1"> <tr> <th>Name</th> <th>Price</th> <th>Description</th> <th> </th> </tr>

<cfoutput query="getart">

&lt;tr data-artid="#artid#"&gt;
	&lt;td&gt;#artname#&lt;/td&gt;
	&lt;td data-price="#price#"&gt;
	Price: #dollarFormat(price)#
	&lt;/td&gt;
	&lt;td class="description"&gt;
	#description#
	&lt;/td&gt;
	&lt;td&gt;&lt;a class="editLink" href=""&gt;Edit&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;

</cfoutput>

</table>

<div id="editForm" title="Edit Art"> <input type="hidden" id="artid"> <p> <b>Name:</b><br/> <input type="text" id="namefield"> </p> <p> <b>Price:</b><br/> <input type="text" id="pricefield"> </p> <p> <b>Description:</b><br/> <textarea id="descriptionfield"></textarea> </p>

</div>

</body> </html>

So the first obvious change is the display at the bottom. Instead of a list of DIVs I output table rows. That's a pretty simple change. I also added an edit link as the fourth column in the table.

Now go back up to the document ready block. I'm now listening for clicks to my new edit link. Note that at the very end I now use e.preventDefault() to block the browser from actually trying to do something with the link. The only other change then is to how I get the various values. Notice I get the table row by using parent.parent on my link. Once I have that, I use a combination of td:first and td:nth-child calls to get at my various items. Outside of that though nothing much else has changed. If you want to run this, please download the attachment from the previous entry and just copy the code above into a new table. Hope this helps!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Phillip Senn posted on 1/5/2011 at 11:39 PM

The jQuery .data method is new to me. Thanks for pointing that one out.
I think data-artid, and data-price are red herrings.
Are they?

Comment 2 by Phillip Senn posted on 1/5/2011 at 11:44 PM

Oh, I see. It has to do with HTML5.
http://ejohn.org/blog/html-...

Comment 3 by Raymond Camden posted on 1/5/2011 at 11:44 PM

HTML5 allows you to specify data-ANYTHING="foo" in tags. It's ignored by the rendering engine but shows up in your DOM. jQuery then provides an easy way to set/get them.

Comment 4 by Adam Presley posted on 1/6/2011 at 11:39 PM

Nice post as always Ray. The only issue I see is the dollarFormat function you borrowed from mredkj.com. That function makes use of un-var'd variables, and thus will place them in the global window object. This code demonstrates the problem.

<script type="text/javascript">

var x = 15;

function dollarFormat(nStr){
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return "$" + x1 + x2;
}

function improvedDollarFormat(nStr){
nStr += '';
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return "$" + x1 + x2;
}

alert("x = " + x);
alert(dollarFormat("444.55"));
alert("x = " + x);

/* Reset test */
x = 15;

alert("x = " + x);
alert(improvedDollarFormat("444.56"));
alert("x = " + x);

</script>

Comment 5 by Raymond Camden posted on 1/6/2011 at 11:41 PM

Ah good catch there. Thanks.

Comment 6 by Raul posted on 3/24/2011 at 5:43 AM

Sorry for the noob question but...
How do you go about 'adding/deleting' and refreshing the table?

On your form, how do you handle dealing with dropdowns, checkboxes and radio buttons?
I think that's what's missing to this lovely example.

Any help/tip would be greatly appreciated.

Thanks,
RD

Comment 7 by Raymond Camden posted on 3/28/2011 at 3:25 PM

Deleting could be a simple link in each row that passes the ID of the row to delete.

For add, you would pop up the dialog but not preload any of the form values. You would want to set the ID to something like 0 or keep it blank, and ensure "saveavrt" can handle that.

As for the dropdowns and checkboxes, well, the API for them is just a bit more complex. Enough for me not to want to write the code in a comment box. ;) For a checkbox, it's a matter of getting them all and finding the one with the right value to check. jQuery makes that easy. For a select box it's simiilar.

Comment 8 by erik posted on 7/12/2011 at 7:22 PM

Hi Ray

How can I expand the code so once the save button is clicked update the initial page as well. DO I just need to reload a page

Comment 9 by Raymond Camden posted on 7/12/2011 at 8:53 PM

If you just want to reload an entire page you can use window.location.href=.... Or use window.location.reload.

Comment 10 by Misty posted on 7/20/2011 at 5:28 PM

and if we just ned to reload the DIV after the initial Add or Edit, Then what we need to do!

Comment 11 by Raymond Camden posted on 7/24/2011 at 3:53 AM

Not quite sure I get you Misty, but reloading content in a div is easy with JS, even easier with jQuery.

Comment 12 by Misty posted on 7/24/2011 at 1:52 PM

Its just like this,

1. Opened the dialog,
2. I added a new Entry
3. I clicked Add
4. Add will add the entry & close the dialog Box,
5. I have wrapped the table with a DIV id="refreshDiv">
6. Question, How on Closure of the Dialog when i Press Add will trigger the <DIV> which refreshes it and show the added record.

I have implemented Add/Delete Functionality & i will share it with you asap!, Once i Complete this

Comment 13 by Raymond Camden posted on 7/27/2011 at 6:17 AM

Whatever you use to close the dialog (a link for example) should use an event handler to do the rest of your process.

Comment 14 by Misty posted on 7/27/2011 at 9:05 AM

what exactly are u trying to say, dialog box just closes the dialog and doesnot refresh the div, i can add the tr td manually but that is not what i m trying

Comment 15 by Raymond Camden posted on 7/27/2011 at 3:08 PM

What do you mean when you say dialog box exactly? If it is a jQuery UI dialog, you have the option to do something on close.

Comment 16 by Phillip Senn posted on 4/7/2012 at 6:38 PM

I think I just learned yesterday that $(this).data('ANYTHING') is different from the data-ANYTHING attribute. For example, if you have data-ANYTHING and you say removeData('ANYTHING'), it's not going to work - you have to use removeattr('ANYTHING').

Comment 17 by Phillip Senn posted on 4/7/2012 at 6:38 PM

removeAttr('data-ANYTHING')

Comment 18 by Raymond Camden posted on 4/7/2012 at 10:12 PM

Interesting. If I had to guess, I'd say $(this).data is a polyfill for things that don't support data-*. I'm not sure though. I'd check the docs.

Comment 19 by Raymond Camden posted on 4/7/2012 at 10:28 PM

I don't know - it seems like it should be the same in any modern jQuery lib: http://api.jquery.com/data/...

Comment 20 by Phillip Senn posted on 4/8/2012 at 12:56 AM

OK, I've put together a proof-of-concept.
http://www.phillipsenn.com/...

Comment 21 by Raymond Camden posted on 4/9/2012 at 5:49 PM

Doing a bit of research and found this: http://www.visualjquery.net...

Note specifically this portion: (btw, api.jquery.com is down for me so I can't find the official doc) "NOTE: Starting with jQuery 1.4.3, calling .removeData() will cause the value of the property being removed to revert to the value of the data attribute of the same name in the DOM, rather than being set to undefined."

This seems to mesh with your demo where removeAttr just reverted it back to the DOM value.