Search code examples
javascriptgoogle-chromegreasemonkeyuserscripts

Getting jQuery and GM_addStyle to work in a Chrome userscript based off of a working Greasemonkey script


I wrote a simple Greasemonkey script that enlarges thumbnail pictures in a flyover popup. It uses a lot of jQuery in it. It works just fine on Firefox. But not on Chrome since it doesn't support @require.

I came across this solution for this matter. But the script didn't work on Chrome even after I integrated it with the get-around code. I just put all my script code inside the solution code's main function.

Is it wrong? If anyone can point out where is the problem, and what I can do to get it right, it'll be very much appreciated.

function addJQuery(callback) {
  var script = document.createElement("script");
  script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
  script.addEventListener('load', function() {
    var script = document.createElement("script");
    script.textContent = "(" + callback.toString() + ")();";
    document.body.appendChild(script);
  }, false);
  document.body.appendChild(script);
}

function main() 
{
  $("body").append ('<div id="idLargePicturePopupWindow"><img></div>');

$('#idLargePicturePopupWindow').bind 
(
    "mouseenter mouseleave",
    {bInPopup: true},
    myImageHover
);

$('#profPhotos .profPhotoLink > img').bind 
(
    "mouseenter mouseleave",
    {bInPopup: false},
    myImageHover
);

function myImageHover (zEvent) 
{
    if (zEvent.type == 'mouseenter') 
    {

        if ( ! zEvent.data.bInPopup) 
        {

            var imgurl = this.src.toString();
            var bigimg = imgurl.replace(/\/thumbs\/[0-9x]+\//i, "/photos/");

            $("#idLargePicturePopupWindow img").attr ('src', bigimg);
        }

        $("#idLargePicturePopupWindow").show();
    }
    else 
    {
        $("#idLargePicturePopupWindow").hide();
    }
}

GM_addStyle ( (<><![CDATA[
    #idLargePicturePopupWindow 
    {
        position:               absolute;
        background:             white;
        border:                 none;
        margin:                 1ex;
        opacity:                1.0;
        z-index:                1222;
        min-height:             100px;
        min-width:              200px;
        padding:                0;
        display:                none;
        top:                    2em;
        left:                   50em;
    }
    #idLargePicturePopupWindow img 
    {
        margin:                 0;
        margin-bottom:          -4px;
        padding:                0;
    }
]]></>).toString () );
}

addJQuery(main);

Solution

  • Two main problems and 1 possible problem:

    1) Do not wrap GM_addStyle() inside the main() function. GM_addStyle() only works in script scope, it will not work injected to the target page (which is what that main() and addJQuery() business does).

    2) The current code uses E4X to make a multiline string to send to GM_addStyle(), but Chrome doesn't support E4X.

    Alas, the multiline string hack that Chrome does support (for now) does not work in Firefox.

    That means it's slightly harder to code realistic styles with GM_addStyle() if you wish to support both browsers. Use the multiline escape character (\) like so:

    GM_addStyle ( "                                 \
        #idLargePicturePopupWindow  {               \
            position:               absolute;       \
            background:             white;          \
            border:                 none;           \
            margin:                 1ex;            \
            opacity:                1.0;            \
            z-index:                1222;           \
            min-height:             100px;          \
            min-width:              200px;          \
            padding:                0;              \
            display:                none;           \
            top:                    2em;            \
            left:                   50em;           \
        }                                           \
        #idLargePicturePopupWindow img  {           \
            margin:                 0;              \
            margin-bottom:          -4px;           \
            padding:                0;              \
        }                                           \
    " );
    

    ¿3?) That particular version of addJQuery() may not always work (race condition). Let me know if it doesn't.