vue-social-sharing
Version:
A Vue.js component for sharing links to social networks
282 lines (248 loc) • 7.07 kB
JavaScript
import SocialSharingNetwork from './social-sharing-network';
import BaseNetworks from './networks.json';
import Vue from 'vue';
const inBrowser = typeof window !== 'undefined';
var $window = inBrowser ? window : null;
export function mockWindow (self) {
$window = self || window; // mock window for unit testing
}
export default {
props: {
/**
* URL to share.
* @var string
*/
url: {
type: String,
default: inBrowser ? window.location.href : ''
},
/**
* Sharing title, if available by network.
* @var string
*/
title: {
type: String,
default: ''
},
/**
* Sharing description, if available by network.
* @var string
*/
description: {
type: String,
default: ''
},
/**
* Facebook quote
* @var string
*/
quote: {
type: String,
default: ''
},
/**
* Twitter hashtags
* @var string
*/
hashtags: {
type: String,
default: ''
},
/**
* Twitter user.
* @var string
*/
twitterUser: {
type: String,
default: ''
},
/**
* Flag that indicates if counts should be retrieved.
* - NOT WORKING IN CURRENT VERSION
* @var mixed
*/
withCounts: {
type: [String, Boolean],
default: false
},
/**
* Google plus key.
* @var string
*/
googleKey: {
type: String,
default: undefined
},
/**
* Pinterest Media URL.
* Specifies the image/media to be used.
*/
media: {
type: String,
default: ''
},
/**
* Network sub component tag.
* Default to span tag
*/
networkTag: {
type: String,
default: 'span'
},
/**
* Additional or overridden networks.
* Default to BaseNetworks
*/
networks: {
type: Object,
default: function () {
return {};
}
}
},
data () {
return {
/**
* Available sharing networks.
* @param object
*/
baseNetworks: BaseNetworks,
/**
* Popup settings.
* @param object
*/
popup: {
status: false,
resizable: true,
toolbar: false,
menubar: false,
scrollbars: false,
location: false,
directories: false,
width: 626,
height: 436,
top: 0,
left: 0,
window: undefined,
interval: null
}
};
},
methods: {
/**
* Returns generated sharer url.
*
* @param network Social network key.
*/
createSharingUrl (network) {
return this.baseNetworks[network].sharer
.replace(/ /g, encodeURIComponent(this.url))
.replace(/ /g, encodeURIComponent(this.title))
.replace(/ /g, encodeURIComponent(this.description))
.replace(/ /g, encodeURIComponent(this.quote))
.replace(/ /g, this.encodeFacebookHashtags(network, this.hashtags))
.replace(/ /g, this.media)
.replace(/ /g, this.twitterUser ? '&via=' + this.twitterUser : '');
},
/**
* encode hash tag for facebook url
* @param network to check if the current network is facebbok
* @param hashtags all hashtags specified
* @return encoded hashtag [only the first one because of facebook policy]
*/
encodeFacebookHashtags (network, hashtags) {
return network === 'facebook' ? '%23' + hashtags : hashtags;
},
/**
* Shares URL in specified network.
*
* @param string network Social network key.
*/
share (network) {
this.openSharer(network, this.createSharingUrl(network));
this.$root.$emit('social_shares_open', network, this.url);
this.$emit('open', network, this.url);
},
/**
* Touches network and emits click event.
*
* @param string network Social network key.
*/
touch (network) {
window.open(this.createSharingUrl(network), '_self');
this.$root.$emit('social_shares_open', network, this.url);
this.$emit('open', network, this.url);
},
/**
* Opens sharer popup.
*
* @param string url Url to share.
*/
openSharer (network, url) {
// If a popup window already exist it will be replaced, trigger a close event.
if (this.popup.window && this.popup.interval) {
clearInterval(this.popup.interval);
this.popup.window.close();// Force close (for Facebook)
this.$root.$emit('social_shares_change', network, this.url);
this.$emit('change', network, this.url);
}
this.popup.window = window.open(
url,
'sharer',
'status=' + (this.popup.status ? 'yes' : 'no') +
',height=' + this.popup.height +
',width=' + this.popup.width +
',resizable=' + (this.popup.resizable ? 'yes' : 'no') +
',left=' + this.popup.left +
',top=' + this.popup.top +
',screenX=' + this.popup.left +
',screenY=' + this.popup.top +
',toolbar=' + (this.popup.toolbar ? 'yes' : 'no') +
',menubar=' + (this.popup.menubar ? 'yes' : 'no') +
',scrollbars=' + (this.popup.scrollbars ? 'yes' : 'no') +
',location=' + (this.popup.location ? 'yes' : 'no') +
',directories=' + (this.popup.directories ? 'yes' : 'no')
);
this.popup.window.focus();
// Create an interval to detect popup closing event
this.popup.interval = setInterval(() => {
if (this.popup.window.closed) {
clearInterval(this.popup.interval);
this.popup.window = undefined;
this.$root.$emit('social_shares_close', network, this.url);
this.$emit('close', network, this.url);
}
}, 500);
}
},
/**
* Merge base networks list with user's list
*/
beforeMount () {
this.baseNetworks = Vue.util.extend(this.baseNetworks, this.networks);
},
/**
* Sets popup default dimensions.
*/
mounted () {
if (!inBrowser) {
return;
}
/**
* Center the popup on dual screens
* http://stackoverflow.com/questions/4068373/center-a-popup-window-on-screen/32261263
*/
const dualScreenLeft = $window.screenLeft !== undefined ? $window.screenLeft : screen.left;
const dualScreenTop = $window.screenTop !== undefined ? $window.screenTop : screen.top;
const width = $window.innerWidth ? $window.innerWidth : (document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width);
const height = $window.innerHeight ? $window.innerHeight : (document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height);
this.popup.left = ((width / 2) - (this.popup.width / 2)) + dualScreenLeft;
this.popup.top = ((height / 2) - (this.popup.height / 2)) + dualScreenTop;
},
/**
* Set component aliases for buttons and links.
*/
components: {
'network': SocialSharingNetwork
}
};