social-likes-nojq/src/social-likes.js

756 lines
20 KiB
JavaScript
Raw Permalink Normal View History

2012-06-14 11:26:25 +04:00
/**
* Social Likes
* http://sapegin.github.com/social-likes
*
* Sharing buttons for Russian and worldwide social networks.
2016-04-30 21:17:19 +03:00
* jQuery removed, only requires simple utilities: GET, onDomReady, http_build_query, addListener, removeListener
2012-06-14 11:26:25 +04:00
*
2016-05-01 14:41:03 +03:00
* @author Artem Sapegin, Vitaliy Filippov
* @copyright 2014 Artem Sapegin (sapegin.me), 2016 Vitaliy Filippov
2012-06-14 11:26:25 +04:00
* @license MIT
*/
2016-05-01 14:41:03 +03:00
/*jshint -W030 */
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
(function() {
2014-04-04 17:00:38 +04:00
'use strict';
var prefix = 'social-likes';
var classPrefix = prefix + '__';
var openClass = prefix + '_opened';
var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
var isHttps = protocol === 'https:';
2014-04-04 17:00:38 +04:00
2016-04-30 21:17:19 +03:00
function hasClass(e, cls, remove)
{
2016-05-01 14:41:03 +03:00
var p = -1, r = false;
2016-04-30 21:17:19 +03:00
while ((p = e.className.indexOf(cls, p+1)) != -1)
{
if ((!p || /\s/.exec(e.className.charAt(p-1))) &&
(p == e.className.length-cls.length || /\s/.exec(e.className.charAt(p+cls.length))))
{
2016-05-01 14:41:03 +03:00
r = true;
2016-04-30 21:17:19 +03:00
if (remove)
e.className = e.className.substr(0, p-1)+e.className.substr(p+cls.length);
}
}
2016-05-01 14:41:03 +03:00
return r;
2016-04-30 21:17:19 +03:00
}
function getScript(url, onsuccess, onerror)
{
var node = document.createElement('script');
node.type = 'text/javascript';
node.src = url;
2016-05-03 10:14:18 +03:00
node.onreadystatechange = function()
2016-04-30 21:17:19 +03:00
{
if (node.readyState == 'complete')
onsuccess && onsuccess();
else if (node.readyState == 'loaded')
{
node.children; // IE hack
if (node.readyState == 'loading')
onerror && onerror();
}
2016-05-03 10:14:18 +03:00
node.parentNode && node.parentNode.removeChild(node);
node = null;
};
node.onload = function()
{
onsuccess && onsuccess();
node.parentNode && node.parentNode.removeChild(node);
node = null;
};
node.onerror = function()
{
onerror && onerror();
node.parentNode && node.parentNode.removeChild(node);
node = null;
2016-04-30 21:17:19 +03:00
};
2016-05-03 10:14:18 +03:00
var head = document.head || document.getElementsByTagName('head')[0];
head.appendChild(node);
2016-04-30 21:17:19 +03:00
}
2014-04-04 17:00:38 +04:00
/**
* Buttons
*/
var services = {
facebook: {
2014-04-28 18:19:35 +04:00
// https://developers.facebook.com/docs/reference/fql/link_stat/
2014-04-04 17:00:38 +04:00
counterUrl: 'https://graph.facebook.com/fql?q=SELECT+total_count+FROM+link_stat+WHERE+url%3D%22{url}%22&callback=?',
convertNumber: function(data) {
return data.data[0].total_count;
},
popupUrl: 'https://www.facebook.com/sharer/sharer.php?u={url}',
popupWidth: 600,
2015-12-21 23:40:46 +03:00
popupHeight: 359
2012-06-14 11:26:25 +04:00
},
2014-04-04 17:00:38 +04:00
twitter: {
popupUrl: 'https://twitter.com/intent/tweet?url={url}&text={title}',
popupWidth: 600,
2015-12-21 23:40:46 +03:00
popupHeight: 250,
2014-04-04 17:00:38 +04:00
click: function() {
// Add colon to improve readability
if (!/[\.\?:\-–—]\s*$/.test(this.options.title)) this.options.title += ':';
2014-04-04 17:00:38 +04:00
return true;
2012-06-14 11:26:25 +04:00
}
},
2014-04-04 17:00:38 +04:00
mailru: {
counterUrl: protocol + '//connect.mail.ru/share_count?url_list={url}&callback=1&func=?',
convertNumber: function(data) {
for (var url in data) {
if (data.hasOwnProperty(url)) {
return data[url].shares;
}
2014-04-04 17:00:38 +04:00
}
},
2016-05-03 10:14:18 +03:00
popupUrl: 'https://connect.mail.ru/share?share_url={url}&title={title}&image_url={image}',
2015-12-21 23:40:46 +03:00
popupWidth: 492,
popupHeight: 500
2012-06-14 11:26:25 +04:00
},
2014-04-04 17:00:38 +04:00
vkontakte: {
counterUrl: 'https://vk.com/share.php?act=count&url={url}&index={index}',
2014-04-04 17:00:38 +04:00
counter: function(jsonUrl, deferred) {
var options = services.vkontakte;
if (!options._) {
options._ = [];
if (!window.VK) window.VK = {};
window.VK.Share = {
count: function(idx, number) {
options._[idx].resolve(number);
}
};
}
2014-04-04 17:00:38 +04:00
var index = options._.length;
options._.push(deferred);
2016-05-01 14:41:03 +03:00
getScript(makeUrl(jsonUrl, {index: index}), null, function() { deferred.reject(); });
2014-04-04 17:00:38 +04:00
},
2016-05-03 10:14:18 +03:00
popupUrl: 'https://vk.com/share.php?url={url}&title={title}&image={image}',
2015-12-21 23:40:46 +03:00
popupWidth: 655,
popupHeight: 450
},
2014-04-04 17:00:38 +04:00
odnoklassniki: {
2015-12-24 15:27:56 +03:00
counterUrl: protocol + '//connect.ok.ru/dk?st.cmd=extLike&ref={url}&uid={index}',
counter: function(jsonUrl, deferred) {
var options = services.odnoklassniki;
if (!options._) {
options._ = [];
if (!window.ODKL) window.ODKL = {};
window.ODKL.updateCount = function(idx, number) {
options._[idx].resolve(number);
};
}
var index = options._.length;
options._.push(deferred);
2016-05-01 14:41:03 +03:00
getScript(makeUrl(jsonUrl, {index: index}), null, function() { deferred.reject(); });
2014-04-04 17:00:38 +04:00
},
2015-12-21 23:40:12 +03:00
popupUrl: 'https://connect.ok.ru/dk?st.cmd=WidgetSharePreview&service=odnoklassniki&st.shareUrl={url}',
2015-12-21 23:40:46 +03:00
popupWidth: 580,
popupHeight: 336
2013-01-29 01:39:36 +04:00
},
2014-04-04 17:00:38 +04:00
plusone: {
2015-12-24 15:27:56 +03:00
counterUrl: protocol + '//share.yandex.ru/gpp.xml?url={url}&callback=?',
convertNumber: function(number) {
return parseInt(number.replace(/\D/g, ''), 10);
2014-04-04 17:00:38 +04:00
},
popupUrl: 'https://plus.google.com/share?url={url}',
2015-12-21 23:40:46 +03:00
popupWidth: 500,
popupHeight: 550
2014-04-04 17:00:38 +04:00
},
pinterest: {
counterUrl: protocol + '//api.pinterest.com/v1/urls/count.json?url={url}&callback=?',
convertNumber: function(data) {
return data.count;
},
2015-12-21 23:40:12 +03:00
popupUrl: 'https://pinterest.com/pin/create/button/?url={url}&description={title}',
2015-12-21 23:40:46 +03:00
popupWidth: 740,
popupHeight: 550
2012-06-14 11:26:25 +04:00
}
2014-04-04 17:00:38 +04:00
};
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
/**
* Counters manager
*/
var counters = {
promises: {},
fetch: function(service, url, extraOptions) {
if (!counters.promises[service]) counters.promises[service] = {};
var servicePromises = counters.promises[service];
2016-05-01 14:41:03 +03:00
if (!extraOptions.forceUpdate && servicePromises[url])
2014-04-04 17:00:38 +04:00
return servicePromises[url];
2016-05-01 14:41:03 +03:00
else
{
2016-04-30 21:17:19 +03:00
var options = {};
for (var i in services[service])
options[i] = services[service][i];
2016-05-01 14:41:03 +03:00
for (i in extraOptions)
2016-04-30 21:17:19 +03:00
options[i] = extraOptions[i];
var deferred = { resolve: function(v) {}, reject: function() {} };
2014-04-04 17:00:38 +04:00
var jsonUrl = options.counterUrl && makeUrl(options.counterUrl, {url: url});
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
if (jsonUrl && typeof options.counter == 'function')
2014-04-04 17:00:38 +04:00
options.counter(jsonUrl, deferred);
2016-04-30 21:17:19 +03:00
else if (options.counterUrl)
{
2016-05-03 10:14:18 +03:00
var cb = function(number)
2016-04-30 21:17:19 +03:00
{
2016-05-03 10:14:18 +03:00
try
{
if (typeof options.convertNumber == 'function')
number = options.convertNumber(number);
deferred.resolve(number);
}
catch (e)
{
2016-04-30 21:17:19 +03:00
deferred.reject();
2016-05-03 10:14:18 +03:00
}
};
if (jsonUrl.indexOf('=?') > 0)
{
var k = 0;
while (window['__jsonp'+k]) k++;
window['__jsonp'+k] = function(d)
2016-04-30 21:17:19 +03:00
{
2016-05-03 10:14:18 +03:00
delete window['__jsonp'+k];
cb(d);
};
jsonUrl = jsonUrl.replace('=?', '=__jsonp'+k);
getScript(jsonUrl, null, function() { deferred.reject(); });
}
else
{
GET(jsonUrl, function(r, d)
{
if (!r.responseText)
2014-04-04 17:00:38 +04:00
deferred.reject();
2016-05-03 10:14:18 +03:00
else
cb(d||r.responseText);
});
}
2014-04-04 17:00:38 +04:00
}
2016-04-30 21:17:19 +03:00
else
2014-04-04 17:00:38 +04:00
deferred.reject();
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
servicePromises[url] = deferred;
2014-04-04 17:00:38 +04:00
return servicePromises[url];
2014-02-04 12:50:52 +04:00
}
}
2014-04-04 17:00:38 +04:00
};
/**
* jQuery plugin
*/
2016-04-30 21:17:19 +03:00
window.socialLikes = function(element, options) {
var instance = element['__'+prefix];
if (instance) {
if (typeof options == 'object') {
instance.update(options);
2014-04-04 17:00:38 +04:00
}
2016-04-30 21:17:19 +03:00
}
else {
var c = {}, o = dataToOptions(element);
for (var i in window.socialLikes.defaults)
c[i] = window.socialLikes.defaults[i];
2016-05-01 14:41:03 +03:00
for (i in options)
2016-04-30 21:17:19 +03:00
c[i] = options[i];
2016-05-01 14:41:03 +03:00
for (i in o)
2016-04-30 21:17:19 +03:00
c[i] = o[i];
instance = new SocialLikes(element, c);
element['__'+prefix] = instance;
}
2014-04-04 17:00:38 +04:00
};
2016-05-03 10:14:18 +03:00
function getOg()
{
var h = {};
var es = document.getElementsByTagName('meta');
for (var i = 0; i < es.length; i++)
{
var p = es[i].getAttribute('property');
if (p && p.substr(0, 3) == 'og:')
h[p.substr(3)] = es[i].getAttribute('content');
}
return h;
}
var og = getOg();
2016-04-30 21:17:19 +03:00
window.socialLikes.defaults = {
2014-04-04 17:00:38 +04:00
url: window.location.href.replace(window.location.hash, ''),
2016-05-03 10:14:18 +03:00
title: og.title||document.title,
image: og.image,
2014-04-04 17:00:38 +04:00
counters: true,
zeroes: false,
wait: 500, // Show buttons only after counters are ready or after this amount of time
timeout: 10000, // Show counters after this amount of time even if they arent ready
2014-04-04 17:00:38 +04:00
popupCheckInterval: 500,
singleTitle: 'Share'
};
function SocialLikes(container, options) {
this.container = container;
this.options = options;
this.init();
}
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
SocialLikes.prototype = {
init: function() {
2016-04-30 21:17:19 +03:00
var self = this;
2014-04-04 17:00:38 +04:00
// Add class in case of manual initialization
2016-04-30 21:17:19 +03:00
if (!hasClass(this.container, prefix))
this.container.className += ' '+prefix;
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
this.single = hasClass(this.container, prefix+'_single');
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
this.initUserButtons();
2013-04-17 17:11:33 +04:00
this.countersLeft = 0;
2014-04-04 17:00:38 +04:00
this.number = 0;
2016-04-30 21:17:19 +03:00
this.container['on_counter.' + prefix] = function(e) { return self.updateCounter(e); };
2014-11-06 11:53:17 +03:00
2014-04-04 17:00:38 +04:00
this.makeSingleButton();
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
this.buttons = [];
2016-04-30 21:17:19 +03:00
for (var i = 0; i < this.container.children.length; i++)
{
var button = new Button(this.container.children[i], this.options);
this.buttons.push(button);
2016-04-30 21:17:19 +03:00
if (button.options.counterUrl)
this.countersLeft++;
}
2014-01-16 15:06:36 +04:00
2016-04-30 21:17:19 +03:00
if (this.options.counters)
{
2016-05-01 14:41:03 +03:00
this.timer = setTimeout(function() { self.appear(); }, this.options.wait);
this.timeout = setTimeout(function() { self.ready(); }, this.options.timeout);
2014-04-04 17:00:38 +04:00
}
2016-04-30 21:17:19 +03:00
else
2014-04-04 17:00:38 +04:00
this.appear();
},
initUserButtons: function() {
if (!this.userButtonInited && window.socialLikesButtons) {
2016-05-01 14:41:03 +03:00
for (var i in window.socialLikesButtons) {
2016-04-30 21:17:19 +03:00
services[i] = services[i] || {};
2016-05-01 14:41:03 +03:00
for (var j in window.socialLikesButtons[i])
services[i][j] = window.socialLikesButtons[i][j];
2016-04-30 21:17:19 +03:00
}
2014-04-04 17:00:38 +04:00
}
this.userButtonInited = true;
},
makeSingleButton: function() {
if (!this.single) return;
var container = this.container;
2016-04-30 21:17:19 +03:00
container.className += ' ' + prefix + '_vertical';
var wrapper = document.createElement('div');
wrapper.className = prefix + '_single-w';
container.parentNode.insertBefore(wrapper, container);
wrapper.appendChild(container);
var d = document.createElement('div');
d.className = prefix + '__single-container';
while (container.firstChild)
d.appendChild(container.firstChild);
container.appendChild(d);
2014-04-04 17:00:38 +04:00
// Widget
2016-04-30 21:17:19 +03:00
var widget = document.createElement('div');
widget.className = getElementClassNames('widget', 'single');
widget.innerHTML = '<div class="'+getElementClassNames('button', 'single')+
'"><span class="'+getElementClassNames('icon', 'single')+'"></span>'+
this.options.singleTitle+'</div>';
wrapper.appendChild(widget);
addListener(widget, 'click', function() {
var activeClass = prefix+'__widget_active';
2016-05-01 14:41:03 +03:00
if (!hasClass(widget, activeClass, true)) {
2016-04-30 21:17:19 +03:00
widget.className += ' '+activeClass;
container.style.left = ((widget.offsetWidth-container.offsetWidth)/2)+'px';
container.style.top = -container.offsetHeight+'px';
2014-04-04 17:00:38 +04:00
showInViewport(container);
closeOnClick(container, function() {
2016-04-30 21:17:19 +03:00
hasClass(widget, activeClass, true);
2014-04-04 17:00:38 +04:00
});
}
else {
2016-04-30 21:17:19 +03:00
hasClass(container, openClass, true);
2014-04-04 17:00:38 +04:00
}
return false;
});
2014-01-16 15:06:36 +04:00
2014-04-04 17:00:38 +04:00
this.widget = widget;
},
update: function(options) {
if (!options.forceUpdate && options.url === this.options.url) return;
// Reset counters
this.number = 0;
this.countersLeft = this.buttons.length;
2016-04-30 21:17:19 +03:00
if (this.widget)
{
var e = this.widget.querySelector('.' + prefix + '__counter');
if (e) e.parentNode.removeChild(e);
}
2014-04-04 17:00:38 +04:00
// Update options
2016-04-30 21:17:19 +03:00
for (var i in options)
this.options[i] = options[i];
for (var buttonIdx = 0; buttonIdx < this.buttons.length; buttonIdx++)
2014-04-04 17:00:38 +04:00
this.buttons[buttonIdx].update(options);
},
updateCounter: function(e, service, number) {
number = number || 0;
if (number || this.options.zeroes) {
2014-04-04 17:00:38 +04:00
this.number += number;
if (this.single) {
this.getCounterElem().text(this.number);
}
}
2014-04-04 17:00:38 +04:00
if (this.countersLeft === 0) {
this.appear();
this.ready();
2013-12-31 11:46:56 +04:00
}
2015-12-16 16:25:20 +03:00
this.countersLeft--;
2014-04-04 17:00:38 +04:00
},
appear: function() {
2016-04-30 21:17:19 +03:00
this.container.className += ' '+prefix+'_visible';
2014-04-04 17:00:38 +04:00
},
ready: function(silent) {
if (this.timeout) {
clearTimeout(this.timeout);
}
2016-04-30 21:17:19 +03:00
this.container.className += ' '+prefix+'_ready';
if (!silent) {
2016-04-30 21:17:19 +03:00
var e = this.container['on_ready.'+prefix];
if (e) e(this.number);
}
},
2014-04-04 17:00:38 +04:00
getCounterElem: function() {
2016-04-30 21:17:19 +03:00
var counterElem = this.widget.querySelector('.' + classPrefix + 'counter_single');
2014-04-04 17:00:38 +04:00
if (!counterElem.length) {
2016-04-30 21:17:19 +03:00
counterElem = document.createElement('span');
counterElem.className = getElementClassNames('counter', 'single');
2014-04-04 17:00:38 +04:00
this.widget.append(counterElem);
}
2014-04-04 17:00:38 +04:00
return counterElem;
}
};
2013-12-31 11:46:56 +04:00
2014-04-04 17:00:38 +04:00
function Button(widget, options) {
2013-12-31 11:46:56 +04:00
this.widget = widget;
2016-04-30 21:17:19 +03:00
this.options = {};
for (var i in options)
this.options[i] = options[i];
2014-04-04 17:00:38 +04:00
this.detectService();
if (this.service) {
this.init();
2014-02-04 12:50:52 +04:00
}
2014-04-04 17:00:38 +04:00
}
Button.prototype = {
init: function() {
this.detectParams();
this.initHtml();
2016-04-30 21:17:19 +03:00
var self = this;
2016-05-01 14:41:03 +03:00
setTimeout(function() { self.initCounter(); }, 0);
2014-04-04 17:00:38 +04:00
},
update: function(options) {
2016-04-30 21:17:19 +03:00
this.options.forceUpdate = false;
for (var i in options)
this.options[i] = options[i];
var e = this.widget.querySelector('.' + prefix + '__counter');
if (e) e.parentNode.removeChild(e); // Remove old counter
2014-04-04 17:00:38 +04:00
this.initCounter();
},
detectService: function() {
2016-04-30 21:17:19 +03:00
var service = this.widget.getAttribute('data-service');
2014-04-10 09:51:02 +04:00
if (!service) {
// class="facebook"
2016-04-30 21:17:19 +03:00
var classes = this.widget.classList || this.widget.className.split(' ');
2014-04-05 08:54:18 +04:00
for (var classIdx = 0; classIdx < classes.length; classIdx++) {
var cls = classes[classIdx];
if (services[cls]) {
2014-04-10 09:51:02 +04:00
service = cls;
break;
2014-04-05 08:54:18 +04:00
}
2014-04-04 17:00:38 +04:00
}
2014-04-10 09:51:02 +04:00
if (!service) return;
}
2014-04-10 09:51:02 +04:00
this.service = service;
2016-04-30 21:17:19 +03:00
for (var i in services[service])
this.options[i] = services[service][i];
2014-04-04 17:00:38 +04:00
},
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
detectParams: function() {
// Custom page counter URL or number
2016-04-30 21:17:19 +03:00
var c = this.widget.getAttribute('data-counter');
if (c) {
var number = parseInt(c, 10);
if (isNaN(number))
this.options.counterUrl = c;
else
2014-04-04 17:00:38 +04:00
this.options.counterNumber = number;
}
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
// Custom page title
2016-04-30 21:17:19 +03:00
c = this.widget.getAttribute('data-title');
if (c)
this.options.title = c;
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
// Custom page URL
2016-04-30 21:17:19 +03:00
c = this.widget.getAttribute('data-url');
if (c)
this.options.url = c;
2014-04-04 17:00:38 +04:00
},
initHtml: function() {
2016-04-30 21:17:19 +03:00
var self = this;
2014-04-04 17:00:38 +04:00
var options = this.options;
var widget = this.widget;
// Old initialization HTML
2016-04-30 21:17:19 +03:00
var a = widget.querySelector('a');
if (a)
2014-04-04 17:00:38 +04:00
this.cloneDataAttrs(a, widget);
2014-01-15 12:27:09 +04:00
2014-04-04 17:00:38 +04:00
// Button
2016-04-30 21:17:19 +03:00
var button = document.createElement('span');
button.className = this.getElementClassNames('button');
button.innerHTML = widget.innerHTML;
2014-04-04 17:00:38 +04:00
if (options.clickUrl) {
var url = makeUrl(options.clickUrl, {
url: options.url,
2016-05-03 10:14:18 +03:00
title: options.title,
image: options.image||''
2014-04-04 17:00:38 +04:00
});
2016-04-30 21:17:19 +03:00
var link = document.createElement('a');
link.href = url;
2014-04-04 17:00:38 +04:00
this.cloneDataAttrs(widget, link);
2016-04-30 21:17:19 +03:00
widget.parentNode.insertBefore(link, widget);
widget.parentNode.removeChild(widget);
2014-04-04 17:00:38 +04:00
this.widget = widget = link;
2014-01-15 12:27:09 +04:00
}
else {
2016-05-01 14:41:03 +03:00
addListener(widget, 'click', function() { self.click(); });
2014-01-15 12:27:09 +04:00
}
2013-02-05 16:22:54 +04:00
2016-04-30 21:17:19 +03:00
widget.className = widget.className.replace(' '+this.service, '') + ' '+this.getElementClassNames('widget');
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
// Icon
2016-04-30 21:17:19 +03:00
var s = document.createElement('span');
s.className = this.getElementClassNames('icon');
button.children.length ? button.insertBefore(s, button.firstChild) : button.appendChild(s);
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
widget.innerHTML = '';
widget.appendChild(button);
2014-04-04 17:00:38 +04:00
this.button = button;
},
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
initCounter: function() {
if (this.options.counters) {
if (this.options.counterNumber) {
this.updateCounter(this.options.counterNumber);
}
else {
var extraOptions = {
counterUrl: this.options.counterUrl,
forceUpdate: this.options.forceUpdate
};
2016-04-30 21:17:19 +03:00
var self = this;
var r = counters.fetch(this.service, this.options.url, extraOptions);
2016-05-01 14:41:03 +03:00
r.reject = r.resolve = function(n) { self.updateCounter(n); };
2014-04-04 17:00:38 +04:00
}
}
},
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
cloneDataAttrs: function(source, destination) {
2016-04-30 21:17:19 +03:00
for (var i = 0; i < source.attributes.length; i++)
if (source.attributes[i].name.substr(0, 5) == 'data-')
destination.setAttribute(source.attributes[i].name, source.attributes[i].value);
2014-04-04 17:00:38 +04:00
},
2014-04-04 17:00:38 +04:00
getElementClassNames: function(elem) {
return getElementClassNames(elem, this.service);
},
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
updateCounter: function(number) {
number = parseInt(number, 10) || 0;
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
var counterElem = document.createElement('span');
2016-05-01 14:41:03 +03:00
if (!number && !this.options.zeroes)
2016-04-30 21:17:19 +03:00
counterElem.className = this.getElementClassNames('counter') + ' ' + prefix + '__counter_empty';
2016-05-01 14:41:03 +03:00
else
{
2016-04-30 21:17:19 +03:00
counterElem.innerHTML = number;
counterElem.className = this.getElementClassNames('counter');
2014-02-04 12:50:52 +04:00
}
2016-04-30 21:17:19 +03:00
this.widget.appendChild(counterElem);
2014-04-04 17:00:38 +04:00
2016-04-30 21:17:19 +03:00
var e = this.widget['on_counter.'+prefix];
if (e) e([this.service, number]);
2014-04-04 17:00:38 +04:00
},
click: function(e) {
var options = this.options;
var process = true;
2016-04-30 21:17:19 +03:00
if (typeof options.click == 'function') {
2014-04-04 17:00:38 +04:00
process = options.click.call(this, e);
2014-02-04 12:50:52 +04:00
}
2014-04-04 17:00:38 +04:00
if (process) {
var url = makeUrl(options.popupUrl, {
url: options.url,
2016-05-03 10:14:18 +03:00
title: options.title,
image: options.image||''
2014-04-04 17:00:38 +04:00
});
url = this.addAdditionalParamsToUrl(url);
this.openPopup(url, {
width: options.popupWidth,
height: options.popupHeight
});
}
return false;
},
2014-02-04 12:50:52 +04:00
2014-04-04 17:00:38 +04:00
addAdditionalParamsToUrl: function(url) {
2016-04-30 21:17:19 +03:00
var params = dataToOptions(this.widget);
for (var i in this.options.data)
params[i] = this.options.data[i];
var s = '';
2016-05-01 14:41:03 +03:00
for (i in params)
2016-04-30 21:17:19 +03:00
s += '&'+encodeURIComponent(i)+'='+encodeURIComponent(params[i]);
if (!s)
return url;
if (!url.indexOf('?'))
s = '?'+s.substr(1);
return url + s;
2014-04-04 17:00:38 +04:00
},
openPopup: function(url, params) {
var left = Math.round(screen.width/2 - params.width/2);
var top = 0;
if (screen.height > params.height) {
top = Math.round(screen.height/3 - params.height/2);
}
var win = window.open(url, 'sl_' + this.service, 'left=' + left + ',top=' + top + ',' +
'width=' + params.width + ',height=' + params.height + ',personalbar=0,toolbar=0,scrollbars=1,resizable=1');
if (win) {
win.focus();
2016-04-30 21:17:19 +03:00
var e = this.widget['on_popup_opened.' + prefix];
if (e) e([this.service, win]);
var self = this;
var timer = setInterval(function() {
2014-04-04 17:00:38 +04:00
if (!win.closed) return;
clearInterval(timer);
2016-04-30 21:17:19 +03:00
var e = self.widget['on_popup_closed.' + prefix];
if (e) e(self.service);
}, this.options.popupCheckInterval);
2014-04-04 17:00:38 +04:00
}
else {
location.href = url;
2013-10-29 21:35:33 +04:00
}
2012-06-14 11:26:25 +04:00
}
2014-04-04 17:00:38 +04:00
};
2012-06-14 11:26:25 +04:00
2014-04-04 17:00:38 +04:00
/**
* Helpers
*/
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
// Camelize data-attributes
function dataToOptions(elem, nocamel)
{
function upper(m, l)
{
2014-04-04 17:00:38 +04:00
return l.toUpper();
2013-10-29 21:35:33 +04:00
}
2014-04-04 17:00:38 +04:00
var options = {};
2016-04-30 21:17:19 +03:00
for (var i = 0; i < elem.attributes.length; i++)
{
var key = elem.attributes[i].name;
if (key.substr(0, 5) == 'data-')
{
key = key.substr(5);
var value = elem.attributes[i].value;
if (value === 'yes') value = true;
else if (value === 'no') value = false;
options[nocamel ? key : key.replace(/-(\w)/g, upper)] = value;
}
2012-06-14 11:26:25 +04:00
}
2014-04-04 17:00:38 +04:00
return options;
2012-06-14 11:26:25 +04:00
}
2014-04-04 17:00:38 +04:00
function makeUrl(url, context) {
return template(url, context, encodeURIComponent);
2014-01-15 12:27:09 +04:00
}
2014-04-04 17:00:38 +04:00
function template(tmpl, context, filter) {
return tmpl.replace(/\{([^\}]+)\}/g, function(m, key) {
2014-04-28 18:19:29 +04:00
// If key doesn't exists in the context we should keep template tag as is
2014-04-04 17:00:38 +04:00
return key in context ? (filter ? filter(context[key]) : context[key]) : m;
});
2014-01-15 12:27:09 +04:00
}
2014-04-04 17:00:38 +04:00
function getElementClassNames(elem, mod) {
var cls = classPrefix + elem;
return cls + ' ' + cls + '_' + mod;
}
2012-06-14 11:26:25 +04:00
2016-04-30 21:17:19 +03:00
function closeOnClick(elem, callback)
{
function handler(e)
{
if (e.type === 'keydown' && e.which !== 27)
return;
for (var i = e; i && i != elem; i = i.parentNode) {}
if (i == elem)
return;
hasClass(elem, openClass, true);
removeListener(document, 'click', handler);
removeListener(document, 'touchstart', handler);
removeListener(document, 'keydown', handler);
callback();
2014-04-04 17:00:38 +04:00
}
var events = 'click touchstart keydown';
2016-04-30 21:17:19 +03:00
addListener(document, 'click', handler);
addListener(document, 'touchstart', handler);
addListener(document, 'keydown', handler);
}
2014-04-04 17:00:38 +04:00
function showInViewport(elem) {
var offset = 10;
if (document.documentElement.getBoundingClientRect) {
2016-04-30 21:17:19 +03:00
var left = parseInt(elem.style.left, 10);
var top = parseInt(elem.style.top, 10);
2014-04-04 17:00:38 +04:00
var rect = elem[0].getBoundingClientRect();
if (rect.left < offset)
2016-04-30 21:17:19 +03:00
elem.stype.left = (offset - rect.left + left)+'px';
2014-04-04 17:00:38 +04:00
else if (rect.right > window.innerWidth - offset)
2016-04-30 21:17:19 +03:00
elem.style.left = (window.innerWidth - rect.right - offset + left)+'px';
2014-04-04 17:00:38 +04:00
if (rect.top < offset)
2016-04-30 21:17:19 +03:00
elem.style.top = (offset - rect.top + top)+'px';
2014-04-04 17:00:38 +04:00
else if (rect.bottom > window.innerHeight - offset)
2016-04-30 21:17:19 +03:00
elem.style.top = (window.innerHeight - rect.bottom - offset + top)+'px';
2014-04-04 17:00:38 +04:00
}
2016-04-30 21:17:19 +03:00
elem.className += ' '+openClass;
2012-06-14 11:26:25 +04:00
}
2014-04-04 17:00:38 +04:00
/**
* Auto initialization
*/
2016-04-30 21:17:19 +03:00
onDomReady(function() {
var es = document.querySelectorAll('.' + prefix);
for (var i = 0; i < es.length; i++)
2016-05-01 14:41:03 +03:00
window.socialLikes(es[i]);
2014-04-04 17:00:38 +04:00
});
2016-04-30 21:17:19 +03:00
})();