views:

804

answers:

1

I am writing a simple GreaseMonkey script that has a jQuery plugin called hoverIntent embedded in it. (I am embedding it rather than hosting it because it's a very small plugin.)

My problem: after the plugin attaches its event handler to a DOM object, the event triggers an error message that says: "jQuery is not defined."

Is it a scope issue? Here is my entire script:

   if(unsafeWindow.console){
       var GM_log = unsafeWindow.console.log;
    }


    (function($){
            //HoverIntent
            $.fn.hoverIntent=function(f,g){...}; 
            //Removed the plugin code. You can see it in the link at the bottom 
            //of the post.



    //DOM is ready
    //Fetch all the rows with arrows
    $('.arrow')
        .each(function(){
         $(this).hoverIntent(mouseOver,mouseOut);      
        });

    //mouseOver
    function mouseOver(){
        //THIS IS WHERE THE ERROR HAPPENS
        $(this).click();
    }

    //mouseOut
    function mouseOut(){ //nothing here.
    }

    })(unsafeWindow.jQuery);

It works fine when I copy paste it, removing all GM specific tags, and run it from my console. And this is the plugin I am embedding.

+1  A: 

Does the greasemonkey script run before or after onDOMLoaded? You may need to delay the execution of the script until after the jQuery script is sourced by the parent window, and loaded...

Edit per comment:

I don't see the document.ready bit in your code above, although I see your comment about it... However, your comment is a bit too late in the script to be any use... This might explain:

(function($){ /* some code here */ })(unsafeWindow.jQuery)

Regardless of what you put in the the /* some code here */ section, if this line is executed before unsafeWindow.jQuery is defined, you'll still be calling a function on an undefined object...

Reading the GreaseSpot wiki on unsafeWindow, it suggests the alternative approach of:

var script = document.createElement("script");
script.type = "application/javascript";
script.innerHTML = "(function($){
        //HoverIntent
        $.fn.hoverIntent=function(f,g){...}; 
        //Removed the plugin code. You can see it in the link at the bottom 
        //of the post.



    //DOM is ready
    //Fetch all the rows with arrows
    $('.arrow')
        .each(function(){
                $(this).hoverIntent(mouseOver,mouseOut);                
        });

    //mouseOver
    function mouseOver(){
        //THIS IS WHERE THE ERROR HAPPENS
        $(this).click();
    }

    //mouseOut
    function mouseOut(){ //nothing here.
    }

})(jQuery);";

document.body.appendChild(script);

Edit: none of my answers necessarily make sense, though, since you're using the $ object for a few lines before issue presents itself.. :-S weird.

Stobor
Good question. My understanding is userscripts are loaded after the DOM is loaded, but just to be on the safe side I used a document ready in my script as you can see above.
picardo