2012-06-14 11:26:25 +04:00
|
|
|
|
/**
|
|
|
|
|
* Social Likes
|
|
|
|
|
* http://sapegin.github.com/social-likes
|
|
|
|
|
*
|
|
|
|
|
* Sharing buttons for Russian and worldwide social networks.
|
|
|
|
|
*
|
2012-08-02 15:39:51 +04:00
|
|
|
|
* @requires jQuery
|
2012-06-14 11:26:25 +04:00
|
|
|
|
* @author Artem Sapegin
|
2014-01-14 10:31:31 +04:00
|
|
|
|
* @copyright 2014 Artem Sapegin (sapegin.me)
|
2012-06-14 11:26:25 +04:00
|
|
|
|
* @license MIT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*global define:false, socialLikesButtons:false */
|
|
|
|
|
|
2013-10-29 21:35:33 +04:00
|
|
|
|
(function(factory) { // Try to register as an anonymous AMD module
|
2012-06-14 11:26:25 +04:00
|
|
|
|
if (typeof define === 'function' && define.amd) {
|
|
|
|
|
define(['jquery'], factory);
|
2013-10-29 21:35:33 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
2012-06-14 11:26:25 +04:00
|
|
|
|
factory(jQuery);
|
|
|
|
|
}
|
2013-12-23 23:55:51 +04:00
|
|
|
|
}(function($, undefined) {
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
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:';
|
2015-01-19 12:17:14 +03:00
|
|
|
|
var isHttps = protocol === 'https:';
|
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,
|
|
|
|
|
popupHeight: 500
|
2012-06-14 11:26:25 +04:00
|
|
|
|
},
|
2014-04-04 17:00:38 +04:00
|
|
|
|
twitter: {
|
|
|
|
|
counterUrl: 'https://cdn.api.twitter.com/1/urls/count.json?url={url}&callback=?',
|
|
|
|
|
convertNumber: function(data) {
|
|
|
|
|
return data.count;
|
|
|
|
|
},
|
|
|
|
|
popupUrl: 'https://twitter.com/intent/tweet?url={url}&text={title}',
|
|
|
|
|
popupWidth: 600,
|
|
|
|
|
popupHeight: 450,
|
|
|
|
|
click: function() {
|
|
|
|
|
// Add colon to improve readability
|
|
|
|
|
if (!/[\.:\-–—]\s*$/.test(this.options.title)) this.options.title += ':';
|
|
|
|
|
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;
|
2012-08-02 15:17:38 +04:00
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
popupUrl: protocol + '//connect.mail.ru/share?share_url={url}&title={title}',
|
|
|
|
|
popupWidth: 550,
|
|
|
|
|
popupHeight: 360
|
2012-06-14 11:26:25 +04:00
|
|
|
|
},
|
2014-04-04 17:00:38 +04:00
|
|
|
|
vkontakte: {
|
2015-01-13 18:03:30 +03:00
|
|
|
|
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-01-14 10:18:07 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
var index = options._.length;
|
|
|
|
|
options._.push(deferred);
|
|
|
|
|
$.getScript(makeUrl(jsonUrl, {index: index}))
|
|
|
|
|
.fail(deferred.reject);
|
|
|
|
|
},
|
|
|
|
|
popupUrl: protocol + '//vk.com/share.php?url={url}&title={title}',
|
|
|
|
|
popupWidth: 550,
|
|
|
|
|
popupHeight: 330
|
2014-01-14 10:18:07 +04:00
|
|
|
|
},
|
2014-04-04 17:00:38 +04:00
|
|
|
|
odnoklassniki: {
|
2015-02-12 20:10:18 +03:00
|
|
|
|
counterUrl: 'https://share.yandex.net/counter/odnoklassniki/?url={url}',
|
2014-11-20 15:30:33 +03:00
|
|
|
|
counter: function(jsonUrl, deferred) {
|
|
|
|
|
var options = services.odnoklassniki;
|
2015-02-12 20:10:18 +03:00
|
|
|
|
if (options._) {
|
|
|
|
|
// Reject all counters except the first because this counter doesn’t neither return URL nor accept callback
|
|
|
|
|
deferred.reject();
|
|
|
|
|
return;
|
2014-11-20 15:30:33 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-02-12 20:10:18 +03:00
|
|
|
|
if (!window.ODKL) window.ODKL = {};
|
|
|
|
|
window.ODKL.updateCount = function(idx, number) {
|
|
|
|
|
deferred.resolve(number);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
options._ = deferred;
|
|
|
|
|
$.getScript(makeUrl(jsonUrl))
|
2014-11-20 15:31:34 +03:00
|
|
|
|
.fail(deferred.reject);
|
2014-04-04 17:00:38 +04:00
|
|
|
|
},
|
2015-01-13 18:09:14 +03:00
|
|
|
|
popupUrl: 'http://connect.ok.ru/dk?st.cmd=WidgetSharePreview&service=odnoklassniki&st.shareUrl={url}',
|
2014-04-04 17:00:38 +04:00
|
|
|
|
popupWidth: 550,
|
|
|
|
|
popupHeight: 360
|
2013-01-29 01:39:36 +04:00
|
|
|
|
},
|
2014-04-04 17:00:38 +04:00
|
|
|
|
plusone: {
|
|
|
|
|
// HTTPS not supported yet: http://clubs.ya.ru/share/1499
|
2015-01-19 12:17:14 +03:00
|
|
|
|
counterUrl: isHttps ? undefined : 'http://share.yandex.ru/gpp.xml?url={url}',
|
2014-04-04 17:00:38 +04:00
|
|
|
|
counter: function(jsonUrl, deferred) {
|
|
|
|
|
var options = services.plusone;
|
|
|
|
|
if (options._) {
|
2014-09-10 21:43:40 +04:00
|
|
|
|
// Reject all counters except the first because Yandex Share counter doesn’t return URL
|
2014-04-04 17:00:38 +04:00
|
|
|
|
deferred.reject();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
if (!window.services) window.services = {};
|
|
|
|
|
window.services.gplus = {
|
|
|
|
|
cb: function(number) {
|
|
|
|
|
options._.resolve(number);
|
|
|
|
|
}
|
|
|
|
|
};
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
options._ = deferred;
|
|
|
|
|
$.getScript(makeUrl(jsonUrl))
|
|
|
|
|
.fail(deferred.reject);
|
|
|
|
|
},
|
|
|
|
|
popupUrl: 'https://plus.google.com/share?url={url}',
|
|
|
|
|
popupWidth: 700,
|
|
|
|
|
popupHeight: 500
|
|
|
|
|
},
|
|
|
|
|
pinterest: {
|
|
|
|
|
counterUrl: protocol + '//api.pinterest.com/v1/urls/count.json?url={url}&callback=?',
|
|
|
|
|
convertNumber: function(data) {
|
|
|
|
|
return data.count;
|
|
|
|
|
},
|
|
|
|
|
popupUrl: protocol + '//pinterest.com/pin/create/button/?url={url}&description={title}',
|
|
|
|
|
popupWidth: 630,
|
|
|
|
|
popupHeight: 270
|
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];
|
|
|
|
|
|
|
|
|
|
if (!extraOptions.forceUpdate && servicePromises[url]) {
|
|
|
|
|
return servicePromises[url];
|
2012-06-14 11:26:25 +04:00
|
|
|
|
}
|
2014-01-14 12:18:59 +04:00
|
|
|
|
else {
|
2014-04-04 17:00:38 +04:00
|
|
|
|
var options = $.extend({}, services[service], extraOptions);
|
|
|
|
|
var deferred = $.Deferred();
|
|
|
|
|
var jsonUrl = options.counterUrl && makeUrl(options.counterUrl, {url: url});
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
if (jsonUrl && $.isFunction(options.counter)) {
|
|
|
|
|
options.counter(jsonUrl, deferred);
|
|
|
|
|
}
|
|
|
|
|
else if (options.counterUrl) {
|
|
|
|
|
$.getJSON(jsonUrl)
|
|
|
|
|
.done(function(data) {
|
|
|
|
|
try {
|
|
|
|
|
var number = data;
|
|
|
|
|
if ($.isFunction(options.convertNumber)) {
|
|
|
|
|
number = options.convertNumber(data);
|
|
|
|
|
}
|
|
|
|
|
deferred.resolve(number);
|
|
|
|
|
}
|
|
|
|
|
catch (e) {
|
|
|
|
|
deferred.reject();
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.fail(deferred.reject);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
deferred.reject();
|
|
|
|
|
}
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
servicePromises[url] = deferred.promise();
|
|
|
|
|
return servicePromises[url];
|
2014-02-04 12:50:52 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* jQuery plugin
|
|
|
|
|
*/
|
|
|
|
|
$.fn.socialLikes = function(options) {
|
|
|
|
|
return this.each(function() {
|
|
|
|
|
var elem = $(this);
|
|
|
|
|
var instance = elem.data(prefix);
|
|
|
|
|
if (instance) {
|
|
|
|
|
if ($.isPlainObject(options)) {
|
|
|
|
|
instance.update(options);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
instance = new SocialLikes(elem, $.extend({}, $.fn.socialLikes.defaults, options, dataToOptions(elem)));
|
|
|
|
|
elem.data(prefix, instance);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
$.fn.socialLikes.defaults = {
|
|
|
|
|
url: window.location.href.replace(window.location.hash, ''),
|
|
|
|
|
title: document.title,
|
|
|
|
|
counters: true,
|
|
|
|
|
zeroes: false,
|
|
|
|
|
wait: 500,
|
|
|
|
|
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() {
|
|
|
|
|
// Add class in case of manual initialization
|
|
|
|
|
this.container.addClass(prefix);
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
this.single = this.container.hasClass(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
|
|
|
|
|
2014-10-09 11:08:28 +04:00
|
|
|
|
this.countersLeft = 0;
|
2014-04-04 17:00:38 +04:00
|
|
|
|
this.number = 0;
|
|
|
|
|
this.container.on('counter.' + prefix, $.proxy(this.updateCounter, this));
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-11-06 11:53:17 +03:00
|
|
|
|
var buttons = this.container.children();
|
|
|
|
|
|
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 = [];
|
|
|
|
|
buttons.each($.proxy(function(idx, elem) {
|
2014-10-09 11:08:28 +04:00
|
|
|
|
var button = new Button($(elem), this.options);
|
|
|
|
|
this.buttons.push(button);
|
|
|
|
|
if (button.options.counterUrl) this.countersLeft++;
|
2014-04-04 17:00:38 +04:00
|
|
|
|
}, this));
|
2014-01-16 15:06:36 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
if (this.options.counters) {
|
|
|
|
|
this.timer = setTimeout($.proxy(this.appear, this), this.options.wait);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.appear();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
initUserButtons: function() {
|
|
|
|
|
if (!this.userButtonInited && window.socialLikesButtons) {
|
|
|
|
|
$.extend(true, services, socialLikesButtons);
|
|
|
|
|
}
|
|
|
|
|
this.userButtonInited = true;
|
|
|
|
|
},
|
|
|
|
|
makeSingleButton: function() {
|
|
|
|
|
if (!this.single) return;
|
|
|
|
|
|
|
|
|
|
var container = this.container;
|
|
|
|
|
container.addClass(prefix + '_vertical');
|
|
|
|
|
container.wrap($('<div>', {'class': prefix + '_single-w'}));
|
|
|
|
|
container.wrapInner($('<div>', {'class': prefix + '__single-container'}));
|
|
|
|
|
var wrapper = container.parent();
|
|
|
|
|
|
|
|
|
|
// Widget
|
|
|
|
|
var widget = $('<div>', {
|
|
|
|
|
'class': getElementClassNames('widget', 'single')
|
|
|
|
|
});
|
|
|
|
|
var button = $(template(
|
|
|
|
|
'<div class="{buttonCls}">' +
|
|
|
|
|
'<span class="{iconCls}"></span>' +
|
|
|
|
|
'{title}' +
|
|
|
|
|
'</div>',
|
|
|
|
|
{
|
|
|
|
|
buttonCls: getElementClassNames('button', 'single'),
|
|
|
|
|
iconCls: getElementClassNames('icon', 'single'),
|
|
|
|
|
title: this.options.singleTitle
|
|
|
|
|
}
|
|
|
|
|
));
|
|
|
|
|
widget.append(button);
|
|
|
|
|
wrapper.append(widget);
|
|
|
|
|
|
2015-01-18 22:32:43 +03:00
|
|
|
|
widget.on('click', function() {
|
2014-04-04 17:00:38 +04:00
|
|
|
|
var activeClass = prefix + '__widget_active';
|
|
|
|
|
widget.toggleClass(activeClass);
|
|
|
|
|
if (widget.hasClass(activeClass)) {
|
|
|
|
|
container.css({left: -(container.width()-widget.width())/2, top: -container.height()});
|
|
|
|
|
showInViewport(container);
|
|
|
|
|
closeOnClick(container, function() {
|
|
|
|
|
widget.removeClass(activeClass);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
container.removeClass(openClass);
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
if (this.widget) this.widget.find('.' + prefix + '__counter').remove();
|
|
|
|
|
|
|
|
|
|
// Update options
|
|
|
|
|
$.extend(this.options, options);
|
|
|
|
|
for (var buttonIdx = 0; buttonIdx < this.buttons.length; buttonIdx++) {
|
|
|
|
|
this.buttons[buttonIdx].update(options);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
updateCounter: function(e, service, number) {
|
|
|
|
|
if (number) {
|
|
|
|
|
this.number += number;
|
|
|
|
|
if (this.single) {
|
|
|
|
|
this.getCounterElem().text(this.number);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-01-14 12:18:59 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
this.countersLeft--;
|
|
|
|
|
if (this.countersLeft === 0) {
|
|
|
|
|
this.appear();
|
|
|
|
|
this.container.addClass(prefix + '_ready');
|
|
|
|
|
this.container.trigger('ready.' + prefix, this.number);
|
2013-12-31 11:46:56 +04:00
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
},
|
|
|
|
|
appear: function() {
|
|
|
|
|
this.container.addClass(prefix + '_visible');
|
|
|
|
|
},
|
|
|
|
|
getCounterElem: function() {
|
|
|
|
|
var counterElem = this.widget.find('.' + classPrefix + 'counter_single');
|
|
|
|
|
if (!counterElem.length) {
|
|
|
|
|
counterElem = $('<span>', {
|
|
|
|
|
'class': getElementClassNames('counter', 'single')
|
2014-04-01 12:49:35 +04:00
|
|
|
|
});
|
2014-04-04 17:00:38 +04:00
|
|
|
|
this.widget.append(counterElem);
|
2014-04-01 12:49:35 +04:00
|
|
|
|
}
|
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;
|
2014-04-04 17:00:38 +04:00
|
|
|
|
this.options = $.extend({}, options);
|
|
|
|
|
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();
|
2014-11-20 18:32:02 +03:00
|
|
|
|
setTimeout($.proxy(this.initCounter, this), 0);
|
2014-04-04 17:00:38 +04:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
update: function(options) {
|
|
|
|
|
$.extend(this.options, {forceUpdate: false}, options);
|
|
|
|
|
this.widget.find('.' + prefix + '__counter').remove(); // Remove old counter
|
|
|
|
|
this.initCounter();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
detectService: function() {
|
2014-04-10 09:51:02 +04:00
|
|
|
|
var service = this.widget.data('service');
|
|
|
|
|
if (!service) {
|
|
|
|
|
// class="facebook"
|
|
|
|
|
var node = this.widget[0];
|
|
|
|
|
var classes = node.classList || node.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-01-14 12:18:59 +04:00
|
|
|
|
}
|
2014-04-10 09:51:02 +04:00
|
|
|
|
this.service = service;
|
|
|
|
|
$.extend(this.options, services[service]);
|
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() {
|
|
|
|
|
var data = this.widget.data();
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
// Custom page counter URL or number
|
|
|
|
|
if (data.counter) {
|
|
|
|
|
var number = parseInt(data.counter, 10);
|
|
|
|
|
if (isNaN(number)) {
|
|
|
|
|
this.options.counterUrl = data.counter;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
this.options.counterNumber = number;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
// Custom page title
|
|
|
|
|
if (data.title) {
|
|
|
|
|
this.options.title = data.title;
|
2012-06-14 11:26:25 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
// Custom page URL
|
|
|
|
|
if (data.url) {
|
|
|
|
|
this.options.url = data.url;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
initHtml: function() {
|
|
|
|
|
var options = this.options;
|
|
|
|
|
var widget = this.widget;
|
|
|
|
|
|
|
|
|
|
// Old initialization HTML
|
|
|
|
|
var a = widget.find('a');
|
|
|
|
|
if (a.length) {
|
|
|
|
|
this.cloneDataAttrs(a, widget);
|
|
|
|
|
}
|
2014-01-15 12:27:09 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
// Button
|
|
|
|
|
var button = $('<span>', {
|
|
|
|
|
'class': this.getElementClassNames('button'),
|
|
|
|
|
'text': widget.text()
|
|
|
|
|
});
|
|
|
|
|
if (options.clickUrl) {
|
|
|
|
|
var url = makeUrl(options.clickUrl, {
|
|
|
|
|
url: options.url,
|
|
|
|
|
title: options.title
|
|
|
|
|
});
|
|
|
|
|
var link = $('<a>', {
|
|
|
|
|
href: url
|
|
|
|
|
});
|
|
|
|
|
this.cloneDataAttrs(widget, link);
|
|
|
|
|
widget.replaceWith(link);
|
|
|
|
|
this.widget = widget = link;
|
2014-01-15 12:27:09 +04:00
|
|
|
|
}
|
|
|
|
|
else {
|
2015-01-18 22:32:43 +03:00
|
|
|
|
widget.on('click', $.proxy(this.click, this));
|
2014-01-15 12:27:09 +04:00
|
|
|
|
}
|
2013-02-05 16:22:54 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
widget.removeClass(this.service);
|
|
|
|
|
widget.addClass(this.getElementClassNames('widget'));
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
// Icon
|
|
|
|
|
button.prepend($('<span>', {'class': this.getElementClassNames('icon')}));
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
widget.empty().append(button);
|
|
|
|
|
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
|
|
|
|
|
};
|
|
|
|
|
counters.fetch(this.service, this.options.url, extraOptions)
|
|
|
|
|
.always($.proxy(this.updateCounter, this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
cloneDataAttrs: function(source, destination) {
|
|
|
|
|
var data = source.data();
|
|
|
|
|
for (var key in data) {
|
|
|
|
|
if (data.hasOwnProperty(key)) {
|
|
|
|
|
destination.data(key, data[key]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2014-01-14 10:48:32 +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) {
|
2015-01-19 11:28:01 +03:00
|
|
|
|
if (typeof number === 'string') {
|
|
|
|
|
number = number.replace(/\D/g, '');
|
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
number = parseInt(number, 10) || 0;
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
var params = {
|
|
|
|
|
'class': this.getElementClassNames('counter'),
|
2014-04-11 16:37:26 +04:00
|
|
|
|
'text': number
|
2014-04-04 17:00:38 +04:00
|
|
|
|
};
|
|
|
|
|
if (!number && !this.options.zeroes) {
|
|
|
|
|
params['class'] += ' ' + prefix + '__counter_empty';
|
|
|
|
|
params.text = '';
|
2014-02-04 12:50:52 +04:00
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
var counterElem = $('<span>', params);
|
|
|
|
|
this.widget.append(counterElem);
|
|
|
|
|
|
|
|
|
|
this.widget.trigger('counter.' + prefix, [this.service, number]);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
click: function(e) {
|
|
|
|
|
var options = this.options;
|
|
|
|
|
var process = true;
|
|
|
|
|
if ($.isFunction(options.click)) {
|
|
|
|
|
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,
|
|
|
|
|
title: options.title
|
|
|
|
|
});
|
|
|
|
|
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) {
|
|
|
|
|
var params = $.param($.extend(this.widget.data(), this.options.data));
|
|
|
|
|
if ($.isEmptyObject(params)) return url;
|
|
|
|
|
var glue = url.indexOf('?') === -1 ? '?' : '&';
|
|
|
|
|
return url + glue + params;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
this.widget.trigger('popup_opened.' + prefix, [this.service, win]);
|
|
|
|
|
var timer = setInterval($.proxy(function() {
|
|
|
|
|
if (!win.closed) return;
|
|
|
|
|
clearInterval(timer);
|
|
|
|
|
this.widget.trigger('popup_closed.' + prefix, this.service);
|
|
|
|
|
}, this), this.options.popupCheckInterval);
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
// Camelize data-attributes
|
|
|
|
|
function dataToOptions(elem) {
|
|
|
|
|
function upper(m, l) {
|
|
|
|
|
return l.toUpper();
|
2013-10-29 21:35:33 +04:00
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
var options = {};
|
|
|
|
|
var data = elem.data();
|
|
|
|
|
for (var key in data) {
|
|
|
|
|
var value = data[key];
|
|
|
|
|
if (value === 'yes') value = true;
|
|
|
|
|
else if (value === 'no') value = false;
|
|
|
|
|
options[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
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
function closeOnClick(elem, callback) {
|
|
|
|
|
function handler(e) {
|
|
|
|
|
if ((e.type === 'keydown' && e.which !== 27) || $(e.target).closest(elem).length) return;
|
|
|
|
|
elem.removeClass(openClass);
|
|
|
|
|
doc.off(events, handler);
|
|
|
|
|
if ($.isFunction(callback)) callback();
|
|
|
|
|
}
|
|
|
|
|
var doc = $(document);
|
|
|
|
|
var events = 'click touchstart keydown';
|
|
|
|
|
doc.on(events, handler);
|
2012-11-20 23:56:23 +04:00
|
|
|
|
}
|
2014-04-04 17:00:38 +04:00
|
|
|
|
|
|
|
|
|
function showInViewport(elem) {
|
|
|
|
|
var offset = 10;
|
|
|
|
|
if (document.documentElement.getBoundingClientRect) {
|
|
|
|
|
var left = parseInt(elem.css('left'), 10);
|
|
|
|
|
var top = parseInt(elem.css('top'), 10);
|
|
|
|
|
|
|
|
|
|
var rect = elem[0].getBoundingClientRect();
|
|
|
|
|
if (rect.left < offset)
|
|
|
|
|
elem.css('left', offset - rect.left + left);
|
|
|
|
|
else if (rect.right > window.innerWidth - offset)
|
|
|
|
|
elem.css('left', window.innerWidth - rect.right - offset + left);
|
|
|
|
|
|
|
|
|
|
if (rect.top < offset)
|
|
|
|
|
elem.css('top', offset - rect.top + top);
|
|
|
|
|
else if (rect.bottom > window.innerHeight - offset)
|
|
|
|
|
elem.css('top', window.innerHeight - rect.bottom - offset + top);
|
|
|
|
|
}
|
|
|
|
|
elem.addClass(openClass);
|
2012-06-14 11:26:25 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2014-04-04 17:00:38 +04:00
|
|
|
|
/**
|
|
|
|
|
* Auto initialization
|
|
|
|
|
*/
|
|
|
|
|
$(function() {
|
|
|
|
|
$('.' + prefix).socialLikes();
|
|
|
|
|
});
|
2012-06-14 11:26:25 +04:00
|
|
|
|
|
2013-01-18 01:46:24 +04:00
|
|
|
|
}));
|