This quick walkthrough is going to bring you up to speed on how to create your own social bookmarking button. The three prime examples are the famous Digg button, Facebook’s like functionality and the tweetmeme button. For an implementation look slightly above this paragraph or check out mashable’s version on the left of their post.
Our button will be focusing on Fashiolista.com. Fashiolista is a social bookmarking site for fashion, which has seen rapid growth after launching at the next web. This tutorial explains the javascript (client side) aspects of the button. Feedback and improvements on the code would be greatly appreciated. You can find the full 450 lines of js on github.
This is what the end result looks like:
Compact | Medium | Large |
---|---|---|
Love it! |
Love it! |
Love it! |
(If you are working on a shop in the fashion industry have a look at our installation instuctions.)
Step 1 – The markup
Its important to get the client side markup of the button right. Since other sites will be implementing this there is no way you can change it later on. The three major players each have their own way.
Facebook XFBML: Async script with XFBML or Iframe
Digg button: Async script with A elements
Tweetmeme: Normal script
<script type="text/javascript"> //async script, fashiolista.com version (function() { var s = document.createElement('SCRIPT'); var c = document.getElementsByTagName('script')[0]; s.type = 'text/javascript'; s.async = true; s.src = 'http://button.www.fashiolista.com/button/script/'; c.parentNode.insertBefore(s, c); })(); </script> <a class="fashiolista_button fashiolista_compact" href="http://www.fashiolista.com/item_add_oe/">Love it!</a>
For Fashiolista we have chosen an async script approach with A elements. Normally loading a script element is a blocking operation for the browser. Loading the script async ensures faster page load times and a better experience if your site would ever go down. (Note that not all browsers support this option so it is still recommended to include the script tag at the bottom of the page). The function wrapped around the code ensures we don’t pollute the global scope. Furthermore the insertBefore in combination with a script tag technique is used by GA so should work in any scenario.
Step 2 – Creating the buttons, Iframe vs Script
The next step is to convert our A elements into actual buttons. We can choose to replace these A elements by our button’s html (digg, delicious approach) or load an iframe in their place (facebook, tweetmeme). The difference between these two approaches is actually pretty large. For Fashiolista you can see both an iframe and script approach. These are the most important differences I encountered.
Iframe vs Script
- + Popup communication possible
The script approach cannot communicate with popups it creates due to the same origin restrictions. The iframe however can be of the same domain as the popup and freely communicate. This gives a better user experience when for instance logging in. - + Easier to develop
The iframe approach is easier to develop and requires less code. - + Parallel download in IE
IE doesn’t download the count scripts in parallel, but it does do so for the IFRAMEs. Making this approach somewhat faster. - Independent CSS
External sites don’t interfere with your button’s css if you use an iframe technique. The disadvantage is that it makes things likes hovers impossible to integrate with the other site. (For example Fashiolista’s compact button). - Independent
The iframe approach makes it very hard for other sites to game the users like/love action. With a script approach a foreign site can simply call your javascript to fake someone loving the product. This freedom can be abused but also allows for mashups. - - Slower dom load
Creating iframes takes a lot more time for the browser. - - Slower perceived load
The script approach allows you to format the buttons before the data is loaded. Vastly increasing the perceived load speed. - - No shared functionality
Buttons can’t share functionality. So when someone logs in for one button its is not possible to update the others.
The best choice differs for each project. For Fashiolista the more open script approach is currently the default.
Step 3 – Cross site scripting using JSONP
Essential to the bookmarking button is requesting the count for the given url. Cross site policies prevent us from using Ajax so we will do so by creating a script element.
_makeRequest: function (url) { //Simple create script element functionality var s = document.createElement('script'); var b = document.body; s.setAttribute('type', 'text/javascript'); s.setAttribute('async', 'true'); s.setAttribute('src', url); b.appendChild(s); }
The trouble with the script element is that you lack the nice APIs Ajax offers you. We work around this by using an url with a callback paramater, for example callback=button_loaded_3
The server side code then responds with something like this, executing the callback when the script is loaded.
button_loaded_3({"item_id": 26545, "url": "/item/26545/", "loves": 853})
This technique is often referred to as JSONP. We bind the response function to the global button_loaded_3 using the following code:
loadButtonInformation: function (buttonId) { //make a request to the script with the given callback var buttonInstance = this.buttonDict[buttonId]; var buttonUrl = buttonInstance.lookupUrl; var path = '&url=' + encodeURIComponent(buttonUrl); var callbackFunctionName = 'button_loaded_' + buttonId; var scope = this; var callbackFunction = function(data) { //bind the scope and button id scope.buttonLoaded.call(scope, buttonId, data); }; window[callbackFunctionName] = callbackFunction; this.makeRequest(this.countApi + path, callbackFunctionName, true); }
Step 4 – Object oriented design
Since we are loading our code into someone else’s website we should be careful not to use similar variable names. We therefore hide as much code as possible in classes.
var fashiolistaClass = function(){ this.initialize.apply(this, arguments); }; fashiolistaClass.prototype = { // //Base class implementing the fashiolista button // initialize: function () { //load the buttons this.initializeCss(); var fashiolistaButtons = this.findButtons(); this.initializeButtons(fashiolistaButtons); } }
Note that we are not simulating inheritance for these classes. Using them as simple namespaces is more than sufficient in this case.
The code is organized into 3 classes:
- fashiolistaClass
- fashiolistaUtilsClass
- fashiolistaButtonClass
The first one acts as a manager (finding the buttons, instantiating fashiolistaButtonClasses and retrieving counts). Fashiolista button contains the logic for individual buttons and fashiolista utils contains some string parsing and dom load functionality.
Step 5 – Caching requests in the google app engine
To prevent our servers from getting flooded we are routing all traffic through google servers using the google app engine. button.www.fashiolista.com is connected to a google app engine account which forwards and caches requests to fashiolista.com. This setup enables your button to withstand great amounts of traffic without killing your servers. Furthermore it immediately also acts as a cdn for our web requests, speeding up load times for our international visitors. Setting up caching in the google app engine would require another blog post though. Let us know in the comments if you would like to know more about it.
Conclusion
The full client side code can be found here. This blog post covered the most essential parts. Code review and questions are more than welcome. Be sure to let us know in the comments. Furthermore if you are running a webshop in the fashion industry consider implementing the button.
More information
- Server side standards – OExchange
- Installing the fashiolista button (for shops)
- Subscribe to this blog’s rss feed
Improvements/ Request for code review
- The domload technique is rather verbose, does anyone know a better method?
- The popup communication or lack thereof is not ideal for users, is there a better method?
- Script or Iframe what do you prefer?
- Suggestions to make it faster?
10 Utile Resources of Aug 2010 for Web Design and Development | Gadgets World responded on 07 Aug 2010 at 2:03 am #
[...] Creating your own Digg/Facebook/Tweetmeme button [...]
Mellow Morning » Twitter button to pull down the internet? responded on 13 Aug 2010 at 2:39 pm #
[...] Fashiolista.com we have been writing a lot about the various techniques for implementing these type of buttons. Especially important here is the way the javascript is [...]
Øyvind Sean Kinsey responded on 29 Aug 2010 at 4:30 pm #
Why are you using a prototype based approach for a object that is only going to be created once (the fashiolistaClass)?
This will only make your code more complex as you need to access everything through
this
instead of through the scope chain.A proper ’singleton’ should either be formed by using a regular literal object, or through the module pattern combined with an immediately invoked function.
var foo = (function(){
return {
bar: funciton(){..}
};
}());
F. Emi responded on 29 Jan 2012 at 8:03 pm #
I would love to see a blog about caching button requests using the google app engine, a deeper high level info is much appreciated.
Mike responded on 05 Oct 2012 at 2:22 pm #
Very nice article… Thx!
Creating your own Digg/Facebook/Tweetmeme button | Django Daily responded on 03 Dec 2013 at 4:43 am #
[...] Source article: Creating your own Digg/Facebook/Tweetmeme button [...]
mass facebook account creator responded on 22 Apr 2014 at 11:48 am #
Color it appropriately with the help of the “Paint Bucket Tool,” and erase the top line of the box using the “Eraser Tool”
to make it appear as if the chest and arms are connected.
The starting point when wanting to lose fat from a body part, no matter if it’s the belly, the
hips or the chin is to adopt a healthy lifestyle and to start burning more calories than you eat.
Using the same machine day-in, day-out can get a little boring.
To tell some they are not achieving much with the 10,000
steps program and now they must do more intensely could result in
some giving up completely. The first four months are said to be
fine for Pole Dancing.
free twitter account creator responded on 22 Apr 2014 at 9:43 pm #
Three notable standalone applications for Black – Berry users who want a separate built in
mobile instant messenger are Chat on Facebook, Chat for
Facebook, and FChat. Some of these are blocked
in Vietnam, as they’re a pretty common way to get around Firewalls and such,
but there are also still some available. A poll was
taken from average FB users and over half of the people voted
that they only regularly communicate with less than 30% of their ‘facebook friends’.
For many businesses and institutions, having a Facebook page is an effective way
to promote their products and services, and can significantly expand their network.
When you are providing something of try,
service and offer a free gift or competitions which will have more likers as well as
their close friends to participate and join.
vine bot responded on 22 Apr 2014 at 11:36 pm #
Everyone has different limits so take the time to push yourself until you
find yours. The scene immediately before the hunt shows Jack crossing over from civilized
to savage by making a mask, “a thing on its own, behind which Jack hid, (liberating him) from shame and self consciousness” (64).
“Who Else Wants To Shrink Their Sagging Jaw line, Double Chin, Crows Feet and Drooping Lips Without Surgery, Pain or Thousands of Dollars. The good news is that you can raise the good and lower the bad through proper diet and excercise. Bone makeup and loose skin also plays a factor and doesn’t help your cause.
buy trip advisor reviews responded on 23 Apr 2014 at 12:10 am #
You place the base of the tool on your chest bone and your chin on top of the platform.
Sodas and sugared drink would not help because they contain
sugar and will lead to bloating too. Whatever you do, don’t
waste your money on “double chin fixes” such as the Neckline Slimmer.
I walk in different neighborhoods to see different sights and I’ve found myself wanting more.
Lack of exercise can lead to weight gain, as well as to stiffness of joints.