Today's Weird JavaScript Issue

This post is more than 2 years old.

I ran into an interesting JavaScript issue yesterday. A user reported a bug with ColdFusionBloggers and searching. If he searched for one word, like 'object', then he could navigate through multiple pages of results just fine. If he search for two words, 'object oriented', then as soon as he clicked next the page would break.

This immediately made me think that I had forgotten a urlEncodedFormat() call somewhere. I'm very good about remembering that but it was certainly possible I could have made a mistake. (Although I'd probably blame Microsoft somehow.) When I opened the file though I could plainly see that I was indeed urlEncodeFormating the string before passing it to my JavaScript code to handle navigation.

I wanted to blame jQuery for this. When you use jQuery to do an Ajax-based content load into a div, they support loading a URL and optionally filtering to a div. What I mean is, you can say: I want you to load the contents of foo.cfm into my div called content, however, I don't want you to load all of foo.cfm, I want you to load the goo div's content only.

Here is an example that does a plain load of foo.cfm, and then another one that loads the goo div from foo.cfm:

$("content").load('foo.cfm')

versus...

$("content").load('foo.cfm goo')

Notice that the syntax uses a space to signify that the goo div is what we want from foo.cfm. My code was passing a URL that looked something like this:

content.cfm?start=11&search=foo%20goo (a search for foo goo)

Notice the escaped space. I thought perhaps jQuery was un-encoding the string somehow and getting confused. However, as I dug more, it seemed more as if that the string was being undecoded as it arrived to the function. I was able to recreate this bug without any jQuery at all:

<cfset s = "frank and beans"> <cfset u = "test3.cfm?x=1&foo=#urlEncodedFormat(s)#">

<script> function testit(s) { console.log(s); } </script> <cfoutput> <a href="javaScript:testit('#u#')">Test1</a><br /> <a href="" onClick="testit('#u#');return false">Test2</a><br /> </cfoutput>

So get this. Notice how the first link uses a javaScript: style link while the second uses an onClick. When you run this test, the first one will log test3.cfm?x=1&foo=frank. No beans! Edit: I had a brain fart there. The console shows frank and beans, but w/o the %20, the escape. End Edit The second test will correctly show the entire string with the proper escape values. I also tested with an input type=button and it worked fine as well.

So for some reason, when the string was passed using the href property of the anchor, the encoded part of the string is lost somehow. Now I'm still getting used to JavaScript after my long, dark, cold war with it, and I believe that I've read the using the event handler way is 'more proper', but this is the first time I've been bitten by something like this.

Does anyone know of any place where this behavior is documented?

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 Jon Dowdle posted on 10/22/2008 at 6:22 PM

While I couldn't find anything specific to this, have you tried escape() and unescape()?
If you don't go the event handler approach that should solve your problem.

Comment 2 by Ernst van der Linden posted on 10/22/2008 at 6:23 PM

Hi Ray,

If you replace console.log(s) by alert(s), you'll see the difference.
I agree, it's weird.

Comment 3 by Raymond Camden posted on 10/22/2008 at 6:31 PM

I'm not seeing a difference. But I made a mistake in my blog entry (going to correct it after this comment).

The console.log DOES show frank and beans, but WITHOUT the escape. Brain fart on my part. Still wrong for sure.

Anyway, the alert shows the same as the console msg for me.

Comment 4 by Raymond Camden posted on 10/22/2008 at 6:34 PM

Guys, I've edited the blog entry a bit. Hopefully it clears up the confusion (although I'm still confused by the behavior in general!)

@JD - For CFB, I just used replace and switched spaces to +. I didn't notice the 'nicer' event handler fix till later.

Comment 5 by Tim Garver posted on 10/22/2008 at 6:52 PM

Hi Ray,
Have you tried to see if setting the encoded var into a js var makes a difference before adding it to the href?

<cfset s = "frank and beans">
<cfset u = "test3.cfm?x=1&foo=#urlEncodedFormat(s)#">
<cfoutput>
<script>
function testit(s) { alert(s); }
var s = '#s#';
var u = '#u#';
</script>

<a href="javaScript:testit(u)">Test1</a><br />
<a href="" onClick="testit(u);return false">Test2</a><br />
</cfoutput>

Comment 6 by Mat Evans posted on 10/22/2008 at 7:33 PM

Tim's method works perfectly, also using encodeURI() produces the proper result.

I haven't found any mention of a problem such as this before, the only thing I can think of is that the string is getting parsed improperly when it's first initialised in the JS engine, although it's strange that putting it into a javascript variable works.

Seems to show the same behaviour in different browsers.

Comment 7 by Tim Garver posted on 10/22/2008 at 7:40 PM

Just a thought,

Its probably the browsers HTML engine since the string is being added to the href property. that would make since because its being evaluated before its passed to the JS engine.

Tim

Comment 8 by Mat Evans posted on 10/22/2008 at 7:51 PM

yeah possibly.. although it seems to do fine in the page source..

Not sure what else we can do to get to the bottom of it really.. it's strange it's not documented anywhere?

Comment 9 by Nathan Mische posted on 10/22/2008 at 7:53 PM

I think Tim is probabaly right. Href is a DOM attribute, defined as a string, while click is a DOM event, defined as function reference.

Comment 10 by Jason Fisher posted on 10/23/2008 at 12:20 AM

Definitely have seen this and related issues before that seemed to only show up when using href="javascript:foo();", but I've made a habit of using href="javascript:void(null);" onclick="foo();" for so long now that I don't recall whether I ever knew *why* things would error using the first way. I'm guessing Nathan has it right: the events like onclick can even string several functions all together, with spaces between, in, and around, as necessary.

Comment 11 by brendan posted on 10/23/2008 at 5:04 PM

If you load up the page and put this is the browser address box it acts like the href link

javaScript:testit('-%20-')

Its automatically unencoding the url for use.