views:

424

answers:

2

Once again I want to load a page which contains its own script into a div using $("divid").load(...). The problem I face is related to events. Let's say we trigger("monkey") from the parent page and on the loaded page we bind("monkey") and just do an alert("monkey bound"). If the same load method is called multiple times, the bind is called multiple times. Now I could just unbind it before I bind it, or check the number of handlers before the bind and then not bind it to prevent this. Neither option is scalable as what if I later want to bind to that trigger in another "sub page" (a page loaded into a div).

What I ideally want to do then is check if the handler I am about to add already exists, but I still WANT to use anonymous handlers... (asking a bit much with that last request I think). Currently I have a workaround by using pre-defined/named methods and then checking this before the bind.

// Found this on StackOverflow
function getFunctionName(fn)
{
 var rgx = /^function\s+([^\(\s]+)/
 var matches = rgx.exec(fn.toString());
 return matches ? matches[1] : "(anonymous)"
}

function HandlerExists(triggerName, handlerName) {
        exists = false;
        if ($(document).data('events') !== undefined) {
            var event = $(document).data('events')[triggerName];
            if(event !== undefined)
            {
                $.each(event, function(i, handler) {
                    alert(handlerName);
                    if (getFunctionName(handler) == handlerName) {
                        exists = true;
                    }
                });
            }
        }
        return exists;
    }

This is a pretty crude way of going about it I feel, but appears to work. I just do the following before the bind as follows:

if (!HandlerExists("test", "theMethod")) {
    $(document).bind("test", theMethod);
}

Does anyone have a more elegant solution? for instance, is there any way to check a particular script is loaded? so I could use getScript() to load the js from the child page on first load, and then simply not load it on subsequent loads (and just fire a trigger which would be handled by he preexisting js)..

+1  A: 

This isn't a full answer, but I quickly found how to fix all my code with minimal changes. In my "base" js class (this is an object which is used on every page for standard button hookups by class name etc) I added the following method which does the check for dupe handlers:

BindOnce: function(triggerName, fn) {
    function handlerExists(triggerName, theHandler) {
        function getFunctionName(fn) {
            var rgx = /^function\s+([^\(\s]+)/
            var matches = rgx.exec(fn.toString());
            return matches ? matches[1] : "(anonymous)"
        }
        exists = false;
        var handlerName = getFunctionName(theHandler);
        if ($(document).data('events') !== undefined) {
            var event = $(document).data('events')[triggerName];
            if (event !== undefined) {
                $.each(event, function(i, handler) {
                    if (getFunctionName(handler) == handlerName) {
                        exists = true;
                    }
                });
            }
        }
        return exists;
    }
    if (!handlerExists(triggerName, fn)) {
        $(document).bind(triggerName, fn);
    }
},

Then I just invoke it instead of the bind method!

$.mystuff.BindOnce("TheTrigger", OnTriggered)

Note that you can't use anon methods here as they would just be called 1, 2, 3 etc and the only way to check for dupes would be with a toString() on the method, which would be pretty slow in a complex application

Mr AH
+2  A: 

Ummm how about using one()? http://api.jquery.com/one/

Or am i completely misunderstanding you?

prodigitalson
It crossed my mind too, but `one` will only happen once per each bound element and handler injected into the page, and I'm pretty sure those handlers should *stay* bound while said elements are in view.
karim79
I was not aware of this method! very useful. Though it wont be useful for many examples in my project. The js is already loaded (and big) and so loading and unbinding it every time may cause further memory issues. Also as karim79 suggests many of the handlers do need to stay bound. Thanks for pointing me in this direction though, I'm gonna try using that for the on sub form loaded handlers and see if we suffer leakage.
Mr AH