Monday, April 1, 2013

Add a PayPal shopping cart and Facebook to your gallery in 10 minutes

Probably the most exciting feature in 3.0 is the template engine that generates the UI from jsRender templates. They are easy to modify and don’t require .NET or C# programming experience. This feature gives you the power and flexibility to mold the gallery experience to fit your website requirements and UI style guidelines.

There is a lot to write on this topic, but let’s start with a demonstration to show how easy it is. We’ll customize a default installation of the 3.0 beta to add these features:

  • Add a Facebook ‘Like’ button for every gallery item.
  • Add the Facebook comment widget to allow discussions for each gallery item.
  • Add PayPal ‘Add to cart’ and ‘View cart’ widgets to let users add gallery items to a shopping cart and manage them.
  • When users are ready to complete their purchase, they use the secure payment process provided by PayPal. PayPal notifies the website owner of the purchase via e-mail and optionally a programmatic callback, who can then take the necessary action (ship items, add user to new role, etc).

We can make all of these changes on the new UI Templates page in the site admin area. Here is what it will look like when we’re done:


You can see these changes in action in the beta site. This tutorial combines Facebook and PayPal integration and applies it to the entire gallery, but in the beta I split them into two child albums: Facebook album and PayPal album

NOTE: Be sure you are using the latest version of the beta. This tutorial requires a version of the beta that was released today (April 1) or later. You can check your own version by looking at the date modified timestamp on GalleryServerPro.Web.dll in the bin directory. It should be April 1, 2013 or later.

Download Gallery Server Pro 3.0 Beta
Download Gallery Server Pro 3.0 Beta (source code)

More info, including install instructions


Facebook ‘Like’

Let’s add a ‘Like’ button at the top of the right pane each time a media item is displayed:


Go to the UI Templates page in the Site admin area and select RightPane in the Gallery item dropdown:


We want to modify the right pane template, but we don’t want to mess with the default one in case we want to revert back to it and to eliminate the possibility of our changes getting overwritten during an upgrade. So click Copy as new, type Facebook & PayPal Integration for the name and click Save:


Before we continue with our new template, we want to deactivate the default one. Select Default from the Name dropdown, click the JavaScript tab, uncheck all the albums, and save.


At this point our new template is being used to render the right pane. Go back to the new template by picking it from the dropdown.

Adding a ‘Like’ button requires some HTML and JavaScript. Facebook provides the code we can use as a starting point, but we need to tweak it a bit. The code is not specific to any Facebook account so you can just copy and paste the text I use here:


<div id="fb-root"></div>
{{if MediaItem != null}}
<iframe src="//{{:App.HostUrl}}{{:App.CurrentPageUrl}}?moid={{:MediaItem.Id}}&amp;width=450&amp;colorscheme=dark&amp;height=80" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:400px; height:27px;display:block;margin:5px 0 0 5px;" allowTransparency="true"></iframe>


(function(d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) return;
    js = d.createElement(s); = id;
    js.src = "//";
    fjs.parentNode.insertBefore(js, fjs);
  }(document, 'script', 'facebook-jssdk'));

$('#{{:Settings.MediaClientId}}').on('next.{{:Settings.ClientId}} previous.{{:Settings.ClientId}}', function() {
if (typeof (FB) != 'undefined') FB.XFBML.parse();

Paste the HTML in at the beginning of the HTML template and paste the JavaScript in at the end of the existing script, then save.



This code differs from the sample Facebook provides in two respects:

Conditional rendering – There will be times when we don’t have a single media item in scope when the right pane is rendered. This happens, for example, when the user drags a select box around several thumbnails. In this situation, the right pane displays a summarized view of all selected items, and since we can’t generate a unique URL to give to Facebook that represents this situation, we don’t want to render the like button. So we wrap the iframe in a jsRender if conditional ({{if …}}…{{/if}}) that checks the client API to see if we have a single media item available. When we do, the contents of the if statement are rendered; otherwise we just skip that chunk of HTML.

Replacement parameters – We need to generate a unique URL to give to Facebook to represent the media item being liked. We construct it from several properties available to us in the client data model:


As the page is being rendered in the browser, jsRender replaces each {{..}} section with the property referenced inside. So what gets generated in the client-side HTML ends up being a real URL:

The JavaScript code does two things:

  1. It dynamically loads the Facebook JavaScript library.
  2. It calls the Facebook parse routine each time the next and previous media event occurs. Without this, the like button would appear when the page first loads, but not as the user navigates between items with the next and previous buttons.

Now navigate to a media object and notice the like button. It works just like you would expect, and if that’s all you wanted to do to your gallery, you are done. But let’s keep the sweetness going.



Facebook Comments

Facebook offers a comment widget that lets you add discussion capability to any website. It includes moderation tools and even lets users log in with providers other than Facebook, such as Yahoo, AOL, and Hotmail. Let’s add the widget under each media item.

On the UI Templates page, select the MediaObject template, create a copy of it named Facebook & PayPal Integration, and save it. Then switch over to the default template, uncheck all the albums associated with it, and save. We’re doing the same thing we did with the right pane template – making a copy and activating it.

Here is the HTML provided by Facebook, tweaked to replace the static URL with a dynamic URL:

<div class="fb-comments" data-href="{{:App.HostUrl}}{{:App.CurrentPageUrl}}?moid={{:MediaItem.Id}}" data-width="470" data-num-posts="10" data-colorscheme="dark"></div>

We’re constructing an URL using replacement parameters the same way we did with the like button. Paste it in at the location shown here and then save.


We didn’t have to add JavaScript this time because the script we added for the like widget also covers us here. If we hadn’t added the like widget, then we would have had to add that script into our template here. Now view a media object and start adding comments:



PayPal Integration

Now let’s add e-commerce to our gallery with the widgets provided by PayPal. Your media items can represent anything you want to sell – photographs, videos, or physical objects like clothing or toys. When your customers finish paying at PayPal, you get an e-mail with details about the purchase, including the title of the media item and its unique ID (this corresponds to the moid query string parameter and the ID column in the media objects table in the database).

Advanced admins can even configure PayPal with a callback URL that can programmatically receive the purchase details and take action without human intervention. One example might be to add the buyer’s account to a role that gives them access to the high resolution version of the images they purchased.

The first step is to set up a PayPal account and use their button wizard to generate the HTML for the ‘Add to cart’ and ‘View cart’ buttons. PayPal has excellent documentation for this process, so I’ll refer you to that. Here is the code PayPal provides for the add to cart button that links to my account:

<form target="paypal" action="" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="JP2UFSSRLBSM8">
<input type="image" src="" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="" width="1" height="1">

We need to make a few modifications to it before we can use it in our template:

<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="JP2UFSSRLBSM8">
<input type="hidden" name="item_name" value="Photograph - {{:MediaItem.Title}} (Item # {{:MediaItem.Id}})">
<input id='{{:Settings.ClientId}}_addToCart' type="image" src="" border="0" name="addToCart" alt="PayPal - The safer, easier way to pay online!" style="padding:5px;">
<span style='display:inline-block;vertical-align:top;margin-top:10px;'>$1.00</span>
<img alt="" border="0" src="" width="1" height="1">

Remove the form – ASP.NET renders all page content inside a form, and we can’t nest forms, so we remove the beginning and ending form elements.

Add item_name – We add a hidden input tag named item_name that holds the description of the item and it’s ID. This is picked up by PayPal to describe the purchased item in the invoice.

Add ID to button – We add a unique ID to the button (the input tag of type image). We do this so we can get a reference to it in JavaScript – more on that below. The ID includes the ClientId property to ensure it is unique even if multiple instances of a gallery are on a single page. That is not common but better safe than sorry, right?

Add the price – We add a span tag with the price. This is just for display purposes. The real price is stored on the PayPal server and cannot be overridden for security reasons. If you need different prices on your items, you can generate additional button templates at PayPal or use the PayPal API.

Paste the code into the HTML area of the right pane template named Facebook & PayPal Integration. We can add it right next to the Facebook code we added earlier:


We also need to construct a bit of JavaScript:

var bindAddToCartButton = function() {
$('#{{:Settings.ClientId}}_addToCart').click(function() {
  var f = $('form')[0];
  f.action = '';
  return false;

$('#{{:Settings.MediaClientId}}').on('next.{{:Settings.ClientId}} previous.{{:Settings.ClientId}}', function() {


This script does the following:

  1. Adds an event handler to the click event of the add to cart button to submit the form to PayPal.
  2. Binds this event handler when the page loads and also when the user clicks the next/previous buttons.

Paste this script in after the Facebook code, like this:


Save it and take a look:


When you click the button you are redirected to PayPal where you can see your cart:


Click the Continue Shopping button to return to the gallery, where you can add other items. At this point you can check out and complete your purchase anytime you add an item, but it would be convenient to add a view cart button to the top of the page. Let’s do that next. The HTML PayPal provides for viewing a cart looks like this:

<form target="paypal" action="" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value="…encrypted text removed…">
<input type="image" src="" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="" width="1" height="1">

We’ll include some of the same modifications we did to the add to cart button – remove the outer <form> tag and add an ID to the image button:

<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value="…encrypted text removed…">
<input id="{{:Settings.ClientId}}_viewCart" type="image" src="" border="0" name="btnPayPal" alt="PayPal - The safer, easier way to pay online!" style='float:right;margin-top:5px'>
<img alt="" border="0" src="" width="1" height="1">

Create a copy of the header template, call it Facebook & PayPal Integration, and deactivate the default one (just like with the media object and right pane templates). Then paste the HTML into the HTML template at the point where you want the view cart button to appear. In this example I’m putting it just before the {{if Settings.ShowLogin}} line:


We need to wire up some script to submit the form when clicked, just like we did with the add to cart button. It can be a little simpler than that code, though, because we don’t need to bind it to next/previous events. That’s because the header is generated once when the page loads, while the right pane gets regenerated on each next/previous event. Here is the code::

$('#{{:Settings.ClientId}}_viewCart').click(function() {
var f = $('form')[0];
f.action = '';
return false;

Select the JavaScript tab and add the script.


Save your changes and notice the view cart button at the top right:



We’ve integrated Facebook and PayPal into the gallery by doing nothing more than editing a few of the templates. Here is the final result:


This is just one example of the power of the new UI templates feature. Future posts will dig into the client data model and some of the other new features. Have fun!

No comments: