1

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.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
Eric
  • 2,201
  • 5
  • 29
  • 35
  • Like I said in my other comment, you won't get a click event of any kind (direct or delegated) if the object is disabled. You will need to run some other code AFTER the dynamic content loads in order to remove the disabled property. Then, the delegated event handling will work for the click event. – jfriend00 Jun 01 '14 at 00:31
  • In addition, remove the parens on `restoreDefaultFunctionality()` in this: `$("body").on("click", "#RestoreDefaultsButton", restoreDefaultFunctionality());`. Using parens after a function name means to call it NOW. It should be `$("body").on("click", "#RestoreDefaultsButton", restoreDefaultFunctionality);`. – jfriend00 Jun 01 '14 at 00:32
  • Fair enough. I will try and find some other way to access those form buttons then, thanks for the help. – Eric Jun 01 '14 at 00:39

2 Answers2

1

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

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thank you very much for the descriptive and well written comment. I probably could have worded things better. I am not trying to perform an action on buttons with the same ID, but rather multiple buttons, using the same method. Some buttons are just there when the page loads, others only available when I click a link and it opens a form in a modal window. – Eric Jun 01 '14 at 00:07
  • That said, I did try your solution. While this bubble up effect works great for buttons on the page when it loads, I can't seem to copy the code, change the ID to a button that's on one of the dynamically loaded forms and get that one to work. – Eric Jun 01 '14 at 00:07
  • @Eric - the concept of delegated event handlers for dynamic elements works just fine if implemented correctly so there must be some error in your implementation. We can only help you with that implementation if you show both the HTML and the code that you're trying (by editing it into your question). – jfriend00 Jun 01 '14 at 00:11
  • For example, I know there is a button with an ID "#RequestToolkit". That doesn't come up unless I click click a link that opens a form in a modal window. In that modal window, the button has the disabled property and is missing an onclick function. I want to be able to target THAT button and put the appropriate properties on it. Which, using `$("body").on("click", "#RequestToolkit", restoreToolkitFunctionality);` does not work with – Eric Jun 01 '14 at 00:12
  • @Eric - If the button is disabled, it won't process the click event at all. You can't solve the disabled issue with delegated event handling. You will have to solve that issue separately. – jfriend00 Jun 01 '14 at 00:13
  • I have modified my original post if you would please take the time to read it. I am actually able to remove the disable on the button just fine with the original code. I assumed with the delegated code, if I clicked anywhere, I could trigger a list of functions to restore functionality if needed. IF this won't work, is there any sort of listener that could be implemented to wait until certain buttons are loaded? Even if that button appeared, I closed the modal and had to open it again, it would apply the changes again? – Eric Jun 01 '14 at 00:28
  • @Eric - comments added to your question. – jfriend00 Jun 01 '14 at 00:34
0

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");

  • I think that's my problem. I'm not sure how to trigger the restoreFunctionality function after the ajax forms are built. I assumed adding on() in some way would do so, but it doesn't seem to. I tried using trigger as well just to see if it would work, but doesn't seem to apply the changes. – Eric May 31 '14 at 23:28
  • change $("#RestoreDefaultsButton").on("restoreFunctionality"... to $("#RestoreDefaultsButton").bind("restoreFunctionality"... THEN from the ajax return $("#RestoreDefaultsButton").trigger("restoreFunctionality"); – Richard Taylor-Kenny May 31 '14 at 23:30
  • Keep in mind that unfortunately, I have no control over the output of the ajax or how it's calling it's functions. I'm trying to modify an existing script through a chrome extension. – Eric May 31 '14 at 23:34
  • if the resut of the ajax call triggers an event on you dom then you can hook into that event to trigger "restorFunctionality" – Richard Taylor-Kenny May 31 '14 at 23:40