The issue is obvious here.
https://www.facebook.com/TabascoUK/app_202624839826809
Using Google Chrome on Windows XP, FB.Canvas.setAutoGrow miscalculates frame size by two pixels. I would report it as a bug, but (1) I didn't manage to reproduce the same behavior on all computers, even though they have the same setup. (2) I've looked at the all.js and it looks Okay – no obvious reason for the error.
I've tried reseting cache, updating browser, etc. But there still is 2px error.
What can be causing it?
I haven't had any issues long time ever since this was posted. But since Chuck Morris seems to be experiencing the same issue, I will share my experience.
First of, I had erroneous assumption that FB.Canvas.setAutoGrow can be called at any time in code. It made sense since it then starts interval, which should detect any DOM changes. Well, it isn't exactly that way.
Anyway, the trick is to load Facebook JS after the DOM is loaded. In my experience this helps to get around all glitches. If you are using jQuery, something like this will do.
$(function(){
window.fbAsyncInit = function()
{
FB.init({/*[..]*/});
FB.Canvas.setAutoGrow(91);
FB.Canvas.scrollTo(0,0);
};
// Load the SDK Asynchronously
(function(d){
var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
ref.parentNode.insertBefore(js, ref);
}(document));
});
Guy,
I really appreciate you following up on this, I was really hoping that your way was going to work in my setup, because it's a lot cleaner than my hack fix, but it's still miscalculating the iframe by 2pixels. Anyways, this is what I did just in-case if anyone runs into this.
window.fbAsyncInit = function() {
FB.init({/*[..]*/});
// Additional initialization code here
FB.Canvas.setAutoGrow(91);
FB.Canvas.scrollTo(0,0);
//FB.Canvas.setAutoGrow is miscalculating the height by 2 pixels in webkit browsers
//so we shorten the content by 2 pixels right away, and a second later if things were a little too slow
window.setTimeout(function() {
$("#footer").css("height", "74px");
}, 250);
window.setTimeout(function() {
$("#footer").css("height", "72px");
}, 1000);
};
I had the same issue and i found i was added
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js"></script>
But in chrome you have to add by the following way
<script type="text/javascript" src="https://connect.facebook.net/en_US/all.js"></script>
Different protocol not work in chrome always use https
or the best way could be
<script type="text/javascript" src="//connect.facebook.net/en_US/all.js"></script>
Related
I have a weird issue with IE and Edge. When I first load a page everything works fine. However when I navigate away from the page by going to a new page on the same website, JavaScript on the new page will show errors. If I now go back to the previous page, it, too will no longer work properly and dev. console will show errors.
If I leave dev. console open while navigating and attempt to set breakpoints where the console mentioned errors occur, they are not triggered.
If I refresh the page (with or without dev. tools open) everything works as expected.
In Chrome and FireFox everything just works.
Here's the page in question:
(Sorry according to guidelines I was forced to submit it as a picture, and I was not allowed to submit a direct link)
The first time you load it, everything should be fine. However, when you say click on "Products" the "Products" page will load with JS errors, and if you go back, the original page will no longer work.
From my attempts to solve the issue it seems that it has to do with the fact that IE no longer executes scripts in the proper order once they are cached. However why it always works in other browsers then?
This is not the answer I was hoping for, but I found a workaround (though the original IE/Edge behavior remains unexplained).
Basically I was dynamically loading scripts like so:
function bmpl_loadScript(scriptName, callback, async, crossorigin, integrity, defer) {
if (!bmpl_arr[scriptName]) {
bmpl_arr[scriptName] = true;
var body = document.getElementsByTagName('body')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptName;
if (async) { script.async = 1; }
if (defer) { script.defer = 1; }
if (integrity) { script.integrity = integrity; }
if (crossorigin) { script.crossOrigin = crossorigin; }
if (callback) { script.onload = callback; }
body.appendChild(script);
}
}
//Load scripts
//bootstrap depends on jquery, and scripts depends on both, hence they are not async and are nested
bmpl_loadScript('//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js', function () {
bmpl_loadScript('//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js', function () {
bmpl_loadScript('/v3/js/scripts.min.js', function () {
//Do final JS loading here
}, false,false,false,true);
}, false, 'anonymous', 'sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS',true);
},false,false,false,true);
So, apparently, unlike Chrome and FireFox, IE/Edge cannot figure out how to run the same routine properly if scripts are already in cache. Therefore I had to go back to the original:
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/v3/js/jquery.fallback.min.js"><\/script>')</script>
<script>bmpl_window_onload();</script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
<script>jQuery.fn.tooltip || document.write('<script src="/v3/js/bootstrap.fallback.min.js"><\/script>')</script>
<script src="/v3/js/scripts.min.js"></script>
This has the added benefit that it allows for fallbacks in case loading from CDN fails.
The reason why I wanted to go with the dynamic loading approach was that Google's Page Speed Insights tool complained about render-blocking JS. However I suppose first priority should be that a site works, and then how fast it loads, considering that the difference between load speeds would probably be minimal.
I still hope someone might shed a light on this IE/Edge behavior, so I am not marking this as an answer.
Is there any way to stop browser add-ons from injecting HTML code?
I am having a website built in angularjs but because of some browser add-ons my route is getting messed up, this is the HTML snippet which is causing some errors in my angularjs:
<script async="" src="http://b.scorecardresearch.com/beacon.js"></script>
<script type="text/javascript" async="" src="http://in1.perfectnavigator.com/d.php?id=57573&eid=&vdisp=0&u=http://www.domain.com/app/#/users&r=http://www.domain.com/site/profile/view/&vdisplayEn=0&vsliderEn=1&bannerAds=1&usadservEx=Oj45JDs7PTUiNg&lrc=0&curatedSite=0"></script>
<script type="text/javascript" src="https://api.jollywallet.com/affiliate/client?dist=111&sub=1&name=Browser%20Extensions"></script>
<script type="text/javascript" src="https://colo.cachefly.net/js/min.inject.js?id=Pz8sOCA"></script>
<script type="text/javascript" src="https://colo.cachefly.net/js/min.inject.js?id=Pz8sOis"></script>
<script type="text/javascript" src="https://colo.cachefly.net/js/min.inject.js?id=Pz8sOiA"></script>
<script type="text/javascript" src="https://colo.cachefly.net/js/min.inject.js?id=Pz8sOSA"></script>
<script type="text/javascript" src="https://colo.cachefly.net/js/min.inject.js?id=Pz8sOSs"></script>
<script type="text/javascript" src="http://www.superfish.com/ws/sf_main.jsp?dlsource=hhnkdzlc&CTID=ssaddon"></script>
<script type="text/javascript" src="http://istatic.datafastguru.info/fo/min/abc1RSQC.js"></script>
<script type="text/javascript" src="http://i.swebdpjs.info/sweb/javascript.js"></script>
<script type="text/javascript" src="http://cond01.etbxml.com/conduit_bundle/web/hotels.php?mamId=G8K2&userId=2222&appId=3333&&ui=1&ns=ETB_Hotels_Widget&partner=smg"></script>
<script type="text/javascript" src="http://cdn.visadd.com/script/14567725590/preload.js"></script>
<script type="text/javascript" src="https://www.tr553.com/InterYield/bindevent.do?e=click&affiliate=harel777&subid=iy&ecpm=0&debug=false&snoozeMinutes=1&adCountIntervalHours=24&maxAdCountsPerInterval=6&endpoint=https%3A%2F%2Fwww.tr553.com"></script>
<script type="text/javascript" src="https://intext.nav-links.com/js/intext.js?afid=wolfpack&subid=def&maxlinks=4&linkcolor=006bff&wiki=1"></script>
<script type="text/javascript" src="http://www.adcash.com/script/java.php?option=rotateur&r=234715"></script>
<script type="text/javascript" id="jw_00" src="//d2cnb4m0nke2lh.cloudfront.net/jollywallet/resources/js/2/affiliate_client.js"></script>
<script src="//jsgnr.datafastguru.info/fl/blm"></script>
<script src="//jsgnr.datafastguru.info/site-classification"></script>
<script src="//jsgnr.datafastguru.info/fl/blm"></script>
<script src="//jsgnr.datafastguru.info/bwl/wl"></script>
<script src="//jsgnr.datafastguru.info/fl/blm"></script>
<script src="//pstatic.datafastguru.info/fo/ecom/lang.js?c=in"></script>
<script src="//pstatic.datafastguru.info/rss/min/fo.min.js?v=2_3_621&b=dynamic&l=right"></script>
<script src="//jsgnr.datafastguru.info/bwl/wl?v=1"></script>
<script src="//jsgnr.datafastguru.info/site-classification"></script>
<script src="//pstatic.datafastguru.info/fo/ecom/lang.js?c=in"></script>
<script src="//jsgnr.datafastguru.info/bwl/wl?v=1"></script>
<script src="//pstatic.datafastguru.info/rb/min/fo.min.js?v=1_1_63"></script>
<script src="//jsgnr.datafastguru.info/bwl/bl"></script>
<script src="//jsgnr.datafastguru.info/bwl/bl?v=1"></script>
<script src="//jsgnr.datafastguru.info/bwl/bl?v=1"></script>
<script type="text/javascript" src="http://www.superfish.com/ws/sf_preloader.jsp?dlsource=hhnkdzlc&CTID=ssaddon&ver=2014.11.25.14.48"></script>
Because of this my URL which was:
www.domain.com/app/#/users
changes to
www.domain.com/users
And I am getting URL related errors: TypeError: Cannot read property 'charAt' of undefined
If I run my website on a browser without any add-ons it works like a charm, but with the above add-ons I am getting errors.
One of our websites user's is facing this issue. Is there any solution to get rid of this?
I looked a bit into intercepting the <script> element injection into the document and prevent loading the code. Disclaimer: I'm no expert on this subject, I just wanted to share what I tried.
At first, I played a bit with MutationObserver, watching the DOM for the creation of a <script> element, and removing it. I came up with the following snippet, added at the very beginning of my HTML page, supposedly to make it load first:
// Create the observer, registering our intercepting callback
var obs = new MutationObserver(function (mutations, obs) {
// Loop over reported mutations
mutations.forEach(function (mutation) {
// childList means nodes have been added. That's the only thing
// we're interested in
if (mutation.type !== 'childList') return;
// Check the added nodes
for (var i=0; i < mutation.addedNodes.length; i++) {
var node = mutation.addedNodes[i];
// Ignore all but SCRIPT elements
if (node.nodeName !== 'SCRIPT') return;
// Remove it
node.parentNode.removeChild(node);
console.log(node.nodeName);
}
});
});
// Start observer
obs.observe(document, {subtree: true, childList: true});
Obviously, this was doomed to fail. If I need to ask a parent element to remove the node, that means it was already added to the DOM and loaded (loading, at least) when I came in to prevent it.
I tried to get there earlier, by overriding document.createElement and returning <div>s instead of <script>s:
document.createElementOriginal = document.createElement;
document.createElement = function (tagName) {
if (tagName.toLowerCase() == 'script') {
console.log('Script interception');
tagName = 'div';
}
return document.createElementOriginal(tagName);
};
But no luck. Looking at the console, no interception was reported. Still too late.
I can only conclude that the extension data is injected before any script on my page is executed, or that the element injection is made in an way independent of the scope I could access in my code.
If you have any suggestion in how I could investigate further, feel free to point me in that direction.
Tell the user to uninstall her add-ons.
OR, if you are truly intent on making your website compatible with this user's array of add-ons (perhaps she is a person of high importance, or she represents many people in an organization in which everyone has these add-ons installed?)...
Designate the line of code at which the error is thrown, and set a breakpoint there. Here are instructions on how to do that in Chrome. Walk your way up the call stack and see if you can find any clues.
If that does not work, try removing some of those scripts. Find out which ones, when removed, solve the issue. Try as many combinations as you are willing to try. Once you have found the culprit script, determine which add-on injected it. Instruct the user to uninstall this add-on, otherwise she will not be able to use your website.
If you want to work around the existence of this script, and you really think it's worth your time (it probably isn't), you can examine the culprit script and try to find out where it's screwing you up. If the script is minified, you can drop it into a deobfuscator like jsnice and scour it. Of course, that will take forever.
In a final bid to get your site to work alongside these add-ons, you could employ various hacks, like wrapping your code in try catch blocks and redirecting on errors, using setTimeout to sidestep errors, etc etc... but really, the easy and obvious solution is to uninstall the add-ons.
You can not disable addons but you can overwrite their functionality. as every javascript code runs under window context, you will get access to addons variable. You just need to do some RnD on those add ons and replace functions before your script loads.
If an addon messes with a website's URL, it's going to break the website. This is not the fault of you, the website developer, but instead the fault of the addon developer (assuming you did not install these "addons" into your website yourself). I feel like there's some sort of miscommunication or something missing if the "addon" is changing your url from a hash to an html5mode pushstate url.
Have the user figure out WHICH addon is causing the bug by one by one having her disabling every addon until the problem goes away. With the information you provided there's absolutely not enough information to go on and I would generally advocate to close this question on that basis.
Once you identify the addon in question, contact their developer asking them why they are changing the URL of random websites.
If the user has an addon that converts www.google.com to www.giggle.com would you not expect the website to "break"? You can't expect google to fix this behavior.
I am displaying a Norton Secure Site Seal in a website and I would like to improve the page speed deferring the loading of the seal script. All the tries I've done failed and I found only this page where this is mentioned (link). Has anyone ever found a good workaround for this?
The deferred code I'm using to run my other scripts looks like this:
<script type="text/javascript">(function(d, s) {
var js, fjs = d.getElementsByTagName(s)[0], load = function(url, id) {
if (d.getElementById(id)) {
return;
}
js = d.createElement(s);
js.src = url;
js.id = id;
fjs.parentNode.insertBefore(js, fjs);
};
load('/js/scriptone.js', 'one');
load('/js/scripttwo.js', 'two');
}(document, 'script'));
</script>
In case you want to have a look to the site seal initialization script:
(I'm using the flash animated seal)
<script type="text/javascript" src="https://trustseal.verisign.com/getseal?host_name=www.undisclosed.com&size=S&use_flash=YES&use_transparent=YES&lang=en"></script>
obviously this will only display correctly in my website and I opted to change the domain name for privacy. I really want to avoid using iframe and if you find relevant I am also loading jQuery
This is killing my business too. Seriously... +2 to +20 seconds per page load. AFYS?
We are switching to hosting the image locally but still linking to the original URL on Norton. Don't do this. Mark this answer down. It's wrong. It's illegal. But it's practical.
https://trustsealinfo.verisign.com/splash?form_file=fdf/splash.fdf&dn=WWW.EXAMPLE.COM&lang=en
UPDATE:
Real solution is to:
Call 877-438-8776, x2, x1
Tell them seal is slow and you have > 10,000 visits per day on your site
They give you media kit to install on your own site
If you look at the code, they are using document.write.
The way I handle this is the following
document.write = function(s) {
document.getElementById('seal-wrapper').innerHTML += s;
}
Of course this is a very simple hack which only works when there's a single script which uses document.write and you know where you want it to be written to.
I've tried to load seal into a iframe and then put it to where it's intended to be. It works for me. With the help of jQuery. Here it is:
Create .js file (I called it hackseal.js)
$(function () {
if (typeof(vs_hack) !== 'undefined') {
return;
}
vs_hack = true;
var iframe = document.createElement('iframe');
var html = '<script src="url_to_verysign" type="text/javascript"></script>';
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.contentWindow.document.open();
iframe.contentWindow.document.write(html);
iframe.contentWindow.document.close();
iframe.onload = function () {
var copy = ['dn', 'lang', 'tpt', 'vrsn_style', 'splash_url', 'seal_url', 'u1', 'u2', 'sopener', 'vrsn_splash', 'ver', 'v_ua', 're', 'v_old_ie', 'v_mact', 'v_mDown', 'v_resized'];
for (var copy_i in copy) {
window[copy[copy_i]] = iframe.contentWindow[copy[copy_i]];
}
$('script#seal-sign').replaceWith(iframe.contentWindow.document.body.innerHTML);
}
});
Change the original code from this
<script type="text/javascript" src="url_to_verysign"></script>
to this
<script id="seal-sign" type="text/javascript" src="url_to_hackseal.js"></script>
I am currently trying to solve an issue so that my facebook application is resized appropriately as it is currently getting cut off before the bottom (Aka you can't scroll to the bottom of my hosted app using the scrollbar.) I have spent a lot of time trying to figure out this issue so any help would be appreciated. Currently my calls to FB.Canvas.setSize({ height: 2000 }); return true however nothing happens and I still cant reach the bottom of my app. I even tried calling on a button click however I still get the same result.
Update: After trying some ideas, I was able to get this to work if I load the Facebook SDK sync into my homepage and call setSize there. However I still am not having any luck when it is loaded Async or Sync into a different page that my canvas navigates to? Just setting the size on my homepage won't work since each page has a different size. Has anyone seen issues like this
Here is the code:
window.fbAsyncInit = function() {
FB.init({
appId : 'XXXXXXXXX', // App ID
cookie : true, // enable cookies to allow the server to access the session
oauth : true, // enable OAuth 2.0
xfbml : false // parse XFBML
});
FB.Canvas.setSize({ width: $(document).width(), height: $(document).height() });
setFriends();
};
(function(d){
var js, id = 'facebook-jssdk'; if (d.getElementById(id)) {return;}
js = d.createElement('script'); js.id = id; js.async = true;
js.src = "//connect.facebook.net/en_US/all.js";
d.getElementsByTagName('head')[0].appendChild(js);
}(document));
$(document).ready(function() {
if (FB && FB.Canvas) {
FB.Canvas.setSize({ width: $(document).width(), height: $(document).height() });
}
});
I just had a similar problem creating an app for a client. I couldn't get the scroll bars to drop. Finally got those to go away and then had the same issue as you with it cutting off the bottom of my app. Here's the the link to the forum post at which I found it. Facebook changed just a bit of code:
Instead of FB.Canvas.setSize() it's now FB.Canvas.setAutoGrow().
Hope it helps.
http://facebook.stackoverflow.com/questions/8559679/remove-horizontal-and-vertical-scrollbar-from-facebook-apps
I usually call setSize without any parameters and that seems to work for me.
window.fbAsyncInit = function() {
FB.Canvas.setSize();
}
What do you have your Canvas height set to in the advanced app settings? I found using "fluid" caused problems and had to set it to "Settable (Default: 800px)".
I really was hoping to explicitly set the size since it doesn't change outside of page load. I didn't want to have the extra perf costs of Facebook checking for resize every time interval and changing the size based off of that.
Good call. This advice from http://www.hyperarts.com/blog/facebook-iframe-apps-getting-rid-of-scrollbars/
To reduce your users CPU cycles, you can also use the setSize function.
FB.Canvas.setSize
Once you’ve loaded the Javascript SDK, you can use FB.Canvas.setSize() to get rid of those scrollbars. Put the following code before the closing HEAD tag on your index page:
<script type="text/javascript">
window.fbAsyncInit = function() {
FB.Canvas.setAutoGrow();
}
// Do things that will sometimes call sizeChangeCallback()
function sizeChangeCallback() {
FB.Canvas.setSize({ width: 520, height: 1400 });
}
</script>
This tells Facebook to resize your iFrame once the page has loaded and again whenever the size of your content changes.
Again, these functions will only work if you set your Canvas Height to “Settable.”
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
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.
I guess you can use some js loader (eg yepnope) that allows you to load js on demand and add a callback.
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).