I'm working on a new project now (Picard FTW - Engage!) and it involves converting some existing JavaScript. The "old" JavaScript works fine, but is very difficult to get to and also suffers from the fact that it isn't jQuery. That's a huge problem if you ask me. So as I work through the project I'm slowly converting various dynamic elements into ColdFusion. One of those elements was pretty interesting. A list of fields had an associated piece of metadata. Each piece was represented in simple text. Next to it was an edit link. Clicking edit changed the plain text into a drop down. I reworked this into jQuery and this is what I came up.

First let's define the data. My form will have a list of movies. For each movie there is a simple rating system based on 4 values: Hated It, Disliked It, Liked It, Loved It. It is assumed that the user has already selected some values which end up being rendered as hidden form fields:

   view plainprintabout
 star wars: <span class="changeable"><input type="hidden" name="starwars" value="4">Loved It - <a href="" class="edit">edit</a></span><br/>
 star trek: <span class="changeable"><input type="hidden" name="startrek" value="3">Liked It - <a href="" class="edit">edit</a></span><br/>

This wouldn't normally be hard coded - it would come in dynamically via ColdFusion. But you get the idea. Notice that I've wrapped the hidden field, the current text, and a link within a span. Ok, now for the jQuery:

   view plainprintabout
 $(document).ready(function() {
 
     //used for our drop downs
     var values = [1,2,3,4]
     var labels = ["Hated It","Disliked It","Liked It","Loved It"]
     
     $(".changeable a.edit").click(function() {
         //find the hidden item
         var hiddenItem = $("input:hidden", $(this).parent())
10          //get the current val
11          var currentVal = hiddenItem.val()
12          //get the name
13          var currentName = hiddenItem.attr("name");
14          //now we can draw our drop down and select the right val
15          var s = "<select name=\""+currentName+"\">";
16          //hard coded values for our drop down
17          for(var i=0;i<values.length;i++) {
18              s+= "<option value=\"" + values[i] + "\""
19              if(currentVal == values[i]) s+= " selected"
20              s+= ">" + labels[i] + "</option>"
21          }
22          s += "</select>"
23          //now replace
24          $(this).parent().html(s)
25          return false    
26      })
27  
28  })

First notice I've got two hard coded values. These represent the values and labels for the drop down I'll build later. Again, this would probably be dynamic. Don't forget ColdFusion provides a nice utility function, toScript, to make it easy to convert ColdFusion variables into JavaScript.

Now let's walk through the main function. My selector looks for links with the class edit with DOM items with the class changeable. I've binded to the click event for the link. This matches the link within the span I used. But I need to get information from the rest of the span. So I grab a pointer to the hidden form field by doing a selector against the parent of the link. Does that make sense? Ie: "jQuery, within the parent of what you just found please look for a hidden input field." Once I have that I can get the value as well as the name.

Once I have the name, and the current value, building the drop down is just a matter of string builder. I use the values/labels variables and just create the select. When done I can replace the link for the span. Remember that $(this) represents the original link so $(this).parent() will be the span.

You can see a demo of this here: http://www.coldfusionjedi.com/demos/changedropdown/test.cfm

And here is the complete script:

   view plainprintabout
 <html>
 
 <head>
 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
 <script>
 
 $(document).ready(function() {
 
     //used for our drop downs
10      var values = [1,2,3,4]
11      var labels = ["Hated It","Disliked It","Liked It","Loved It"]
12      
13      $(".changeable a.edit").click(function() {
14          //find the hidden item
15          var hiddenItem = $("input:hidden", $(this).parent())
16          //get the current val
17          var currentVal = hiddenItem.val()
18          //get the name
19          var currentName = hiddenItem.attr("name");
20          //now we can draw our drop down and select the right val
21          var s = "<select name=\""+currentName+"\">";
22          //hard coded values for our drop down
23          for(var i=0;i<values.length;i++) {
24              s+= "<option value=\"" + values[i] + "\""
25              if(currentVal == values[i]) s+= " selected"
26              s+= ">" + labels[i] + "</option>"
27          }
28          s += "</select>"
29          //now replace
30          $(this).parent().html(s)
31          return false    
32      })
33  
34  })
35  
36  </script>
37  </head>
38  
39  <body>
40  
41  <form method="post">
42  
43  star wars: <span class="changeable"><input type="hidden" name="starwars" value="4">Loved It - <a href="" class="edit">edit</a></span><br/>
44  star trek: <span class="changeable"><input type="hidden" name="startrek" value="3">Liked It - <a href="" class="edit">edit</a></span><br/>
45  
46  <input type="submit" value="click me like you mean it">
47  </form>
48  
49  <cfif not structIsEmpty(form)>
50      <cfdump var="#form#" label="form">
51  </cfif>
52  
53  </body>
54  </html>