Hello! I have a question about mixing ColdFusion a...
# cfml-general
j
Hello! I have a question about mixing ColdFusion and Javascript. I have code that is structured in the following way:
Copy code
<cfoutput>
...
     <cfloop>
          <cfset FormElementPK = rc.formElements.getRow(i)["FormElementsPK"]>
          <script>
               //Create a listener for the question text editor to check for errors on blur
               var #toScript(FormElementPK, "jsFormElementPK")#;
               var inputFieldId = document.getElementById("##question" + jsFormElementPK + "TextEditor");
               $(inputFieldId).on('blur', function(e) {
                                alert("I am a test message!");
                                checkQuestionTextForErrors(inputFieldId);
                            });         
          </script>
          ...
     </cfloop>
...
</cfoutput>
Its intended effect is to dynamically generate Ids and then create Jquery event listeners for those Ids. The problem I have is that the event listeners work only when I hardcode the Ids (replace inputFieldId with "##question1TextEditor" etc). I'm wondering, why does this not create working event listeners when I dynamically generate the Ids the way code above does?
w
where does this block of code run, in the head of the page or the body or right before the closing </body> tag?
it should go before the closing body tag as written
j
It runs within the body tag, and there is other content between this code and the closing body tag.
w
does it run after the form elements it references are rendered?
j
Nope, each instance of this code is before the Ids it references.
w
try wrapping your generated code with
$(document).ready( your code here )
right, so then move your generated block below the form elements it references, or follow my suggestion above
j
This is worth a perusal. Used to have the same issue, might be related - https://stackoverflow.com/questions/9484295/jquery-click-not-working-for-dynamically-created-items
That’s using jQuery though.
w
it fails to bind events to elements that don't exist yet
i'm also failing to see the value in toScript here. if you paste a block of generated code it may be more obvious where the problem lies
j
So it moved this code below the elements it references and it works now!
w
the takeaway is that when binding events like you're doing, the elements that you're targeting must already be in the DOM. otherwise, you can delay the execution of those js statements until the entire DOM has been rendered by putting the code in $(document).ready( ... )
j
Okay, that's really helpful! Thank you websolete.
g
We make sure that we always use the document.ready() handler. It rules-out the "obvious" mistakes - that of course just aren't obvious, when you're looking for them! As an additional - Don't forget to use your browsers debugger / developer tools. Put in a "break-point" and see if you can reference your "id"s / variables - at the point you think you should be able to.
m
if you want to loop over each field and add separate scripts into dom for each id, as your example shows: (you can comment out the 2 lines that start with var, and is using the formElementPK from the example) keeping in mind as websolete points out, these do need to already be in the dom
Copy code
$("##question#encodeForJavascript(formElementsPK)#TextEditor").on("blur", function() {
	var myChange = $(this);
	console.log( "blur happened " + myChange.attr("id") + " is now " + myChange.val() );
});
personally though, I'd drop in a single script, rather than one per input, and would add a class="myFancyElement" to your inputs, for jquery to select off of. So that I can use one selector, while this also still requires the elements to exist in the dom, it doesn't require as much duplication.
Copy code
$(".myFancyElement").on("blur", function() {
	var myChange = $(this);
	console.log( "blur happened " + myChange.attr("id") + " is now " + myChange.val()   );
});
if your form could change dynamically, then you can also add a class="myFancyForm" to something that wraps the fields and do a similar item as above. Then any item that is in the dom and any item added later with the myFancyElement class will also be able to trigger the on blur.
Copy code
$(".myFancyForm").on("blur", ".myFancyElement", function() {
	var myChange = $(this);
	console.log( "blur happened " + myChange.attr("id") + " is now " + myChange.val()   );
});