2

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);
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
Isuru
  • 30,617
  • 60
  • 187
  • 303
  • 1
    The `<><![CDATA[ ...` construct won't work in Chrome. Also that jQuery injection is not the best. I'll post a more detailed answer in a few hours if somebody doesn't beat me to it. – Brock Adams Dec 24 '11 at 20:51
  • I kinda guessed it too. Thank you. :) – Isuru Dec 25 '11 at 07:01

1 Answers1

2

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.

Community
  • 1
  • 1
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • It works fine on Chrome now. Not on Firefox though. But its okay. I just made 2 versions. Thank you very much. Merry X'mas and Happy New Year! – Isuru Dec 25 '11 at 12:17
  • btw if this injection method is not best practice, is there a better way to integrate third-party JS libraries to userscripts?? or shall I ask a separate question for this so it might be helpful for others too? – Isuru Dec 26 '11 at 14:03
  • 1
    Happy holidays! If the changes were properly made, then the script should work on both FF and Chrome without needed 2 versions. As for the library load, I prefer to check that the library variable is defined inside a timer. Sometimes a library will not be ready until shortly after the ` – Brock Adams Dec 27 '11 at 00:57
  • I'll check again then. By the way, I'm not quite clear about using timer in JavaScript. Can you please give or direct me to a good example? Thank you. – Isuru Dec 28 '11 at 16:00
  • In response to problem 1: given that one makes use of jQuery by injecting the user script in the page, how _can_ one call GM_* functions from inside the callback function? Or if that's just not possible, how can one make use of both jQuery _and_ GM_* functions in a user script in Chrome? – Jelle Fresen Feb 15 '12 at 13:21
  • @JelleFresen, You don't have to use jQuery by injecting the user script. That's just a convenient hack in most cases. If you want to use GM_ functions from *inside* jQuery driven code, than you cannot inject the jQuery. Open a new question for more information on that. Note that this question and answer already show the use of both jQuery and GM_functions -- just not sharing scope. – Brock Adams Feb 15 '12 at 13:56