jquery lost events - javascript

I would like to know if is there some jquery known behaviour that cause the lost of events handlers (in particular in iframes)?
I've a strange kind of problem.
I've built a webapp composed of two iframe.
First i load content in the first iframe. I add some event event handler using jquery to first iframe content dom.
Everything works.
On user input i load a page in the second iframe. Here too, I add some event handlers using jquery.
Then the strange thing happens: jquery lost the event handlers in the first iframe.
I said 'jquery lost' because if I add an event listener old way, it is still present.

Problem solved.
The problem was caused accessing iframe2.contentWindow or iframe2.contentDocument on the second iframe, when the src of the second iframe was changed (1st time everything worked, from the 2nd onward caused problems) and the second frame was statically coded in the html.
To solve the problem I always remove the second iframe and recreate and append it to dom dynamically via javascript.
The problem occurs only on opera 9.7 embedded for mips (not sure for the exact version)

You might want to use live to bind events. This way when you add new elements with the same selector it will have the event binded to them.
$("p").live("click", function(){
$(this).after("<p>Another paragraph!</p>");
});
Every subsequent p that is added to the page will have the event binded too.

Related

How to find out what event is firing on what element

Is there a tool (or something in firebug) that will tell me what events just fired and more importantly on what elements they were bound to?
I have a number of javascript "includes", some minified, some not. I am experiencing some odd behaviour that I want to turn off, but I cannot find what is causing it.
I have a form showing in a "popup" and when I try to click on one of the input boxes, the "popup" closes, so some event bind somewhere is causing this.
The problem is, I don't know what element has this spurious event bound to it. The problem also occurs if I click anywhere inside the popup (and on the background mask that is covering the rest of the page, but that's acceptable)
I am using firefox, so anything I can type in the console is also an option. The eventys in the multiple javascript files are done in various ways, some through jquery, some using inline attributes (eg. onclick="..."), some using just javascript.
I certainly don't want to go and add some line of code to every possible event in every javascript file.
I have spent over an hour trying to hunt down this dom element and have already eliminated the obvious ones like the divs containing the popup and the body tag.
DOM modifications can be tracked down using the Break On Mutate option within Firebug. It can be activated by clicking the related button ( ) within the HTML panel. Note that the Script panel has to be enabled for this to work.
There are also several other Break On ... features, which may help you finding the right position within the code for a specific event.
Furthermore Firebug 2.0 introduced an Events side panel, which displays all events bound to the element selected within the HTML panel. If libraries like jQuery are used, it will even allow you to investigate the user-defined function wrapped by the library function in case you enable the option Show Wrapped Listeners as described in the answer to a related question.

Can't modify properties of element using jquery .on()

I'm currently trying to write what I feel like should be a very simple chrome addon using jquery. I have a tool I use for work that our IT department has stopped supporting Chrome with, because they have enough on their plate troubleshooting IE. Their solution however, was simply to remove the old onClick functions and added the property disabled="diabled" to all of our buttons.
My simple work around for this is using jquery to remove the disabled properly and append the onClick functionality. I've gotten this to work in a few instances, but the problem I'm running into is with new instances of buttons created using ajax forms.
Here's the code I'm currently trying to work with:
function restoreFunctionality() {
$("#RestoreDefaultsButton").removeProp("disabled").attr("onClick", "OnRestoreDeviceClientClick()");
}
RestoreFunctionality();
Now, this works fine for the initial load, however I'd also like this to work for every button that is to be created in the future. To do this, I added:
$("#RestoreDefaultsButton").on("restoreFunctionality", function(event) {
$("#RestoreDefaultsButton").removeProp("disabled").attr("onClick", "OnRestoreDeviceClientClick()");
});
This, however, does not work for me but also does not provide any sort of console error message telling me why it won't work. I can't seem to find an example of what I want. I see examples in the jquery doc where it can be called by clicking somewhere or something like that, however what I want is for it to just simply "work". Just look for new instances of that button ID and make the changes.
Is on() not the function I want to use in jquery 1.11.1? Am I somehow using this incorrectly? Any guidance to point me in the right direction would help.
Edit for clarification:
I am not trying to edit the same button multiple times in multiple locations. I am trying and willing to create code individually for each button that comes up, given I know the ID of each one.
Here is an example of something I have that is currently working:
The line of code for the button reads:
<input type="button" name="RestoreDefaultsButton" value="Submit"
id="RestoreDefaultsButton" disabled="disabled" class="aspNetDisabled InlineButtonStyle">
The code that I am using and that actually works just fine is now:
$("body").on("click", "#RestoreDefaultsButton", restoreDefaultFunctionality());
and restoreDefaultFunctionality() is simply:
$("#RestoreDefaultsButton").removeProp("disabled").attr("onClick", "OnRestoreDeviceClientClick()");
Again, the above code works just fine. What I seem to have trouble with is that not all of my buttons are present on load, I may click a link that loads a model on the same page/url with a form that has additional buttons. That button might read:
<input type="button" name="OpenToolkitButton" value="Submit" id="OpenToolkitButton" disabled="disabled" class="aspNetDisabled InlineButtonStyle">
Which is almost exactly the same as the original example, it's just been loaded after the script ran for the first time.
What I am looking for is a solution to make all individually specified buttons that I need, when they occur, to have that disabled removed and a specific onclick function added.
It appears that you have several things wrong and you are using .on() incorrectly.
First, ids in your document must be unique. You cannot have multiple DOM elements with the same id. That is both illegal HTML and will not correctly work with selectors. So, if you're trying to detect future "#RestoreDefaultsButton" objects in addition to the one you already have, you will have to change that because you can't have more than one and still have selector code work correctly. Usually, you want to use a class name instead of an id when you want to find multiple objects of the same type.
Second, your use of .on() is simply not correct. .on() allows you to register a callback function that will be called when a certain DOM event is triggered. So, when you do this:
$("#RestoreDefaultsButton").on("restoreFunctionality", fn);
You are asking for jQuery to call your function when the single "#RestoreDefaultsButton" object triggers the "restoreFunctionality" DOM event. Since "restoreFunctionality" is not a built-in DOM event, the only way that could ever trigger is if you triggered the event yourself.
The usual solution to modifying newly created objects that are inserted into the DOM is to go find the code that creates those objects and insert a function call (to call your own function that can find and "patch up" the newly created DOM objects right AFTER the newly created DOM objects have been created.
The newest browser versions allow you to register a callback to be notified when certain types of objects are added to the DOM so you could get notified automatically. These notifications are call MutationObservers (doc here). Unfortunately, those events are only implemented in the latest browsers (IE11) so you generally can't solely rely on them for a general web page.
Your click handler assignment could probably be solved with delegated event handling. In delegated event handling for dynamically created objects, you find a persistent object (that is not dynamically created) that will be in the parent chain of your dynamically created element and you bind the click event handler to that parent. Since click events "bubble" up the parent chain, the click event will be seen by the parent. Using the delegated form of .on() that works like this:
$("static parent selector").on("click", "dynamic element selector", fn);
You can then handle the event without worrying about the timing of when the dynamic element is created/destroyed, etc...
You can read more about delegated event handling in these references:
Does jQuery.on() work for elements that are added after the event handler is created?
jQuery .live() vs .on() method for adding a click event after loading dynamic html
jQuery .on does not work but .live does
Are you triggering the "restoreFunctionality" event after your ajax forms are built?
$("#RestoreDefaultsButton").trigger("restoreFunctionality");
Forces it to be synchronous if you have more to do after the call and before you finish the function
$("#RestoreDefaultsButton").triggerHandler("restoreFunctionality");

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 document reload every time DOM changes via Javascript?

I kind of have a newbie question. I've done some testing, but I didn't get anything solid, so does the whole document reload when DOM is updated?
No, the document is not reloaded when the DOM is updated.
You can test it using this example: http://jsfiddle.net/AATC6/
There is an alert in the load event for the page, and you can click on the link to add an element to the DOM, which does not cause the load event to be triggered.
No it does not. However there is an event for some browsers DOMSubtreeModified which can be used to track changes to the DOM.

a href onclick event is not working if there a rel attribute defined on it

I have a onclick event for a href , but if a define a rel the function is not getting called
<a href="http://somewebsite"
onclick="javascript:someFunction('somevalue');"
name="top"
rel="somevalue">testing </a>
If I remove the rel property the onclick is working just fine.
What's up with that?
I'm not sure this is really an answer, but really more of a debugging diagnostic. Plus, it was getting a bit long for use in the comments section.
There are no JS errors for me in either Chrome 7 or FF 3.6.8
There are no apparent unclosed quotes in the anchor tag
While the rel tag is not directly supported by any modern browser (but rather used by search spiders), the consensus is that it shouldn't affect events. In fact, per some user comments, such #James Kovaks, it works fine in his tests.
From the Chrome JS console, the function trackForGA is visible, and executable without error.
Attaching an event with jQuery, and then clicking, fires the event as expected. This tells us the click event is in fact being fired by the browser.
code:
$('#countrytabs li:first').click(trackForGA); // click overview tab
Suggested next steps:
Try other event types, to see if they are affected as well - such as onmouseover.
Begin removing JavaScript that is not related to this particular event. Specifically, the only JS you want to remain is the trackForGa function and the onclick JS. Even remove externally loaded JS, such as jQuery (you can presumably do this on a local test/dev box)
If the problem persists, remove trackForGa and instead just do an alert() from the onclick event.
If the problem persists, run your site through an HTML validator (http://validator.w3.org/)
If the problem persists after fixing validation problems, begin removing unrelated HTML tags and content. Systematically remove items until the click is firing as expected to identify a potential culprit.
Also, you never need to specify "javascript:" in an onclick. The only thing that can follow is JavaScript.

Categories

Resources