Saturday, April 14, 2007

Gmail HTML Reply Signatures and JavaScript

Nested Quotes causing Bug in HTML Reply Signatures for Gmail

After doing a google search to see where my blog ranks, I've found that some people have been having trouble with the Gmail HTML Reply Signatures script that Greasemonkey uses to embed HTML signatures in Gmail. Consider this to be your user-guide for the script, as well as a little lesson in the intricacies of JavaScript.

Unless you've spent hours banging your head against your computer trying to get JavaScript code to do what you want it to do, you may be confused by the different syntax that you would see when reading code written by different programmers. Come to think of it, even after banging your head against your computer trying to get the code to do what you want it to do, you may still be confused.

In the Gmail HTML Reply Signatures script, the code you are instructed to modify looks like this:

var htmlsig = '<br><p><img src=""></p><br>';

Notice that there are quotes and there are apostrophes. The apostrophes represent the beginning and the end of a string of text that is assigned to the variable called htmlsig. The string also happens to be HTML. However, in JavaScript, the HTML is simply a string that will be used to generate HTML in the Gmail compose window. When this string is written to the browser, it is then read as HTML and interpreted as such.

Now, consider this line of code, which will not work properly due to errors:

var htmlsig = "<br><p><img src=""></p><br>";

Can you see why this won't work? Yes? Good! You've probably had quite a bit of JavaScript experience! You may have even made this mistake yourself in the past. But if you can't see the error, no worries, this is a great learning experience for you! Notice that there are four quotes ("). The JavaScript parser -- if that is what you call it -- is confused because the first quote represents the beginning of a string and the second quote represents the end of the string. But the second quotation mark is actually for the string within the string; it is supposed to mark the assignment of the url to the src attribute.

Nested Quotes JavaScript Analogy

Think about the last book you read where the main character quoted another character:

Mark said to Tammy, "What did John tell you?". Tammy replied, "Mark, John said: 'The only dumb question is the one that is never asked!', and I think he really means it.". Mark raised an eyebrow...

Notice how the storyline is told outside of quotes, quotes are used to indicate a character speaking, and apostrophes are nested within quotes to indicate a person speaking about a person speaking. Could this pattern be nested deeper, such as a person speaking about a person speaking about a person speaking? It could, but we only have two delimiting characters: Quotes and apostrophes. We'll come back to this problem later.

For now, lets apply this really horrible story about Tammy, John, and Mark to our Gmail HTML Reply Signatures nested quote problem. I'm a big fan of analogies, so lets use the following analogies to compare the story to our JavaScript problem:

  • Narrator text outside of quotes - The story - JavaScript API (functions, variables, etc)

  • Character text within quotes - A string assignment - What JavaScript will say to Gmail

  • Character quoting character text within apostrophes - A quote within a string - What JavaScript will tell Gmail to tell the src attribute

Now, what would the reader think of this:

Mark said to Tammy, "Tammy, my writing career is in the toilet, what is this story about?". Tammy looked puzzled. Finally she said, "John said, "This quote is confusing because it is a quote within a quote.", and not to worry about our careers".

Notice the inner quotation uses the same type of quote. Instead of an inner quote, the text would actually represent the narration and not any type of quote.

Think of writing JavaScript as writing a book where the JavaScript parser is your reader, or audience. Unlike a human who could more than likely look past the incorrect usage of quotation marks, the JavaScript parser will become extremely confused by incorrect nesting of quotes.

Which nested JavaScript quote comes first?

Now here comes the really interesting part. You can use quotes in whatever order you want. Consider this:

var htmlsig = "<br><p><img src=''></p><br>";

Notice that I reversed the (') and the ("). The quotation mark is now the outer string wrapper and the apostrophe now represents the inner string wrapper. Be prepared to see differences, as unlike publishing a novel, there is no rule determining whether an apostrophe is used first or a quote is used first. As long as one type is used for the outer string and the other type is used for the inner string, your result will be the same.

Quote within a Quote within a Quote within a ...

If you feel that you now have a good understanding of this concept, I've got a little exercise for you. Remember the story with John, Tammy, and Mark? I mentioned that it was possible to have a character quote a character quoting another character. Can you represent this third-level quote in JavaScript? How would you solve this problem? Remember that there are only two types of quotes, the (") and the ('). There is a solution to nest quotes deeper, good luck!

Feel free to drop me an email if you have any questions or would just like to chat about this topic. My email address is . If you are a beginner to JavaScript, please give me some feedback. Let me know if I have completely confused you. Have I cleared up any misconceptions you may have had and helped you see the light? Let me know.

Thank you,
James Mortensen

UPDATE: The article, Nested-Nested Quotes, describes the concept of nested quotes even deeper using real code and provides the solution to this problem!