AngularJS directives for Pinterest buttons and widgets

Jason Watmore
Thursday 23 April 2015

Website Marketing and Social Networking

A big part of online marketing is done through social media and enabling your website visitors to share your content with their friends and followers on Facebook, Twitter, Google+ and Pinterest (to name a few).

Whether you're managing a major law firm marketing website or a local computer repair shop, the difference between success and failure could be something as simple as adding social sharing buttons to your blog.

Sharing across social networks is one of the key indicators that Google (and other search engines) use to measure how much value a page has, if an article or blog post causes a lot of social activity, it's a sign to Google that the page contains interesting high value content and as a result will have it's page rank boosted in Google's search results.

Social Sharing for a Law Firm Marketing AngularJS Website

I had a requirement on a recent project for one of our law firm marketing clients to enable their website visitors to share event photos on Pinterest, that is, enable them to pin photo gallery images from various legal industry events to their Pinterest boards.

For a traditional website this is a pretty straight forward task that can be achieved by using the Pinterest widget builder to generate a html code snippet that you can paste anywhere that you want a Pinterest button. However since this law firm's website is a single page application (SPA) built with AngularJS it behaves a bit differently.

The angular-pinterest directive

The angular-pinterest module contains a set of directives for easily adding any of the Pinterest buttons and widgets to an AngularJS application. The directives also take care of loading the Pinterest SDK script if it hasn't already been added to the page.

Here it is in action:

Usage

Pin It Button

Create a 'pin-it' element with attributes for the different settings of the button, values can be set directly or viewmodel properties can be used that are set in the controller.

<pin-it url="vm.url" description="vm.description" media="vm.media" config="'above'"></pin-it> 

<pin-it url="'https://www.pointblankdevelopment.com.au'" description="'Point Blank Development'" media="''https://www.pointblankdevelopment.com.au/images/social_media.jpg''" config="'beside'" size="'large'" color="'white'"></pin-it> 

<pin-it url="vm.url" description="vm.description" media="vm.media" shape="'round'" size="'large'"></pin-it>

 

Follow Button

Create a 'pin-follow' element with attributes for Pinterest username and fullname.

<pin-follow username="'pointblankdev'" fullname="'Point Blank Development'"></pin-follow>

 

Pin Widget

Create a 'pin-widget' element with an attribute for the pin-id.

<pin-widget pin-id="'421790321327787486'"></pin-widget>

 

Profile Widget

Create a 'pin-profile' element with attributes for Pinterest username, image-width, board-height and board-width.

<pin-profile username="'pointblankdev'" image-width="'200'" board-height="'140'" board-width="'250'"></pin-profile>

 

Board Widget

Create a 'pin-board' element with attributes for Pinterest username, board-name, image-width, board-height and board-width.

<pin-board username="'pointblankdev'" board-name="'point-blank-development'" image-width="'200'" board-height="'140'" board-width="'250'"></pin-board>

 

The AngularJS Pinterest directive code

/**
 * AngularJS directives for Pinterest buttons and widgets
 * @author Jason Watmore <[email protected]> (https://www.pointblankdevelopment.com.au)
 * @version 1.1.0
 */
(function () {
    'use strict';

    angular
        .module('angular-pinterest', [])
        .directive('pinIt', pinIt)
        .directive('pinFollow', pinFollow)
        .directive('pinWidget', pinWidget)
        .directive('pinProfile', pinProfile)
        .directive('pinBoard', pinBoard);

    /* Pin It Button
    ------------------------------*/
    pinIt.$inject = ['$window', '$location'];
    function pinIt($window, $location) {
        return {
            restrict: 'E',
            scope: {
                url: '=',
                description: '=',
                media: '=',
                size: '=',
                shape: '=',
                color: '=',
                config: '='
            },
            link: link 
        };

        function link(scope, element, attrs) {
            if (!$window.parsePins) {
                loadScript('//assets.pinterest.com/js/pinit.js', render, 'parsePins', { 'data-pin-build': 'parsePins' });
            } else {
                render();
            }

            var watchAdded = false;
            function render() {
                if (!scope.description && !watchAdded) {
                    // wait for angular to bind scope data
                    watchAdded = true;
                    var unbindWatch = scope.$watch('description', function (newValue, oldValue) {
                        if (newValue) {
                            render();

                            // unbind the watch, it only needs to run once
                            unbindWatch();
                        }
                    });
                } else {
                    // set the height based on the size and shape, the button 
                    // defaults to small so height only has to be set for large buttons
                    var height = '';
                    if (scope.size === 'large') {
                        if(scope.shape === 'round') {
                            height = 32;
                        } else {
                            height = 28;
                        }
                    }

                    element.html(
                        '<a href="//www.pinterest.com/pin/create/button/' +
                            '?url=' + (scope.url || $location.absUrl()) +
                            '&media=' + scope.media +
                            '&description=' + scope.description + '" ' +
                            'data-pin-do="buttonPin" ' +
                            'data-pin-config="' + (scope.config || '') + '" ' +
                            'data-pin-shape="' + (scope.shape || '') + '" ' + 
                            'data-pin-color="' + scope.color + '" ' +
                            'data-pin-height="' + height + '"></a>'
                    );
                    $window.parsePins(element.parent()[0]);
                }
            }
        }
    }

    /* Follow Button
    ------------------------------*/
    pinFollow.$inject = ['$window'];
    function pinFollow($window) {
        return {
            restrict: 'E',
            scope: {
                username: '=',
                fullname: '='
            },
            link: link
        };

        function link(scope, element, attrs) {
            if (!$window.parsePins) {
                loadPinterestScript(render);
            } else {
                render();
            }

            var watchAdded = false;
            function render() {
                if (!scope.username && !watchAdded) {
                    // wait for angular to bind scope data
                    watchAdded = true;
                    var unbindWatch = scope.$watch('username', function (newValue, oldValue) {
                        if (newValue) {
                            render();

                            // unbind the watch, it only needs to run once
                            unbindWatch();
                        }
                    });
                } else {
                    element.html(
                        '<a data-pin-do="buttonFollow" href="http://www.pinterest.com/' + scope.username + '/">' + scope.fullname + '</a>'
                    );
                    $window.parsePins(element.parent()[0]);
                }
            }
        }
    }


    /* Pin Widget
    ------------------------------*/
    pinWidget.$inject = ['$window'];
    function pinWidget($window) {
        return {
            restrict: 'E',
            scope: {
                pinId: '='
            },
            link: link
        };

        function link(scope, element, attrs) {
            if (!$window.parsePins) {
                loadPinterestScript(render);
            } else {
                render();
            }

            var watchAdded = false;
            function render() {
                if (!scope.username && !watchAdded) {
                    // wait for angular to bind scope data
                    watchAdded = true;
                    var unbindWatch = scope.$watch('pinId', function (newValue, oldValue) {
                        if (newValue) {
                            render();

                            // unbind the watch, it only needs to run once
                            unbindWatch();
                        }
                    });
                } else {
                    element.html(
                        '<a data-pin-do="embedPin" href="http://www.pinterest.com/pin/' + scope.pinId + '/"></a>'
                    );
                    $window.parsePins(element.parent()[0]);
                }
            }
        }
    }

    /* Profile Widget
    ------------------------------*/
    pinProfile.$inject = ['$window'];
    function pinProfile($window) {
        return {
            restrict: 'E',
            scope: {
                username: '=',
                imageWidth: '=',
                boardHeight: '=',
                boardWidth: '='
            },
            link: link
        };

        function link(scope, element, attrs) {
            if (!$window.parsePins) {
                loadPinterestScript(render);
            } else {
                render();
            }

            var watchAdded = false;
            function render() {
                if (!scope.username && !watchAdded) {
                    // wait for angular to bind scope data
                    watchAdded = true;
                    var unbindWatch = scope.$watch('username', function (newValue, oldValue) {
                        if (newValue) {
                            render();

                            // unbind the watch, it only needs to run once
                            unbindWatch();
                        }
                    });
                } else {
                    element.html(
                        '<a data-pin-do="embedUser" href="http://www.pinterest.com/' + scope.username + '/" ' + 
                            'data-pin-scale-width="' + scope.imageWidth + '" ' +
                            'data-pin-scale-height="' + scope.boardHeight + '" ' +
                            'data-pin-board-width="' + scope.boardWidth + '"></a>'
                    );
                    $window.parsePins(element.parent()[0]);
                }
            }
        }
    }

    /* Board Widget
    ------------------------------*/
    pinBoard.$inject = ['$window'];
    function pinBoard($window) {
        return {
            restrict: 'E',
            scope: {
                username: '=',
                boardName: '=',
                imageWidth: '=',
                boardHeight: '=',
                boardWidth: '='
            },
            link: link
        };

        function link(scope, element, attrs) {
            if (!$window.parsePins) {
                loadPinterestScript(render);
            } else {
                render();
            }

            var watchAdded = false;
            function render() {
                if (!scope.username && !watchAdded) {
                    // wait for angular to bind scope data
                    watchAdded = true;
                    var unbindWatch = scope.$watch('username', function (newValue, oldValue) {
                        if (newValue) {
                            render();

                            // unbind the watch, it only needs to run once
                            unbindWatch();
                        }
                    });
                } else {
                    element.html(
                        '<a data-pin-do="embedBoard" href="http://www.pinterest.com/' + scope.username + '/' + scope.boardName + '" ' + 
                            'data-pin-scale-width="' + scope.imageWidth + '" ' +
                            'data-pin-scale-height="' + scope.boardHeight + '" ' +
                            'data-pin-board-width="' + scope.boardWidth + '"></a>'
                    );
                    $window.parsePins(element.parent()[0]);
                }
            }
        }
    }

    //------------------- private functions ------------------- //

    function loadPinterestScript(callback) {
        loadScript('//assets.pinterest.com/js/pinit.js', callback, 'parsePins', { 'data-pin-build': 'parsePins' });
    }

    // function to load non-angular script and (if required) wait for it to run
    function loadScript(url, callback, propToWaitFor, customScriptAttrs) {
        var d = window.document;
        var s = d.querySelector('script[src="' + url + '"]');

        // add script only once to the page
        if (!s) {
            s = d.createElement('script');
            s.async = true;
            s.src = url;

            // wait for property to load if one was specified, otherwise 
            // run callback function when script is loaded
            s.onload = propToWaitFor ? waitForProp : callback;

            // add custom attributes to script tag if specified
            if (customScriptAttrs) {
                angular.forEach(customScriptAttrs, function (value, key) {
                    s[key] = value;
                });
            }

            d.body.appendChild(s);
        } else {
            propToWaitFor ? waitForProp() : callback();
        }

        // wait for script to run and define property on global 
        // scope, then run callback function
        function waitForProp() {
            if (window[propToWaitFor]) {
                callback();
            } else {
                setTimeout(waitForProp, 250);
            }
        }
    }
})();

 

Web Development and Law Firm Marketing Sydney

Contact us to find out how we can help you achieve your law firm marketing or web development goals.