Skip to content

Instantly share code, notes, and snippets.

@eoneill
Created November 16, 2011 20:31
Show Gist options
  • Save eoneill/1371276 to your computer and use it in GitHub Desktop.
Save eoneill/1371276 to your computer and use it in GitHub Desktop.
i18nShare
IN.$extensions('i18nShare', function() {
/**
* A widget for sharing the current page with your professional network
*/
(function() { // anon function
/**
* Puts a sharing tag onto the page
* @class IN.Tags.Share
* @constructor
* @param el {HTMLElement} the container element
* @param attributes {Object} the collection of attributes from the JS tag
*/
Sslac.Class("IN.Tags.i18nShare").Extends("IN.Tags.Share")
.Constructor(function(el, attributes) {
this.Parent(el, attributes);
this.buttonTitle = attributes.buttonTitle || "Share";
})
/**
* Creates the share button and attach all its infrastructure
* @method makeButton
*/
.Method("makeButton", function() {
var calloutOptions = {
state: (this.position == "right" && !this.showZero) ? "hidden" : null,
position: this.position,
alwaysShow: this.showZero,
content: 0
},
calloutPlacement = (this.position == "right") ? "after" : "before";
function clickHandler() {
var i, len;
if (!this.clickedOnce) {
this.clickedOnce = true;
this.increaseCount();
}
if (this.winObj) {
this.successCallbacks.pop();
this.winObj.remove();
this.winObj = null;
}
this.winObj = IN.UI.Share()
.params({
url: this.url
});
var thisModule = this;
function shareSuccess() {
if(thisModule.useCounter) {
if (!head) {
head = document.getElementsByTagName("head")[0];
}
var sc = document.createElement("script");
sc.type = "text/javascript";
sc.src = getShareCountUrl(thisModule.url)+'&cc='+(thisModule.count);
head.appendChild(sc);
}
}
this.successCallbacks.push(shareSuccess);
for (i = 0, len = this.successCallbacks.length; i < len; i++) {
this.winObj.success(this.successCallbacks[i]);
}
for (i = 0, len = this.errorCallbacks.length; i < len; i++) {
this.winObj.error(this.errorCallbacks[i]);
}
this.winObj.place();
}
var buttonTitle = this.buttonTitle;
this.button = new IN.Objects.Button({
title: buttonTitle
});
this.button.place(this.el());
IN.Event.on(this.button, 'click', clickHandler, this);
if (this.useCounter) {
addShareItem(this.url, this);
this.counter = new IN.Objects.Callout(calloutOptions);
this.counter.place(calloutPlacement, this.button.el());
if (this.position == "top" || this.position == "talltop") {
var br = document.createElement("br");
this.button.el().parentNode.insertBefore(br, this.button.el());
}
IN.Event.on(this.button, 'mouseOver', function() { this.counter.setState('mouseOver'); }, this);
IN.Event.on(this.button, 'mouseOut', function() { this.counter.setState('mouseOut'); }, this);
IN.Event.on(this.button, 'mouseDown', function() { this.counter.setState('mouseDown'); }, this);
IN.Event.on(this.button, 'click', function() { this.counter.setState('click'); }, this);
IN.Event.on(this.counter, 'mouseOver', function() { this.button.setState('mouseOver'); }, this);
IN.Event.on(this.counter, 'mouseOut', function() { this.button.setState('mouseOut'); }, this);
IN.Event.on(this.counter, 'mouseDown', function() { this.button.setState('mouseDown'); }, this);
IN.Event.on(this.counter, 'click', function() { this.button.setState('click'); }, this);
IN.Event.on(this.counter, 'click', clickHandler, this);
}
})
/**
* Sets the count for this share object
* @method setCount
* @param count {Integer} the count for this share object
*/
.Method("setCount", function(count) {
if (this.counter && (count != "" || this.position == "top" || this.position == "talltop")) {
count = count + ""; // normalize to string
if (!count.match(/^[\d]+$/)) {
return;
}
// back to number
count = count * 1;
this.count = count;
this.counter.setState("visible");
// format and show
this.counter.setContent(formatNumber(count));
}
})
/**
* increases the count by a specified amount
* @method increaseCount
* @param count {Integer} an amount to increase by defaults to 1
*/
.Method("increaseCount", function(count) {
count = count || 1;
this.setCount(this.count + count);
})
/**
* A static method to get the count for a generic callback
* @method getCount
* @param url {String} the url to get a count for
* @param callback {Function} a callback function
* @param scope {Object} an optional object for the callback's scope
*/
.Static("getCount", function(url, callback, scope) {
addGenericCountCallback(url, callback, scope);
})
/**
* A static property that all share objects use. It receives a JSONP call
* @method handleCount
* @param data {Object} the Object with share data
*/
.Static("handleCount", function(data) {
handleCount(data);
});
var head,
registry = {};
/**
* creates the share counter URL from the IN.ENV variable
*/
function getShareCountUrl(url) {
return IN.ENV.widget.share_counter_url+"?url="+encodeURIComponent(url);
}
/**
* Adds a share item to the registry, recording the IN tag with it
* it then dispatches a JSONP item for the counting URL
*/
function addShareItem(url, tag) {
addGenericCountCallback(url, tag.setCount, tag);
}
function addGenericCountCallback(url, callback, scope) {
if (!head) {
head = document.getElementsByTagName("head")[0];
}
// add tag to registry under URL
if (!registry[url]) {
registry[url] = [];
}
registry[url].push({
callback: callback || function(){},
scope: scope || window
});
var sc = document.createElement("script");
sc.type = "text/javascript";
sc.src = getShareCountUrl(url);
head.appendChild(sc);
}
/**
* Called from the static IN.Tags.Share.handleCount, this maps the count
* payload back to the counter objects. This also cleans up any outstanding
* JSONP urls for that data item
*/
function handleCount(data) {
if (!head) {
head = document.getElementsByTagName("head")[0];
}
// protections against broken responses
data = data || {};
if ((typeof data.url === $_CONSTANTS.types.undef) || (typeof data.count === $_CONSTANTS.types.undef)) {
return;
}
var url = data.url,
count = data.count,
nodes = head.getElementsByTagName("script"),
node,
exec,
removeNodes = [],
i, len;
// find all script tags for this url
for (i = 0, len = nodes.length; i < len; i++) {
node = nodes[i];
if (node.src == getShareCountUrl(url)) {
removeNodes.push(node);
}
}
// remove all the matching nodes
window.setTimeout(function() {
for (var i = 0, len = removeNodes.length; i < len; i++) {
if (removeNodes[i].parentNode) {
removeNodes[i].parentNode.removeChild(removeNodes[i]);
}
}
}, 100);
// invoke callback() on all registered items
for (i = 0, len = registry[url].length; i < len; i++) {
exec = registry[url][i];
exec.callback.call(exec.scope, count);
}
}
// simplified number formatter for this bubble.
// once 10,000 is hit, it is converted to "k" counts
// to avoid overflowing the bubble.
// 999...1,234...55 k...65.1 k...9,999 k
function formatNumber(num) {
var ret = num + "";
var rgx = /(\d+)(\d{3})/;
if (num > 10000) { // 11 k
ret = Math.floor(num / 1000);
return formatNumber(ret) + " k";
}
else if (num > 1000) { // 4,301
while (rgx.test(ret)) {
ret = ret.replace(rgx, '$1' + ',' + '$2');
}
return ret;
}
else {
return ret;
}
}
})(); // end anon
IN.addTag("i18nShare", IN.Tags.i18nShare);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment