Inline Event handler messing with event handler in separate JavaScript file - javascript

Could something in the code of an inline event handler like in the HTML markup affect some code or prevent it from firing code in a JavaScript file that is later called. Suppose the JavaScript file contained something like this.
$(a).click(function() {
//some code
}
someJavaScriptCode isn't meant to be valid JavaScript syntax. It is generated by the PrimeFaces library.
My event handler in the JavaScript file works once, but any subsequent clicks after that; it doesn't fire. The code in the inline event handler still works however. I didn't make up the inline code; it was web application's UI library doing that. I'm just wondering how I can make the code above still work.

If your inline code has an error in it, and it is executed before the JavaScript in your javascript file, then it will halt javascript execution which would prevent your external file javascript from running.
I hope this helps.

Are you using a framework that re-renders your DOM? It seams that when you click the element, it is replaced and it looses the event that is applied in your JavaScript file.
If that is the case, place your event on a parent that is not being re-rendered, and target the element this way:
$( parent ).on( 'click', 'a', function (e) {})
The second argument in the "on" method will target any selector and apply the click even, even if the content of the parent is refreshed.

Related

JavaScript Function on Injected Content

So something I'm curious about, how the YUI3 PJAX works. For instance, when used, even if you inject an anchor into the page with the yui3-pjax class and click it - that will run the AJAX function.
My question is does that use a Promise or what to determine if the anchor, including injected anchors, has the class?
I have a function for observing mutations for a site and I call it on the click event for the yui3-pjax anchors already existing in the page, but I also want to have it run on yui3-pjax anchors that I dynamically load into the page without having to recall the function.
Using jQuery for the ease of sample code, a similar solution can be written in vanilla Javascript as well.
You can use .on() with a selector parameter. For example:
$('body').on('click', '.class', function(e) {
e.stopPropagation(); //Stop multiple possible triggers from the same click
//TODO: Rest of code
});
The downside obviously being that every click on your highest common ancestor will get processed. The upside is however that since the click is caught there (not on the elements themselves) you don't have to worry about rebinding events.

How to find a Javascript function if it is event handler?

I want use Chrome developer tool to add a break point to js function to debug it.
For example, a function "buttonAlert()" is binded to a button.
But I don't know where the code of such function, and I don't know where the code that bind the function to button.
So, how can I use the tool to find out the location of function and binding code?
It is actually possible to see event listeners in chrome.
Go to the elements panel, select the element in question and click on Event Listeners on the right side.
Sadly most of the time when jQuery is in use, you only see the part of the source of jQuery that bound the event, not the one that called jQuery.

document.write and delegated event handler persistence

I'm just testing out replacing a whole page with another page using JavaScript and I found this answer with document.write. As to why document.write, I needed to replace the entire HTML, including scripts and styles using the same page.
It does what I want but i can't seem to have consistency with my event handlers. My handlers are all attached to document using:
$(document).delegate(...);
Currently, I have weird results. In a fiddle I made, it attaches a handler. When clicked, the event fires, rewrites the page, runs the function again - but it doesn't attach the handler.
However in my project, I'm doing the same routine (d.w(), then add handlers). It does reattach once and handlers work, but after doing a second routine (still on the same page), it doesn't attach anymore.
So my questions are:
When using d.w(), do existing handlers get erased from document?
Are window as well as document the same after subsequent d.w()s? or are they somehow "renewed"
Do scripts that are already parsed stay in memory and run after subsequent d.w()s? Or do they get erased as well?
(The following applies to google chrome)
Only the document is cleared, the scripts in memory still stay the same. You can easily test it by setting something to a variable and see if it exists after clearing out the document with .open.
The old native handler is therefore lost from the document, but jQuery still thinks that the handler exists in its own event model. You can see it by editing the log to:
console.log('patch', JSON.stringify($.cache ));
jQuery only ever attaches a single native handler per event, so if you have a "click" event registered on document, further handlers attached with jQuery don't attach a new native handler, instead the handler is pushed into the jQuery internal handlers array.
Now, because document.open removed the native handler, but doesn't clear javascript, jQuery still thinks the native handler exists, and further .delegate only goes to the jQuery internal handler array. If you replace your handler with plain old document.onclick you will see it starts working.
You can also keep using jQuery if you add $(document).unbind() (or more robust $.cache = {};, but this is internal and subject to change) before the .delegate, so that jQuery is again synced. Otherwise it won't be, since it has no idea you called document.open.
So:
Yes
They are still the same objects, can be tested by saving a reference and checking that agaist document after a .open
They stay in memory.
http://jsfiddle.net/wphzt/4/
The only reason it stops working from second time onwards is because in your function you have written
document.write('<span>'+(++i)+'</span>');
In which case, next time the document doesn't have the delegate function to increment the span value but has only what you have written in the code snippet I have highlighted above. Thus, as you doubted, yes they get erased as well. Hope this helps.

Does this code need to be in a document.ready?

The document.ready is used to execute code after the DOM is fully loaded. This can be used to attach event handlers to elements on the page e.g
$(function(){
$('#somediv').click(function(){
});
})
<div id="somediv"> </div>
Internally, jQuery hooks up to DOMContentLoaded and window.onload as a fallback. In IE's case an attempt is made to scroll the viewport over and over until successful.
I have a few questions, my first one being, when binding event handlers to the document itself, is it necessary to put that code in a document.ready ? I have always been writing the code below without wrapping it in a document.ready
$(document).keydown(function(e){
if (e.which == 39) {
alert( "right arrow pressed" );
return false;
}
});
And as you can see, it works. My understanding is, since this code doesn't hook up to any elements within the document, but the document itself, there's no need to wrap it in a document.ready handler. Another reason i don't wrap it is because i used to do the same in vanilla javascript the equivalent would be the code below, which also works.
document.onkeydown = function(){
var keyCode = event.keyCode || event.which;
if (keyCode == 39) {
alert( "right arrow pressed" );
return false;
}
}
I've seen numerous posts where people wrap it in a document.ready, is there any downside of not wrapping this code in document.ready ?
Also i think this question stems from my lack of clarity of what happens during this time when the DOM is being constructed, so if someone can explain what happens during the period right before the DOM is ready. To me the document is ready when the html has been parsed and converted into a DOM tree, or is there more to it ?
In summary, here are my questions
When binding event handlers to the document itself, is it
necessary to put that code in a document.ready.
Are there any downsides to not wrapping the code in the document.ready ?
What sequence of events take place when the document is being constructed, right before the document.ready is fired ?
If you are binding to the document itself, you don't need to wait until it is ready. There shouldn't be any downsides to not wrapping it in document.ready in this case.
document.ready gets fired when the DOMReady event is triggered by the browser, or when a specific test is successful for versions of browsers that don't support the DOMReady event.
Additional information. (5/22/12)
Most modern browsers implement the DOMContentLoaded event which fires when all elements defined on the document are ready to be manipulated by javascript. Other browsers either rely on a setTimeout loop that continuously checks the readystate of the document or binds directly to the onreadystatechanged method of the document (taken from jquery core). The document itself is ready to be manipulated before javascript is ever executed, therefore you never need to wait when binding directly to the document.
The only gotcha here is that if the code interacts with elements other than the document, there is a chance that the event could be triggered on the document before those elements exist. It is very unlikely for that to happen, but it can happen. If that is something that can happen with your code, then it makes sense to place it inside of $(document).ready() to prevent that scenario. Your sample doesn't warrant being placed inside of $(document).ready().
The point of $(document).ready is to execute code after the entire document has been parsed.
You only need to use it if you want to use elements that don't exist yet.
(eg, if your script is in the <head>)
If the elements you're using already exist (either because they're global or because your <script> is below them), you don't need it.
The only drawback of not binding an event to the document in a document.ready block would be that it will be possible to fire the event before all the page content has been loaded, which may not be what you want.
This event gets triggered when the DOM hierarchy has been fully
constructed i.e. all assets such as images have been completely
received.
You asked:
When binding event handlers to the document itself, is it necessary to put that code in a document.ready?
Answer: Nope. When using code that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the script in which your code resides or just before document.ready() block.
Are there any downsides to not wrapping the code in the document.ready ?
Answer: No. But when you've to create elements inside your documents by using JavaScript, then should wait for sake until your DOM gets ready. For this, you should put your code inside document.ready() block.
What sequence of events take place when the document is being constructed, right before the document.ready is fired ?
Answer: Before document.ready gets fired, DOMContentLoaded is already triggered by browser.
When using actions to elements or calling them (that will be generated in DOM or don't exist yet) you need to use $(document).ready
In addition to the answers: you can mere use jquery live function (instead of keydown, etc.) to be free of the situation 'DOM elements must be finished'.
So the next must work properly:
$( "#somediv" ).live( 'keydown', function(){ ... } );
In this case jQuery binds the event when it is possible. You don't have a pain to place all bindings in one (ready) function, your bindings can be placed in independent parts of your HTML page or Javascript files.
So, the result answer is: no, you don't need to place your code in document.ready when you use the mentioned function.
Update
In the last versions of jQuery (>= 1.7) use on() function instead of live() because the last one is depricated. So, it's not necessary to place event bindings into ready().
1. When binding event handlers to the document itself, is it necessary to put that code in a document.ready?
No. In fact, the 'on' methods for binding in JQ can delegate at the document so you could use those at any time on any element safely as long as there wasn't a lot of bubbling being stopped at container elements with stopPropagation.
2. Are there any downsides to not wrapping the code in the document.ready?
Only that scripts in the head might try to hit HTML that isn't there yet. The converse is that HTML might be ready and getting events from the user before the doc is. See 'on' methods or google 'event delegation' for having your cake and eating it too where events are concerned (the caveat is libraries that use stopPropagation stupidly). document.ready is mostly just a way to be certain your code is firing when the HTML is ready to be hit. It's not necessary for code that falls at the bottom of the body tag unless (maybe) you're hitting body itself with something.
3. What sequence of events take place when the document is being constructed, right before the document.ready is fired ?
At the point that document ready is fired, all tags have been parsed and the layout dimensions have been established. Images do not need to have fully loaded, and I'm only guessing, but I suspect non-layout impacting CSS may not be in effect yet in some browsers. An element is considered 'ready' when its closing tag has been read and executed on by the HTML parser. JS in script tags must be handled by an interpreter before HTML parsing can continue, which is why we tend to put our code at the bottom of the doc nowadays anyway, for faster perceived loading time.

Load external script dynamic, and access it, so I can trigger its domready function

I am trying to load the Zopim chat client. Normally it is included with a document write action. This causes it to be loaded before the domReady function is triggered, as it needs this to start itself.
I want to load it later, and this works by using prototype (framework determined by Magento) to create a new script element and attaching it to the head. The script is loaded perfectly, but the domReady doesn't fire, so the script is never started.
The script is a nameless class, by this I mean that all its functions are encapsulated in {}
UPDATE: Sorry, I got it wrong, it is as self invoking function, the same syntax as the first answer suggest.
(function C(){
})();
This function call when run sets up listening events for the domReady event under various browsers and then waits. When the domready event fires, it calls a function (that is within the self-invoked function) that starts everything. What I need, is a way to access this function somehow.
END UPDATE
Within that is a function named C.
How can I call this function directly?
Or put another way, how can I start an external javascript file that depends on domready going off, when that event doesn't happen?
Can I load an external javascript file into a variable, so I can name the class?
Can I access the nameless class {} somehow maybe via the script tag?
Is there a way to alter the external file/javascript so I can have it look for another event, one that I can trigger?
About the only solution I can think of at the moment is to create a iframe and load the script in that.
If you want to fire it after loading it asynchronously after the domready is already fired, you can do this:
Make your function C a self invoking function by:
(function C(){
})();
With this approach you would be changing the external script though.
You may trigger the event programmatically, for example:
window.dispatchEvent(new Event('DOMContentLoaded'));
See Creating and triggering events.
But note that this solution can be tricky to make it work correctly, cause when you trigger the event, some event handlers that have registered to the event will trigger a second time. And this causes problems like page not working as expected or an infinite loop (event registering, handler call, event registering, handler call indefinitely).
So you would need a solution to make sure that the different scripts that registered to the DOMContentLoaded event have their handlers only called 1 time exactly.

Categories

Resources