0

I'm trying to put together a userscript (for use in Chrome) and I keep hitting a wall. My first goal is to have Scott Reed's gSearch jQuery plugin working on any page via the script.

Here is the script I have from shoving snippets and examples, I find here and there, together:

The error I'm getting with this is "Uncaught TypeError: Cannot read property 'WebSearch' of undefined".

// ==UserScript==
// @name           Example
// @version        1.2
// @namespace      
// @description    
// @include *
// ==/UserScript==

function addScripts(callback) {
  var script = document.createElement("script");
  script.setAttribute("src", "http://google.com/jsapi");
  script.addEventListener('load', function() {
    var script = document.createElement("script");
    script.textContent = "(" + callback.toString() + ")();";
    document.body.appendChild(script);
  }, false);
  document.body.appendChild(script);

  var script = document.createElement("script");
  script.setAttribute("src", "http://gsearch.scottreeddesign.com/js/jquery.gSearch-1.0-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 LoadGoogle()
    {
        if(typeof google != 'undefined' && google && google.load)
        {
            google.load("search", "1");
        }
        else
        {
            // Retry later...
            setTimeout(LoadGoogle, 30);
        }
    }

LoadGoogle();

function main() {

    $("#div").css("border", ".5em solid black");

    $('head').append('<link rel="stylesheet" href="http://gsearch.scottreeddesign.com/css/gSearch.css" type="text/css" />');

    $('body').append('<div id="search-results"></div>');


$('#div').click(
    function() {

        $("#search-results").gSearch({search_text : 'example search'});

    });
}

// load scripts and execute the main function
addScripts(main);
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • this is GM's example script. where is yours? – RASG Oct 04 '12 at 01:56
  • That's why I said "Here is the script I have from snippets and examples here and there". I suppose I could phrase that differently. Regardless, I can only try to shove snippets together like awkward puzzle pieces for so long... Trust me, I'd love to be able to take the time to learn.. Any sort of help will be greatly appreciated by me and anyone looking to do something similar in the future. – user1519730 Oct 04 '12 at 03:06

1 Answers1

0

Several issues with that code in the question:

  1. It's firing the main callback twice.
  2. It's not loading jQuery, but uses JQ functions.
  3. Use callbacks to chain actions to the when a library has loaded, see the code below.
  4. Don't "Clone and Modify" addScripts. Keep such functions "atomic".
  5. It doesn't use a Google API key -- which is (or at least was) required for the search API.
  6. Google loader and jQuery don't "play nice" in a userscript environment. Hence we use addJS_Node to load jQuery instead of Google loader.
  7. Avoid @include * in general (Also use @match for Chrome userscripts). Target just the site(s) you want the script to run on.
  8. It uses a node with the id div, but no such node is created by the code (nor likely to exist on most web pages).

The following code will work as a Chrome userscript, as a Firefox Greasemonkey script, and on other browsers. Note the extensive use of different callbacks and addJS_Node, required by timing issues and the need to inject code in Chrome:

// ==UserScript==
// @name    _Google Search API and plugin demo
// @match   http://stackoverflow.com/questions/*
// ==/UserScript==

function GM_main () {
    console.log ("Firing GM_main().");

    $("body").prepend ('<button id="gmSrchBtn">Run Google Search</button>')
    $('head').append (
        '<link rel="stylesheet" href="http://gsearch.scottreeddesign.com/css/gSearch.css" type="text/css" />'
    );
    $('body').prepend ('<div id="search-results"></div>');
    $('#gmSrchBtn').click ( function () {
        $("#search-results").gSearch ( {
            search_text: 'example search'
        } );
    } );
}

/*--- Load:
        1) Required/handy callbacks.
        2) Google base API
        3) Google search API
        4) jQuery
        5) The scottreeddesign jQuery plugin
*/

function GM_targetScopeFunctions () {
    window.gSearchApiIsLoaded   = false;

    window.gAPI_LoadedCB        = function () {
        console.log ("Google base API loaded.");
        google.load ("search", "1", {callback: gSearchAPI_LoadedCB} );
    }

    window.gSearchAPI_LoadedCB  = function () {
        console.log ("Google search API loaded.");
        window.gSearchApiIsLoaded   = true;
    }
}

addJS_Node (null, null, GM_targetScopeFunctions);
/*--- IMPORTANT!
    You will most likely need to get and use an API key for any but demo searching.
addJS_Node (null, "http://google.com/jsapi?callback=gAPI_LoadedCB&key=YOUR_API_KEY");
*/
addJS_Node (null, "http://google.com/jsapi?callback=gAPI_LoadedCB");
addJS_Node (
    null,
    "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js",
    null,
    loadG_SrchPlugin
);
addJS_Node (GM_main);   //-- Loads main but does not run yet.

function loadG_SrchPlugin () {
    console.log ("jQuery loaded.");
    addJS_Node (
        null,
        "http://gsearch.scottreeddesign.com/js/jquery.gSearch-1.0-min.js",
        null,
        function () { addJS_Node (null, null, fireMainAfterSearchApiLoaded); }
    );

    function fireMainAfterSearchApiLoaded () {
        var srchLoadedIntrvl    = setInterval (checkForSrchAPI, 444);

        function checkForSrchAPI () {
            console.log ("In checkForSrchAPI().");
            if (gSearchApiIsLoaded) {
                clearInterval (srchLoadedIntrvl);
                GM_main ();
            }
        }
    }
}

function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
    var D                                   = document;
    var scriptNode                          = D.createElement ('script');
    if (runOnLoad) {
        scriptNode.addEventListener ("load", runOnLoad, false);
    }
    scriptNode.type                         = "text/javascript";
    if (text)       scriptNode.textContent  = text;
    if (s_URL)      scriptNode.src          = s_URL;
    if (funcToRun)  scriptNode.textContent  = '(' + funcToRun.toString() + ')()';

    var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
    targ.appendChild (scriptNode);
}
Brock Adams
  • 90,639
  • 22
  • 233
  • 295