Category Archives: jQuery

Modifying the jQuery dump plugin to not open in a new window


I have been using the jQuery version of the javascript dump for a while now and it is invaluable especially when debugging JSON objects.  The one down side to the plugin is it tries to display the dump contents in a new window, but I prefer to just get the html contents and stuff it into a div.

As it turns out it was pretty easy to modify the plugin to work how I wanted. To make the collapse/expand feature work I had to make the functions global but it is cool as long as you don’t have any functions on the page with the same name.

Here is an example page:

The dump results:

If you would like check out the dump plugin, here is my modified jqDump.js file.

Advertisements

Quick and easy text size adjustment with jQuery


Lately I have been working on a site that deals with quite a bit of text. When it comes to choosing the default text size for a web site, as a developer I try to pick a happy medium between what lays out well on the page but is still easily readable. It would be nice to give the user the ability to adjust the font size to their liking.

As it turns out, this is dead simple to accomplish and using the jQuery UI slider it even looks pretty good too. First we will create an empty div that will contain our slider element and a target div that will contain some test text. Next we add the jQuery code to adjust the font size as the slider is moved.

Font size:
<span id="fontSz">100%</span>&nbsp;&nbsp;
<div id="fontSlider" style="width: 60%; display: inline-block;"></div>
<div id="adjustableText">
 Some test text in here
</div>
<script type="text/javascript">
 $(document).ready(function(){
  $('#fontSlider').slider({
   range: "min",
   min: 50,
   max: 200,
   value: 100,
   slide: function(event, ui){
    fontSize = ui.value;
    $('#adjustableText').css('font-size', ui.value + '%');
    $('#fontSz').html(ui.value + '%');
   }
  });
 });
</script>

That pretty much covers the code. Basically we are allowing the user to scale the text in the adjustableText div from 50% up to 200% and the font will adjust as the slider is moved. You can see this in action here.

It has been a while since I have posted anything on jQuery so this was a fun little project.

CF Free Chat


Last year I wrote a simple chat system for ColdFusion as a demo for a friend of mine.  It was very simple; a component on the backend acted as the main controller for storing the “message cache” and on the front end jQuery code polls the cfc at a set interval and updates the chat window.  Simple stuff.

I never really got much further than the proof-of-concept code because of time constraints and also not long after that Railo introduced messaging websocket gateways with push notification.   Needless to say, I started playing around with that an the original project just fell to the wayside and I really just forgot about the simple CFChat app.

Fast-forward to yesterday.  Jessica pinged me letting me know she had released a free chat app based loosely on my code called CF Free Chat.  Her version is much more polished with private messaging, user warns and user kicks, all easily configured through a settings file.  With a few CSS tweaks you can easily have a customized version up and running in no time.

This was originally the direction I was intending on going with the application if I had the time to write it.  If you are looking for something along these lines I would definitely suggest checking it out.

cfMud is now up at GitHub


I thought it would be pretty cool to create a MUD based on ColdFusion and jQuery so I thought I would give it a shot and see what I could come up with.  This was my first project that would rely heaving on jQuery and using AJAX calls to push data to the server and back to the client.  The code is still in EARLY in development, but I am putting it up on my public repo.

The main feature is a clickable map that allows you to move your character around the world.  It was designed to be pretty lightweight and caches a large chunk of the map at a time.  I don’t the the multi-user part down either, currently it works for one person.  Also, the NPC system leaves a lot to be desired, the movement is slow and clunky due to the nature of how it is handled (jQuery sends a heartbeat to the server which handles all the server side NPC management).

I don’t have access to my database server to include schema at the moment, but I will update the repo later on this afternoon with the schema in place.

jqDesktop demo app now at GitHub


A few months ago I was playing around with jQuery quite a bit.  I came out with a jQuery desktop-esq demo (which can probably be found here in a download link somewhere) and created a new repository for it at GitHub.

Unfortunately, things happen and both fell by the wayside.  I have a few new projects that will be coming up in the near future and GitHub will be used extensively and a buddy told me about a very nice front end for Git called SmartGit.  Playing around with it was a good excuse to finally get the repo updated.

If you are looking for a nice GUI for Git I highly recommend it.  It is free for non-commercial use and reasonably priced otherwise. It is not open-sourced, but you still cannot beat the price.

If you are interested in checking out the little jQuery Desktop application you can find it here:

http://github.com/robertz/jqDesktop

Recreating your jQuery Sortable() sort order


A reader pinged me with an interesting question.  He was using jQuery the jQuery sortable behavior to allow users to order widgets on a page and then save their layout.  The issue he was having was figuring out how to recreate the layout when the user reloaded the page.

As always there is more than one way to skin a cat, but I came up with a quick demo to illustrate one way to do this.  If we have the user defined sort order it should be easy enough to recreate the view.  I can think of several other ways to accomplish this, but this was the most straight forward way of handling the problem.

For my example I created a div representing my sortable container.  Within the container I created four divs repesenting my sortable children named “div1” through “div4” (I am very creative first thing in the morning).  I then hard-coded a “user defined” sort order that sorts them from “div4” down to “div1”.  Since I know the sort order it is just a matter of looping through my child elements and putting them in their proper place.  This is done by looking at the sort order array and inserting the selected element after the previous element in the sort order.  We skip the first element in the sort order since it obviously will not have a previous element.  The end result being all the divs nicely ordered, just as the user saved them.

Easy jQuery multifile uploader


I needed a quick and dirty multi-file uploader for a site, but I did not want to install another plugin or a flash uploader.  I am using the jQuery form plugin already to handle AJAX form submissions so I will hook to that to upload my files to the site.

My method basically uses jQuery to inject a form with a filefield into the DOM.  I bind to the onchange event of the filefield so when a file is added the current file field is hidden, insert a new blank file field, and update a list of queued files waiting to be uploaded.  When the user hits the “Upload Files” button, I iterate through all the “input:file” elements using jQuery and submit the form using the jQuery form plugin with ajaxForm().  Of course, you can remove a file from queue as well by clicking on the X in the queue list.

It is an inelegant solution, but it does work.  Here is the code if you want to give it a try:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Multi-file upload</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript" src="/js/jquery.form.js"></script>
</head>

<body>
 <div id="uploadContainer"></div>
 <input id="btnSubmit" type="button" value="Submit Files" onclick="submitLoop();" />
 <div id="fileInfo"/>

 <script language="javascript">
  $(document).ready(function(){
   $container = $('#uploadContainer');
   $info = $('#fileInfo');
   count=0;                            
   addUpload();
  });
 function addUpload(){
  count++;
  $('form').hide();
  $container.append('<form id="uploadForm-' + count +'" action="ajaxProxy.cfc?method=upload" enctype="multipart/form-data"><input id="file-' + count + '" name="filename" type="file" onchange="addUpload();" /></form>');
  showFileInfo();
 }
 function removeItem(id){
  if( $('#' + id).length){
   $('#' + id).remove();  
   showFileInfo();
  }
 }
 function showFileInfo(){
  $info.html('');
  $('input:file').each(function(){
   if( $(this).val().length ){
    $info.append('<div id="display-' + $(this).attr('id') + '"><a href="#" onclick="removeItem(\'' + $(this).parent().attr('id') +'\')">X</a> '  + $(this).val() + '</div>');
   }
  });
 }
 function submitLoop(){
  $('input:file').each(function(){
   var currItem = $(this).attr('id');
   if($(this).val()){
    $(this).parent().ajaxForm({
     async: false,
     success: function(data){
      var incoming = $.parseJSON(data);
      $('#display-' + currItem).append(' <strong>' + incoming.svrMessage + '</strong>');
     }
    }).submit();
   }
  });
 }
 </script>
</body>
</html>

Using jQuery sortable() to set display sort order


I am currently working on wrapping up a web site for a client that has quite a few image and video galleries each with 100+ images.  One of the biggest problems I have had with the galleries is being able to sort how they were displayed for the end users.  Initially I added in buttons to move the items up and down in the sort, but when you are dealing with a lot of items it can be tedious and aggravating work.

This weekend things came to a head because the client was getting annoyed.   They wanted a way to quickly update the item sort so I went about finding the best way to go about it because I love happy clients.  My main concern was having items in the database with the same sort order and possibly throwing off the sort.  As it turns out, the answer was surprisingly simple.

The web site in question is already using the jQueryUI so modifying the image administrator to use the UI sortable() option was really no hassle what-so-ever.  I am using AJAX pretty heavily on the site I just needed to do some editing to my file list page that is included on the page with an AJAX load call.

<cfscript>
 catObj = application.transfer.get("categories",url.id);
 base = '/path/to/web/root';
 filePath = base & catObj.getBaseDirectory();

 cq = application.transfer.createQuery("FROM images WHERE images.cat=:id ORDER BY images.sortorder");
 cq.setParam("id",url.id,"numeric");

 files = application.transfer.listByQuery(cq);
</cfscript>

<cfif files.recordcount>
 <div id="sortableContainer" style="margin-top: 48px;">
  <cfoutput query="files">
  <div id="#ID#" style="width: 600px; margin-bottom: 12px;">
   <div style="height: 20px; text-indent: 12px; padding-top: 4px;">Image Header</div>
   <div class="ui-widget-content">
    <table style="width: 600px;">
     <tr>
      <td width="75">
      <a href="/image_viewer.cfm?id=#ID#" target="_blank" style="color: blue;">
       <img src="/#catObj.getBaseDirectory()#/thumbs/#filename#" width="75" height="75"/>
      </a>        
     </td>
     <td>
      <form id="img#ID#" action="ajaxProxy.cfc" method="post">
       <input type="hidden" name="postType" value="updateImage" />
       <input type="hidden" name="id" value="#ID#" />
       <input type="text" name="Title" value="#Title#" style="width: 200px;" /><br />
       <input type="submit" name="Method" value="Update" />
       <input type="button" value="Delete" onClick="void(0);" />
       <input type="button" value="Set" onClick="void(0);" />
      </form>        
     </td>
    </tr>
   </table>
  </div>    
 </div>
 </cfoutput>
 </div>

 <div style="padding-bottom: 128px;"/>

<script type="text/javascript">
 $('#sortableContainer').sortable({
 stop    : function(event, ui){
 var result = $('#sortableContainer').sortable('toArray');
 var sortOrder = '';

 for(var i=0; i<result.length; i++){
 sortOrder += result[i];
 if(i < result.length - 1) sortOrder += ',';
 }
 setImageSortOrder(sortOrder);
 }
 });

 function setImageSortOrder(order){
 $.ajax({
 url            : 'ajaxProxy.cfc',
 data            : {
 method        : 'setImageSortOrder',
 sortOrder     : order
 },
 async        : false,
 success        : function(data){
 var incoming = $.parseJSON(data);
 if(incoming.svrStatus == "-1"){
 alert(incoming.svrMessage);
 }
 }
 });
 }
</script>
</cfif>

Basically this is just looping through the database and outputting all the images in divs in the div named sortableContainer which has the sortable() interaction applied to it.   I also bind to the stop event which will fire when a sortable child is released which will build a string containing the image id’s in the proper sort order.  I pass this value to the setImageSortOrder() function which makes an AJAX call to my remote proxy which will update the values in the database.

<cffunction name="setImageSortOrder" access="remote" returntype="struct" returnFormat="JSON">
 <cfargument name="sortOrder" type="string" required="yes"/>
  <cftry>
  <cfscript>
   var response = structNew();
   var imageObj = "";
   var sortCnt = listLen(arguments.sortOrder);
   var i = 0;

   for(i=1; i lte sortCnt; i++){
    imageObj = application.transfer.get("images", listGetAt(arguments.sortOrder, i));
    imageObj.setSortOrder(i);
    application.transfer.save(imageObj);
   }
   response['svrStatus'] = "0";
   response['svrMessage'] = "Video sort order updated successfully.";
  </cfscript>
  <cfcatch type="any">
   <cfscript>
    response['svrStatus'] = "-1";
    response['svrMessage'] = cfcatch.Message;
   </cfscript>
  </cfcatch>
 </cftry>
 <cfreturn response/>
</cffunction>

The function setting the sort order in the database is pretty straight forward.  I am using Transfer ORM for my database interactions, but it would be easy enough to covert the example into a query.  Since the jQuery function is passing a list of the image id’s in the correct order I loop through the list and set the sort order of each image to its index in the list.  No need to worry about items having the same sort order and displaying incorrectly.  It is pretty much fool proof.

Also of note, this code makes use of the $.parseJSON() function added in jQuery 1.4.1.  No more having to worry about whether or not a browser can support JSON.parse().  This in itself is a good reason to switch to a newer version of jQuery if you have not already.

Debugging ajax calls with ColdFusion


I was debugging a video conversion application this afternoon that relies heavily on ajax to move the user along in the conversion process.  After each step in the process another ajax call is fired off to continue to the next step.  When things are working as expected it is a beautiful thing, when it does not things tend to get interesting.  I had some code inside my CFC and the server was throwing a hard error, needless to say my response codes were never returned back to my ajax call from the remote method.  The user would end up staring at a processing screen that would never go away.

To get around this I standardized all my ajax calls.  No matter what information I am expecting back from my CFC, I always pass back a svrStatus variable and a svrMessage variable.  Server status is the variable I check to make sure everything went as planned, if it is not 0 I know there was a problem.  The svrMessage variable is what I want the users to see so they are not scratching their heads wondering what is going on.

I whipped up a quick demonstration.  It is definitely nothing new, but I thought maybe it would help someone out.

Our basic page:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ajax debug</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>

<body>

<div id="results" />

<script type="text/javascript">
 $(document).ready(function(){

  $res = $('#results');

  for(var i = 0; i < 3; i++){
   $.ajax({
    url    : 'remoteProxy.cfc',
    data   : {
    method : 'remoteFunction',
    pass   : i
   },
   async   : false,
   success : function(data) {
    incoming = JSON.parse(data);
    $res.append( '<strong>Pass ' + i + ':</strong> ' + incoming.svrMessage + '<br/>');
   }
  });
 }

 });
</script>
</body>
</html>

remoteProxy.cfc:

<cfcomponent output="no">

 <cffunction name="remoteFunction" access="remote" returntype="struct" returnFormat="JSON">
  <cfargument name="pass" type="numeric" required="yes"/>
  <cfset var respsone = structNew()/>
  <cftry>
   <cfset response['svrStatus'] = "0"/>
   <cfset response['svrMessage'] = "Method completed successfully"/>

   <cfif arguments.pass eq 1>
    <cfthrow message="Doh!  Something broke!"/>
   </cfif>
   <cfcatch type="any">
    <cfset response['svrStatus'] = "-1"/>
    <cfset response['svrMessage'] = cfcatch.Message/>    
   </cfcatch>
  </cftry>
  <cfreturn response>
 </cffunction>

</cfcomponent>

There is nothing too complicated going on here.  The web page makes a call to our remote CFC and in this case it is hard-coded to throw an error on the second pass, simulating an error condition.  The whole method is wrapped in a CFTRY block so if something did occur while the method was executing it would fire the CFCATCH block.  The CFCATCH block sets the svrStatus to -1 letting me know that there was an error and it also sets the svrMessage variable to CFCATCH.Message so we will know the root cause of the problem.

The web page itself is not that complicated either.  After making the ajax call we parse the data returned into JSON.  At this time we could simply look at the svrStatus variable see if we have an error and display a message if so.

Any other tips and tricks for debugging ajax calls?

Using jQuery to scroll to the bottom of a div, revised


I am a firm believer that every day you should learn something new.  In this particular case, I learned something new quite some time ago and just never applied it to my code samples.  This is something I really want to pay more attention to because I do not want be a purveyor of misinformation.

Nick commented on this original post that once the animation began he could not scroll back up to the top of the post.  Looking into the problem I immediately noticed what was happening, the scrollHeight attribute was not taking into account the height of the scrolling div.  If the scrolling div has a height of 100px initially and enough text has been entered to scroll it, it may have a scrollHeight of 120px.  Moving down to the bottom of the div, the scrollTop would be 20px which is the scrollHeight – $(‘#div’).height().  Adjusting for that in the jQuery code will make it function as expected.

The corrected code is below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuery Scroller</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
</head>
<body>
<div id="myDiv" style="width: 500px; height: 100px; overflow: auto; border: 1px solid black;"></div>
<input type="text" id="myTextInput" />
<input type="button" value="Send" id="postButton" />
<div id="info"/>
<script type="text/javascript">
 $(document).ready(function(){
  $('#postButton').click(function(){
   $('#myDiv').append($('#myTextInput').val() + '<br/>');
   $('#myTextInput').val('');
   $("#myDiv").animate({ scrollTop: $("#myDiv").attr("scrollHeight") - $('#myDiv').height() }, 3000);
  });
 });
</script>
</body>
</html>

Update 9/5/2011:
As JP points out in the comments below, this may need to be modified to work with jQuery 1.6.1
http://stackoverflow.com/questions/6194837/somediv-attrscrollheight-not-working-in-jquery-1-6-1