Magical gnomes present: Two-Click Like Button (or +1 Button)
As many of you know, embedding a Facebook "Like" button (or Google "+1" button) on your site requires you to load javascript source and at least one image from their servers. This allows them to obtain data on and track all users of your site - even if they never click the button.
Heise came up with an interesting solution to this problem described here. I was unable to find any code out there to do it, so I wrote my own (it's stupidly simple).
<script type="text/javascript">
<!--
function share_buttons(elem, url) {
// Generate a string containing the HTML to place in the element (for readability)
var html = "<div id=\"fb-root\">\n";
html += "<div class=\"g-plusone\" data-size=\"small\" data-href=\""+url+"\">\n";
html += "</div>\n";
html += "<div class=\"fb-like\" data-href=\""+url+"\" data-send=\"true\" data-layout=\"button_count\" data-width=\"100\" data-show-faces=\"false\" data-font=\"arial\">\n";
html += "</div>\n";
// Replace the specified element's contents with the HTML necessary to display the
// Like/+1 Buttons, *before* loading the SDKs below
document.getElementById(elem).innerHTML = html;
// This is the code provided by facebook to asynchronously load their SDK
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js#xfbml=1';
document.getElementById('fb-root').appendChild(e);
// This is the code provided by Google to asynchronously load their SDK
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
}
-->
</script>
The javascript code above defines a function that takes two arguments - the id of the element that you want to turn into the Like/+1 buttons and the URL that you want those buttons to pass to facebook/google. It then replaces the contents of the specified element with the appropriate HTML needed to generate the buttons, followed by invoking the code provided by facebook and google to asynchronously load their SDKs. The HTML used for the buttons may be customized to obtain different button styles and/or formatting. The important thing to note here is that instead of loading the SDKs on page load, it now happens only when this function is invoked. Regardless, using this function you can create a div like so:
<div id="mybuttons">
<a href="#" onclick='share_buttons("mybuttons", "http://myurl/"); return false;'>
Click here to Share!
</a>
</div>
This creates a div with id "mybuttons", and an anchor that when clicked invokes our share_buttons() function, passing in the element ("mybuttons") and the URL to associate with the buttons. The "return false;" on the end causes the browser to ignore the href, preventing it from scrolling the page to place the anchor at top. It's optional.
Thus you'll end up with something like this...
Replace the text with your own version of greyed out images and it looks even better (see how I did it on purdueband.com). There. Wasn't that easy?! The beauty of this approach is that it does not load anything from facebook/google's servers until the user clicks on the link, invoking the javascript function above. That means google/facebook only get to track your users when they choose to let them.
Multiple Like Buttons on the Same Page
The function above really only works for one element, at least with facebook. So, if you want to have multiple +1/Like buttons we have to do something a little different. The basic idea is that we want to make sure the corresponding button elements are replaced before invoking the javascript functions for each service. Modifying the above function to look like below accomplishes our goal:
<script type="text/javascript">
<!--
function share_buttons() {
var elem_list = [["buttons1", "http://url1/"],
["buttons2", "http://url2/"]];
for (var i = 0; i < elem_list.length; i++) {
// Generate a string containing the HTML to place in the element (for readability)
var html = "<div id=\"fb-root\">\n";
html += "<div class=\"g-plusone\" data-size=\"small\" data-href=\""+elem_list[i][1]+"\">\n";
html += "</div>\n";
html += "<div class=\"fb-like\" data-href=\""+elem_list[i][1]+"\" data-send=\"true\" data-layout=\"button_count\" data-width=\"100\" data-show-faces=\"false\" data-font=\"arial\">\n";
html += "</div>\n";
// Replace the specified element's contents with the HTML necessary to display the
// Like/+1 Buttons, *before* loading the SDKs below
document.getElementById(elem_list[i][0]).innerHTML = html;
}
// This is the code provided by facebook to asynchronously load their SDK
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js#xfbml=1';
document.getElementById('fb-root').appendChild(e);
// This is the code provided by Google to asynchronously load their SDK
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
}
-->
</script>
The above function is similar to the earlier one, but with some notable differences. First, it no longer takes any arguments. Second, the elements and URLs are specified inside the function as a two-dimensional array. Each element of the top array is itself an array containing the name of the HTML element, and the URL its buttons are to correspond to. When invoked, the function loops through each [element, URL] pair and replaces the named HTML element with the appropriate HTML. Once this has been done it loads the corresponding SDK for each service. It is worth pointing out that with this approach, when any Like/+1 button is clicked to be enabled all buttons are enabled at the same time. Anyway, you can now do something like this:
<div id="buttons1">
<a href="#" onclick='share_buttons(); return false;'>
Click here to Share (URL 1)!
</a>
</div>
(More Content)
<div id="buttons2">
<a href="#" onclick='share_buttons(); return false;'>
Click here to Share (URL 2)!
</a>
</div>
With the above code you end up with something like this...
Note that the javascript code further above only needs to be included on the page once. The function may be invoked multiple times, but only needs to be defined a single time. Each time you specify the name of the element to replace and the URL that you want the buttons to correspond to. You can have an arbitrary number of buttons on a page, just make sure they each have their own element identifier. The URLs can be the same or different, too, it all depends on what goal you're trying to accomplish.