Instantly share code, notes, and snippets.
Created
November 16, 2011 20:31
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save eoneill/1371276 to your computer and use it in GitHub Desktop.
i18nShare
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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