* @license MIT
*
* @example
*
* socialShare('.share-components');
*
* // or
*
* socialShare('.share-bar', {
* sites: ['qzone', 'qq', 'weibo','wechat'],
* // ...
* });
*
*/
;(function (window, document, undefined) {
// Initialize a variables.
var Array$indexOf = Array.prototype.indexOf;
var Object$assign = Object.assign;
var runningInWeChat = /MicroMessenger/i.test(navigator.userAgent);
var ismobilesScreen = document.documentElement.clientWidth <= 768;
var image = (document.images[0] || 0).src || '';
var site = getMetaContentByName('site') || getMetaContentByName('Site') || document.title;
var title = getMetaContentByName('title') || getMetaContentByName('Title') || document.title;
var description = getMetaContentByName('description') || getMetaContentByName('Description') || '';
var defaults = {
url: location.href,
origin: location.origin,
source: site,
title: title,
description: description,
image: image,
imageSelector: undefined,
weiboKey: '',
wechatQrcodeTitle: '微信扫一扫:分享',
wechatQrcodeHelper: '微信里点“发现”,扫一下
二维码便可将本文分享至朋友圈。
',
wechatQrcodeSize: 100,
sites: ['weibo', 'qq', 'wechat', 'douban', 'qzone', 'linkedin', 'facebook', 'twitter', 'google'],
mobilesSites: [],
disabled: [],
initialized: false
};
var templates = {
qzone: 'http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url={{URL}}&title={{TITLE}}&desc={{DESCRIPTION}}&summary={{SUMMARY}}&site={{SOURCE}}&pics={{IMAGE}}',
qq: 'http://connect.qq.com/widget/shareqq/index.html?url={{URL}}&title={{TITLE}}&source={{SOURCE}}&desc={{DESCRIPTION}}&pics={{IMAGE}}&summary="{{SUMMARY}}"',
weibo: 'https://service.weibo.com/share/share.php?url={{URL}}&title={{TITLE}}&pic={{IMAGE}}&appkey={{WEIBOKEY}}',
wechat: 'javascript:',
douban: 'http://shuo.douban.com/!service/share?href={{URL}}&name={{TITLE}}&text={{DESCRIPTION}}&image={{IMAGE}}&starid=0&aid=0&style=11',
linkedin: 'http://www.linkedin.com/shareArticle?mini=true&ro=true&title={{TITLE}}&url={{URL}}&summary={{SUMMARY}}&source={{SOURCE}}&armin=armin',
facebook: 'https://www.facebook.com/sharer/sharer.php?u={{URL}}',
twitter: 'https://twitter.com/intent/tweet?text={{TITLE}}&url={{URL}}&via={{ORIGIN}}',
google: 'https://plus.google.com/share?url={{URL}}'
};
/**
* Expose API to the global
*
* @param {String|Element} elem
* @param {Object} options
*/
window.socialShare = function (elem, options) {
elem = typeof elem === 'string' ? querySelectorAlls(elem) : elem;
if (elem.length === undefined) {
elem = [elem];
}
each(elem, function (el) {
if (!el.initialized) {
share(el, options);
}
});
};
// Domready after initialization
alReady(function () {
socialShare('.social-share, .share-component');
});
/**
* Initialize a share bar.
*
* @param {Object} $options globals (optional).
*
* @return {Void}
*/
function share(elem, options) {
var data = mixin({}, defaults, options || {}, dataset(elem));
if (data.imageSelector) {
data.image = querySelectorAlls(data.imageSelector).map(function(item) {
return item.src;
}).join('||');
}
addClass(elem, 'share-component social-share');
createIcons(elem, data);
createWechat(elem, data);
elem.initialized = true;
}
/**
* Create site icons
*
* @param {Element} elem
* @param {Object} data
*/
function createIcons(elem, data) {
var sites = getSites(data);
var isPrepend = data.mode == 'prepend';
each(isPrepend ? sites.reverse() : sites, function (name) {
var url = makeUrl(name, data);
var link = data.initialized ? getElementsByClassName(elem, 'icon-' + name) : createElementByString('');
if (!link.length) {
return true;
}
link[0].href = url;
if (name === 'wechat') {
link[0].tabindex = -1;
} else {
link[0].target = '_blank';
}
if (!data.initialized) {
isPrepend ? elem.insertBefore(link[0], elem.firstChild) : elem.appendChild(link[0]);
}
});
}
/**
* Create the wechat icon and QRCode.
*
* @param {Element} elem
* @param {Object} data
*/
function createWechat (elem, data) {
var wechat = getElementsByClassName(elem, 'icon-wechat', 'a');
if (wechat.length === 0) {
return false;
}
var elems = createElementByString('' + data.wechatQrcodeTitle + '
' + data.wechatQrcodeHelper + '
');
var qrcode = getElementsByClassName(elems[0], 'qrcode', 'div');
new QRCode(qrcode[0], {text: data.url, width: data.wechatQrcodeSize, height: data.wechatQrcodeSize});
wechat[0].appendChild(elems[0]);
}
/**
* Get available site lists.
*
* @param {Object} data
*
* @returns {Array}
*/
function getSites(data) {
if (!data['mobilesSites'].length) {
data['mobilesSites'] = data['sites'];
}
var sites = (ismobilesScreen ? data['mobilesSites'] : data['sites']).slice(0);
var disabled = data['disabled'];
if (typeof sites == 'string') {
sites = sites.split(/\s*,\s*/);
}
if (typeof disabled == 'string') {
disabled = disabled.split(/\s*,\s*/);
}
if (runningInWeChat) {
disabled.push('wechat');
}
// Remove elements
disabled.length && each(disabled, function (it) {
sites.splice(inArray(it, sites), 1);
});
return sites;
}
/**
* Build the url of icon.
*
* @param {String} name
* @param {Object} data
*
* @returns {String}
*/
function makeUrl(name, data) {
if (! data['summary']){
data['summary'] = data['description'];
}
return templates[name].replace(/\{\{(\w)(\w*)\}\}/g, function (m, fix, key) {
var nameKey = name + fix + key.toLowerCase();
key = (fix + key).toLowerCase();
return encodeURIComponent((data[nameKey] === undefined ? data[key] : data[nameKey]) || '');
});
}
/**
* Supports querySelectorAll, jQuery, Zepto and simple selector.
*
* @param str
*
* @returns {*}
*/
function querySelectorAlls(str) {
return (document.querySelectorAll || window.jQuery || window.Zepto || selector).call(document, str);
}
/**
* Simple selector.
*
* @param {String} str #ID or .CLASS
*
* @returns {Array}
*/
function selector(str) {
var elems = [];
each(str.split(/\s*,\s*/), function(s) {
var m = s.match(/([#.])(\w+)/);
if (m === null) {
throw Error('Supports only simple single #ID or .CLASS selector.');
}
if (m[1]) {
var elem = document.getElementById(m[2]);
if (elem) {
elems.push(elem);
}
}
elems = elems.concat(getElementsByClassName(str));
});
return elems;
}
/**
* Add the classNames for element.
*
* @param {Element} elem
* @param {String} value
*/
function addClass(elem, value) {
if (value && typeof value === "string") {
var classNames = (elem.className + ' ' + value).split(/\s+/);
var setClass = ' ';
each(classNames, function (className) {
if (setClass.indexOf(' ' + className + ' ') < 0) {
setClass += className + ' ';
}
});
elem.className = setClass.slice(1, -1);
}
}
/**
* Get meta element content value
*
* @param {String} name
*
* @returns {String|*}
*/
function getMetaContentByName(name) {
return (document.getElementsByName(name)[0] || 0).content;
}
/**
* Get elements By className for IE8-
*
* @param {Element} elem element
* @param {String} name className
* @param {String} tag tagName
*
* @returns {HTMLCollection|Array}
*/
function getElementsByClassName(elem, name, tag) {
if (elem.getElementsByClassName) {
return elem.getElementsByClassName(name);
}
var elements = [];
var elems = elem.getElementsByTagName(tag || '*');
name = ' ' + name + ' ';
each(elems, function (elem) {
if ((' ' + (elem.className || '') + ' ').indexOf(name) >= 0) {
elements.push(elem);
}
});
return elements;
}
/**
* Create element by string.
*
* @param {String} str
*
* @returns {NodeList}
*/
function createElementByString(str) {
var div = document.createElement('div');
div.innerHTML = str;
return div.childNodes;
}
/**
* Merge objects.
*
* @returns {Object}
*/
function mixin() {
var args = arguments;
if (Object$assign) {
return Object$assign.apply(null, args);
}
var target = {};
each(args, function (it) {
each(it, function (v, k) {
target[k] = v;
});
});
return args[0] = target;
}
/**
* Get dataset object.
*
* @param {Element} elem
*
* @returns {Object}
*/
function dataset(elem) {
if (elem.dataset) {
return JSON.parse(JSON.stringify(elem.dataset));
}
var target = {};
if (elem.hasAttributes()) {
each(elem.attributes, function (attr) {
var name = attr.name;
if (name.indexOf('data-') !== 0) {
return true;
}
name = name.replace(/^data-/i, '')
.replace(/-(\w)/g, function (all, letter) {
return letter.toUpperCase();
});
target[name] = attr.value;
});
return target;
}
return {};
}
/**
* found element in the array.
*
* @param {Array|Object} elem
* @param {Array} arr
* @param {Number} i
*
* @returns {Number}
*/
function inArray(elem, arr, i) {
var len;
if (arr) {
if (Array$indexOf) {
return Array$indexOf.call(arr, elem, i);
}
len = arr.length;
i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
for (; i < len; i++) {
// Skip accessing in sparse arrays
if (i in arr && arr[i] === elem) {
return i;
}
}
}
return -1;
}
/**
* Simple each.
*
* @param {Array|Object} obj
* @param {Function} callback
*
* @returns {*}
*/
function each(obj, callback) {
var length = obj.length;
if (length === undefined) {
for (var name in obj) {
if (obj.hasOwnProperty(name)) {
if (callback.call(obj[name], obj[name], name) === false) {
break;
}
}
}
} else {
for (var i = 0; i < length; i++) {
if (callback.call(obj[i], obj[i], i) === false) {
break;
}
}
}
}
/**
* Dom ready.
*
* @param {Function} fn
*
* @link https://github.com/jed/alReady.js
*/
function alReady ( fn ) {
var add = 'addEventListener';
var pre = document[ add ] ? '' : 'on';
~document.readyState.indexOf( 'm' ) ? fn() :
'load DOMContentLoaded readystatechange'.replace( /\w+/g, function( type, i ) {
( i ? document : window )
[ pre ? 'attachEvent' : add ]
(
pre + type,
function(){ if ( fn ) if ( i < 6 || ~document.readyState.indexOf( 'm' ) ) fn(), fn = 0 },
!1
)
})
}
})(window, document);