Why won’t my span respond to click events? Strings vs. DOM elements
I had another fun opportunity to work on a web app (I’ve been doing a lot of them lately) over the last week. This time I built on my recent JSON experience by writing a Rails app that only communicates in JSON. Rather than have the output built using Rails views the output is sent as JSON to a JavaScript client in the user’s web browser.
Once in the web browser, the data has to be parsed and split up into different sentences based on what the user wants to do with the data. Once the data is split into sentences it’s appended to divs that show the sentences in the web browser. Some of these sentences have to be clickable, they must respond to a “click” event coming from the user. This is completely ordinary in most JavaScript web apps. The user clicks, the browser responds. Imagine my surprise when my sentences weren’t responding to the click input.
I wasn’t surprised for very long, however. By looking at how I prepared the sentence in the JavaScript code made it pretty obvious what was going on.
data[index] = data[index] + ". <span class=\"my_class\">" + choices[choiceIndex++] + "</span>";
This created the sentence that was to be clickable. It’s just string data that creates a span with a class. This is something jQuery can find by doing $(“.my_class”). Once I have all the spans with that class I can add a click event to them. Well, that’s true, but those spans have to be DOM objects before jQuery can find them.
The way I was doing it, those spans were just string data. Sure, the browser displayed them with the correct style but jQuery was unable to find them because they were not internalized as DOM objects. Opening a JavaScript console with Google Chrome would allow me to run the same code to make the spans respond to click events and it would actually work. Chrome’s console reads the DOM after the page has been rendered and creates the DOM objects based on the rendered page when the spans are in place. This is no good to me. I can’t tell my customer to tell his customers to open a JavaScript console and run this cryptic command after loading the page.
In order to get the behavior we want we have to create DOM objects using jQuery so jQuery can then find these objects to add the click behavior to them. Rather than creating spans as string data we use the jQuery function to create a DOM element with the correct class and text.
elm = $("<span class=\"my_class\">" + choices[choiceIndex++] + ". </span>");
elm.click(function(){
alert("Hey! You got the right answer!");
document.location = "http://localhost:3000";
});
The jQuery function, $( ), first looks for elements based on the class, id or attribute selector passed in to it. If there is no selector then the function looks for any tags in the string passed in to it. If there are tags, in our case span tags, jQuery creates the appropriate DOM element based on the content of those tags! This is great! Now I can pass in my string data and have jQuery return a DOM element that I then bind to the click function specified.
Adding the click function later also works now.
$(".my_class").click(function() {
alert("Hey! You got the right answer!");
document.location = "http://localhost:3000";
});
I’m happy with the way I can build a DOM element using the jQuery function. In order for jQuery to find the objects we look for those objects have to be DOM elements, not just string data appended to a div. DOM elements respond to events, strings do not.




