3

I don't know if this is the effects of an update panel or what, but I basically have a drop down list that allows a user to select an item as a filter. When the item is selected it should bring back only one item into a grid view. That is this specific filter will at most bring back the record you are looking for. This works fine if the user clicks an "apply" link to apply the filter. Behind the apply link is some server-side code (C# within an ASP.NET Web Forms application).

We had a request by a user with something to the effect of:

"Why do I have to click the apply button if I make a selection in this one drop down filter...it should simply get that one record I am searching for. This helps me because I don't have to click the "Apply" button."

I agreed with him and thought what is the easiest way to do this...I thought: Simple, I will have an on change event handler of the drop down such that when a selection is made I'll trigger a click event. Something to this effect:

        $("#MainContent_ddlCompany").on("change", function() {
            var companyId = $("#MainContent_ddlCompany").val();
            $("#MainContent_hdnCompanyValue").val(companyId);
            $("#<%=ddlCompany.ClientID %>").trigger("chosen:updated");

            if (companyId.length > 0) {
                $(".apply").click();
                $(".apply").removeClass("applyButton");
                $(".apply").addClass("resetButton");
            } else {
                //cleared selection of a company
                $(".apply").removeClass("resetButton");
                $(".apply").addClass("applyButton");
            }
        });

At first this didn't work, and I couldn't tell why, but then after some serious googling I changed this line:

$(".apply").click();

To this:

$('.apply')[0].click();

That worked great...so I decided to test it some more. As I kept selecting one filter value after another I noticed the page started to slow down. In fact by the 6th or 7th time it was pretty unusable. I don't know why it's happening, but I suspect again it has to do with the fact that this linkbutton with the class name .apply is inside an update panel.

But still I thought to myself, it was inside of an update panel before I changed my jQuery code to simulate the click event. So why does the page slow down and drag with this little piece of code? Is calling the event from jQuery code rendering something else in the HTML that could be causing this?

If I change my code back and force the user to click the apply button then we are back to a good normal speed. Why is it if I tell jQuery to simulate clicking the button my page slow down? It's doing the same thing, the simulation of the click of this link button is calling its server-side code method whether the user clicks it or I have jQuery click it.

For now I'm at a loss as to why this is happening because this button is in an update panel in either case, yet when I have jQuery click it via $('.apply')[0].click(); the page slows down after several attempts. Yet when I have the user simply click this button (without the jQuery click event) then it works fine?

What am I missing here?

Community
  • 1
  • 1
JonH
  • 32,732
  • 12
  • 87
  • 145
  • Try trigger(): $('.apply')[0].trigger('click') . – schellingerht Jul 22 '15 at 20:12
  • @HenriS. - Why would that even matter? – JonH Jul 22 '15 at 20:18
  • @HenriS. - changing to what you mentioned `$('.apply')[0].trigger('click');` now does nothing, no event no data `Uncaught TypeError: $(...)[0].trigger is not a function`...my issue not that it doesn't pull back the data I need. My issue is what is happening to the speed of the page. – JonH Jul 22 '15 at 20:19
  • Check your resources in for example firebug. Maybe, the process does'nt stop? You do all actions on all elements with the class apply. That's not efficient. Better use id (#) for an unique element. – schellingerht Jul 22 '15 at 20:25
  • Henri I can easily change to an id in fact I had that earlier. This is not a question about best practices. Can we please focus on the question. – JonH Jul 22 '15 at 20:33
  • I'd check to make sure the on "change" event isn't being added repetitively somewhere. You can put a console log inside the on event to see if it gets called multiple times on a single "change." If this is the case and you absolutely need to set the on event multiple times, use the off method to remove it before defining it again. – Radio Jul 22 '15 at 20:45
  • Rather than triggering a click event, why not move the `$('.apply').click()` function to name function (not anonymous) and run it both inside the click event of `$('.apply')` and the code above? See if that changes anything? – Michael Tallino Jul 22 '15 at 20:49
  • @radio consider the click event portion of the jquery commented out and having the users simply clicking the apply button. This has no impact on the page or performance and the on event is still there. – JonH Jul 22 '15 at 20:50
  • Psalmody I'm not sure I understand what you mean. Remember the apply button has server side code. – JonH Jul 22 '15 at 20:52
  • 1
    I see what you're saying. I wonder if the update panel is somehow causing multiple instances of the apply button to exist on the dom, yet not visible. So clicking a single button manually triggers a single event, where as calling the whole class to click may cause the click to fire on many instances of ".apply". Worth checking the length of $(".apply") I suppose. Hopefully it's 1. Intuition says this is an event stack leak. This is a tricky issue. – Radio Jul 22 '15 at 22:07
  • @radio I like the comment I'll check into this tomorrow morning. This one has been tricky. – JonH Jul 23 '15 at 01:11
  • Solved it...err update panels - see my answer. – JonH Jul 23 '15 at 13:10

1 Answers1

3

Ugh, well, I found my issue. Because I was using updatepanels I had to wrap my jQuery code to include an add_endRequest. That is, you have something to the effect of:

$(document).ready(function() {

     //Some initial event/triggers

     var prm = Sys.WebForms.PageRequestManager.getInstance();
     prm.add_endRequest(function () {
         //Copy of some initial event/triggers
     });
});

Why do I use the endRequest you ask? Well, because updatepanels basically throw away all your events after an asynchronous postback because the HTML at that point (after an update) is rendered again and at that point all events associated with any control inside an update panel are wiped away. At this point of course document.ready() does not run, so I have to resubscribe to these events inside of endRequest. Enter my issue...

I had a huge brain fart where I basically took everything, literally everything inside document ready and copied it into endRequest. In fact, if I remember correctly, I read articles which stated

Whatever you have in document ready simply copy paste into endRequest

That's fine, but you have to be careful here. I was throwing in events that were not wrapped around inside of an updatepanel into endRequest. The result is disastrous...at least for me.

These events would be attached then multiple times..or based on the number of asynchronous postbacks made. In my case, as I was testing I mentioned after the 6th or 7th time performance starts degrading. Well, by that time my controls were being attached that many times to events. For instance, my .apply button along with my dropdownlist were both outside of my updatepanel. But my jQuery code was attaching the change event of my dropdownlist in both document ready and endRequest.

The result is initially it's pretty fast, because it's only in document ready. But as I make asynchronous postbacks these events are being attached every time. For n tests I would have n attached events...in my case the test of 7 yields 7 on change event handlers!

Case in point, do not place any event handlers such as jQuery's on() event for any controls that are NOT inside an update panel. Otherwise you will run into what I ran into which was poor performance as events are happening.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JonH
  • 32,732
  • 12
  • 87
  • 145