How to load Google's Custom-search-engine(CSE)

2019-01-25 23:12发布

问题:

I am using Google Custom Search Engine with their new auto-completion feature. I want this whole javascript to be loaded AFTER the page itself is loaded. The original Google code is this:

<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
  google.load('search', '1');
  google.setOnLoadCallback(function() {
    google.search.CustomSearchControl.attachAutoCompletion(
      'some-long-unique-id',
      document.getElementById('q'),
      'cse-search-box');
  });
</script>
<script type="text/javascript" src="http://www.google.com/cse/brand?form=cse-search-box&lang=cs"></script>

I have transformed this code using tutorial about JS dynamic loading to this code:

(function() {
  var goog = document.createElement('script'); goog.type = 'text/javascript';
  goog.src = 'http://www.google.com/jsapi';
  var cse = document.createElement('script'); cse.type = 'text/javascript';
  cse.src = 'http://www.google.com/cse/brand?form=cse-search-box&lang=cs';
  goog.onload = function() {
    google.load('search', '1');
    google.setOnLoadCallback(function() {
      google.search.CustomSearchControl.attachAutoCompletion(
        'some-long-unique-id',
        document.getElementById('q'),
        'cse-search-box');
    });
  };
  var s = document.getElementsByTagName('script')[0];
  s.parentNode.insertBefore(cse, s);
  s.parentNode.insertBefore(goog, s);
})();

Well, even though I think my solution should work(the same way has Google changed their Analytics on-demand asynchronous code), it doesn't. The page loads fine and as soon as CSE loads, the page goes blank. Something clears the DOM, I suppose its some kind of "Google thing" ? Can someone bring some light on this problem and possibly a working solution ?

Thanks

回答1:

OK, so by checking Google Loader Developer's Guide and by lots of trying-and-testing I've figured how to change my code so it works as I expected in my question:

(function() {
  var goog = document.createElement('script'); goog.type = 'text/javascript';
  goog.src = 'http://www.google.com/jsapi';
  goog.onload = function() {
    google.load('search', '1', {"callback": function() {}});
    google.setOnLoadCallback(function() {
      google.search.CustomSearchControl.attachAutoCompletion(
        'some-long-unique-id',
        document.getElementById('q'),
        'cse-search-box');
    });
  };
  var cse = document.createElement('script'); cse.type = 'text/javascript';
  cse.src = 'http://www.google.com/cse/brand?form=cse-search-box&lang=cs';
  var s = document.getElementsByTagName('script')[0]; 
  s.parentNode.insertBefore(cse, s);
  s.parentNode.insertBefore(goog, s);    
})()

The main thing is this line:

google.load('search', '1', {"callback": function() {}});

If you don't specify callback (at least empty function as I do), then the whole page goes blank, when Google's CSE loads. I have no idea why, but it works fine now with this dummy callback function.

Hope it helps someone with the same problem.



回答2:

I guess you can use some js loader (eg yepnope) that allows you to load js on demand and add a callback.



回答3:

I don't fully-understand what you're trying to achieve. You've asked for someone to suggest how to 'correct' your code, but you haven't given any context, or what you actually want the end-result to be.

Also, the updates you've provided with the function()s you've written- it's not clear how these are being called. In the when the document readyState is complete?

Firstly, I'd suggest using jQuery to wrap up the JavaScript stuff. Yes, Google provide onload events and other helpers for their API, but jQuery will apply to any Javscript, there's no point in using two Javascript frameworks where you don't have to.

The jQuery might be like this:

<script type="text/javascript" language="javascript" src="/js/jquery/jquery-1.4.2.min.js"></script>
<script type="text/javascript" language="javascript">
    // Use the jQuery document load functionality.
    $(document).ready(function ()
    {
        // Load the Google API asynchronously.  The callback 'GoogleApiLoaded' will be called when the script is fully-loaded.
        $.getScript("http://www.google.com/jsapi?key=yourkey", GoogleApiLoaded);    
        // Load other scripts, do other init code here (non-Google-dependent).
    });

    function GoogleApiLoaded()
    {
        // Google-related init here.
        // Load the custom search API.
        // (Could make the callback an in-line function).
        $.getScript("http://www.google.com/cse/brand?form=cse-search-box&lang=cs", CustomSearchApiLoaded);
    }

    function CustomSearchApiLoaded()
    {
        google.load('search', '1', LoadCustomSearchControl);
    }

    function LoadCustomSearchControl()
    {
        google.search.CustomSearchControl.attachAutoCompletion('some-long-unique-id', document.getElementById('q'), 'cse-search-box');
    }
</script>

It might be helpful to break the code apart into different functions, in order to track-down more easily where the problem is. That you have to put in an optional callback on the 'google.load()' function is strange- it may be a bug in the Google code, there are some floating around.

I've used google.load('search', '1', LoadCustomSearchControl), rather than the google.setOnLoadCallback, because as far as I can see they should do the same thing, and using a callback on load() is neater, in my view.

I'd strongly advise you use jQuery (or any JavaScript framework), as it makes life a lot easier.

I'd be interested to see whether what I've suggested works, and if not where it goes wrong. (Make sure to add-in your own JSAPI key).