Debugging CF and JavaScript, flexbox combobox jQuery

Invalid JSON property [object Error] found when trying to apply resultTemplate or paging.summaryTemplate. Please check your spelling and try again. Error: Unable to get value of the property 'name': object is null or undefined

Getting errors when using flexbox combobox on IE7 and IE8. The code runs on IE9, Chrome, and all Firefox.

Using ColdFusion to generate JavaScript can sure lead to complications when trying to debug. It's complicated trying to write the CFML to generate the code, but we do it to make our lives easier!

This post is more about the process of debugging than writing or even the actual solution. First I will list efforts that proved worthless. I'll bet you tried at least one of these before finding this post.

  1. Searching for "resultTemplate" and/or "summaryTemplate"
  2. Editing jquery.flexbox.js. I actually put in "alert"s to step debug – waste of time.
  3. Edited the generating CF code to add spaces in the resultant JS.
  4. Did a LOT of Googling. This only helped if you found this article, which wasn't here when I went through the process!
So what worked? or how do we find the cause?

The first objective is to narrow down the area which is causing the problem. Because it was clicking in the combobox throwing the error, that sure helped. Next is to look at the JavaScript generated for the combobox. Here's what I had.

view plain print about
1<scr!pt type="text/javascript">var values_6789 = {};values_6789.results = [{id: "View The Collection", name: "View The Collection"},{id: "View The Trunk Show Collection", name: "View The Trunk Show Collection"},{id: "Personal Appearance", name: "Personal Appearance"},];values_6789.total = values_6789.results.length;$(document).ready(function () {$("#misc2").flexbox(values_6789, {autoCompleteFirstMatch: false, selectBehavior: true, paging: false, width: 180, noResultsText: "" });});</script>

Looking through this code, something very small is out of place, a comma.

view plain print about
1......name: "Personal Appearance"},];values_6789.total =......

The comma just before the closing bracket, "]".

Here's the code that builds that part of the JavaScript

view plain print about
1<cfloop query="arguments.qProductAddorValues">
2 <cfif arguments.qProductAddorValues.productAddorID eq arguments.productAddorID>
3 <!--- write element for the JSON object --->
4 <cfset fldString.append('{id: "#arguments.qProductAddorValues.value#", name: "#arguments.qProductAddorValues.name#"} ' )>
5 <cfif arguments.qProductAddorValues.currentrow neq arguments.qProductAddorValues.recordcount>
6 <cfset fldString.append(',')>
7 </cfif>
8 <cfif (len(arguments.fldval) and not cbBoxFldValAdded)>
9 <!--- this string is used for initialization of the control --->
10 <cfset defaultSelection = ',initialValue: "#arguments.fldval#"'>
11 <cfif arguments.qProductAddorValues.currentrow neq arguments.qProductAddorValues.recordcount>
12 <cfset fldString.append(',')>
13 </cfif>
14 <cfset cbBoxFldValAdded = 1>
15 <cfelse>
16 <cfif (arguments.qProductAddorValues.default eq 1 and not cbBoxFldValAdded)>
17 <cfset defaultSelection = ',initialValue: "#arguments.qProductAddorValues.value#"'>
18 </cfif>
19 </cfif>
20 </cfif>
21</cfloop>

Why is that extra comma there? There's a checking for the end...

view plain print about
1<cfif arguments.qProductAddorValues.currentrow neq arguments.qProductAddorValues.recordcount>
2 <cfset fldString.append(',')>
3</cfif>

The logic is probably bad. To prove it we have to output the 2 variables in the test. We have to output them and NOT break jQuery so the page will render AND still display the variable output.

This is done by commenting out the variable output with JavaScript syntax, /* stuff */. First, I create a string with the 2 test variables and concatenate them together with opening and closing JS comments.

view plain print about
1<cfset JSStringTest = "/* " & arguments.qProductAddorValues.currentrow & " = " & arguments.qProductAddorValues.recordcount & " */" />

Then I stick output of the string into the generated JS string where I think it will be innocuous. Outside of the array but inside the single quote.

view plain print about
1<cfset fldString.append('{id: "#arguments.qProductAddorValues.value#", name: "#arguments.qProductAddorValues.name#"} #JSStringTest#' )>

Here is the resultant JavaScript output:

view plain print about
1<scr!pt type="text/javascript">var values_6789 = {};values_6789.results = [{id: "View The Collection", name: "View The Collection"} /* 2 = 63 */,{id: "View The Trunk Show Collection", name: "View The Trunk Show Collection"} /* 3 = 63 */,{id: "Personal Appearance", name: "Personal Appearance"} /* 4 = 63 */,];values_6789.total = values_6789.results.length;$(document).ready(function () {$("#misc2").flexbox(values_6789, {autoCompleteFirstMatch: false, selectBehavior: true, paging: false, width: 180, noResultsText: "" });});</script>

You can see that the commented /* 4 = 63 */ for the final entry is obviously false. Thus proving the test is bad.

From here I have 2 options

  1. Find an accurate test.
  2. Just remove the last comma.

In this instance there really wasn't a valid test that could be easily and accurately generated. Information was being pulled from too many different places. I decided to just add the trailing comma after every iteration and remove it from end of the string after the loop is completed, but before we appended more JavaScript.

This turned out to not be easy either. If you recall, the string, fldString was appending JavaScript using:

view plain print about
1fldString.append()

This was because fldString is not really a string but a Java object created with:

view plain print about
1fldString = createobject("java", "java.lang.StringBuffer").init()

using CF's create Java object and Java's StringBuffer class. So the "fldString.append()" is a StringBuffer method.

What other StringBuffer method can I use to trim off the pesky trailing comma? We could use deleteCharAt() but how to find what the index is of the comma. It's at the end of a variable length string, changing every time the function is called. Well we just find the length of the string using another StringBuffer method, length(). Can't get much simpler than that! So here is how that code looks:

view plain print about
1<!--- remove trailing comma which is always added above ~ line 156, using Java StringBuffer class --->
2<cfset fldString.deleteCharAt(fldString.length()-1) />

Starting from the inside, we find the fldString length, subtract one and delete the character in that position.

So here's the final bit of completed code:

view plain print about
1<cfloop query="arguments.qProductAddorValues">
2 <cfif arguments.qProductAddorValues.productAddorID eq arguments.productAddorID>
3 <!--- write element for the JSON object --->
4 <cfset fldString.append('{id: "#arguments.qProductAddorValues.value#", name: "#arguments.qProductAddorValues.name#"},' )>
5 <cfif (len(arguments.fldval) and not cbBoxFldValAdded)>
6 <!--- this string is used for initialization of the control --->
7 <cfset defaultSelection = ',initialValue: "#arguments.fldval#"'>
8 <cfset cbBoxFldValAdded = 1>
9 <cfelse>
10 <cfif (arguments.qProductAddorValues.default eq 1 and not cbBoxFldValAdded)>
11 <cfset defaultSelection = ',initialValue: "#arguments.qProductAddorValues.value#"'>
12 </cfif>
13 </cfif>
14 </cfif>
15</cfloop>
16<!--- remove trailing comma which is always added above ~ line 156, using Java StringBuffer class --->
17<cfset fldString.deleteCharAt(fldString.length()-1) />

Bam! The JSON error is gone in IE7 and IE8 and the code still runs perfectly in all other browsers. This is a long story with a few important pieces. I'll break out the useful tidbits and post those in separate blog entries so that others may find specific answers without having to read this saga.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)

Previous Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.7. Contact Blog Owner