From d972da935a80de6ae96edf1f9b537c1287b82ef2 Mon Sep 17 00:00:00 2001 From: Brett Sun Date: Mon, 9 Nov 2015 17:46:49 +0100 Subject: [PATCH] Add Facebook Share button --- js/app.js | 1 + .../ascribe_detail/media_container.js | 3 ++ .../facebook_share_button.js | 52 +++++++++++++++++++ js/constants/application_constants.js | 4 ++ js/third_party/facebook.js | 30 +++++++++++ 5 files changed, 90 insertions(+) create mode 100644 js/components/ascribe_social_share/facebook_share_button.js create mode 100644 js/third_party/facebook.js diff --git a/js/app.js b/js/app.js index c9451e47..520bedbd 100644 --- a/js/app.js +++ b/js/app.js @@ -30,6 +30,7 @@ import GoogleAnalyticsHandler from './third_party/ga'; import RavenHandler from './third_party/raven'; import IntercomHandler from './third_party/intercom'; import NotificationsHandler from './third_party/notifications'; +import FacebookHandler from './third_party/facebook'; /* eslint-enable */ initLogging(); diff --git a/js/components/ascribe_detail/media_container.js b/js/components/ascribe_detail/media_container.js index 6ac2f745..9e5126bf 100644 --- a/js/components/ascribe_detail/media_container.js +++ b/js/components/ascribe_detail/media_container.js @@ -7,6 +7,8 @@ import Glyphicon from 'react-bootstrap/lib/Glyphicon'; import MediaPlayer from './../ascribe_media/media_player'; +import FacebookShareButton from '../ascribe_social_share/facebook_share_button'; + import CollapsibleButton from './../ascribe_collapsible/collapsible_button'; import AclProxy from '../acl_proxy'; @@ -95,6 +97,7 @@ let MediaContainer = React.createClass({ Download + {embed}

diff --git a/js/components/ascribe_social_share/facebook_share_button.js b/js/components/ascribe_social_share/facebook_share_button.js new file mode 100644 index 00000000..98350347 --- /dev/null +++ b/js/components/ascribe_social_share/facebook_share_button.js @@ -0,0 +1,52 @@ +'use strict'; + +import React from 'react'; + +import AppConstants from '../../constants/application_constants'; + +import { InjectInHeadUtils } from '../../utils/inject_utils'; + +let FacebookShareButton = React.createClass({ + propTypes: { + url: React.PropTypes.string, + type: React.PropTypes.string + }, + + getDefaultProps() { + return { + type: 'button' + }; + }, + + componentDidMount() { + /** + * Ideally we would only use FB.XFBML.parse() on the component that we're + * mounting, but doing this when we first load the FB sdk causes unpredictable behaviour. + * The button sometimes doesn't get initialized, likely because FB hasn't properly + * been initialized yet. + * + * To circumvent this, we always have the sdk parse the entire DOM on the initial load + * (see FacebookHandler) and then use FB.XFBML.parse() on the mounting component later. + */ + if (!InjectInHeadUtils.isPresent('script', AppConstants.facebook.sdkUrl)) { + InjectInHeadUtils.inject(AppConstants.facebook.sdkUrl); + } else { + // Parse() searches the children of the element we give it, not the element itself. + FB.XFBML.parse(this.refs.fbShareButton.getDOMNode().parentElement); + } + }, + + render() { + return ( + + + ); + } +}); + +export default FacebookShareButton; diff --git a/js/constants/application_constants.js b/js/constants/application_constants.js index 0fe5e210..b86bb594 100644 --- a/js/constants/application_constants.js +++ b/js/constants/application_constants.js @@ -75,6 +75,10 @@ let constants = { 'raven': { 'url': 'https://0955da3388c64ab29bd32c2a429f9ef4@app.getsentry.com/48351' }, + 'facebook': { + 'appId': '420813844732240', + 'sdkUrl': '//connect.facebook.net/en_US/sdk.js' + }, 'copyrightAssociations': ['ARS', 'DACS', 'Bildkunst', 'Pictoright', 'SODRAC', 'Copyright Agency/Viscopy', 'SAVA', 'Bildrecht GmbH', 'SABAM', 'AUTVIS', 'CREAIMAGEN', 'SONECA', 'Copydan', 'EAU', 'Kuvasto', 'GCA', 'HUNGART', 'IVARO', 'SIAE', 'JASPAR-SPDA', 'AKKA/LAA', 'LATGA-A', 'SOMAAP', 'ARTEGESTION', 'CARIER', 'BONO', 'APSAV', diff --git a/js/third_party/facebook.js b/js/third_party/facebook.js new file mode 100644 index 00000000..eab0b0e0 --- /dev/null +++ b/js/third_party/facebook.js @@ -0,0 +1,30 @@ +'use strict'; + +import { altThirdParty } from '../alt'; +import EventActions from '../actions/event_actions'; + +import AppConstants from '../constants/application_constants' + +class FacebookHandler { + constructor() { + this.bindActions(EventActions); + } + + onApplicationWillBoot(settings) { + // Callback function that FB's sdk will call when it's finished loading + // See https://developers.facebook.com/docs/javascript/quickstart/v2.5 + window.fbAsyncInit = () => { + FB.init({ + appId: AppConstants.facebook.appId, + // Force FB to parse everything on first load to make sure all the XFBML components are initialized. + // If we don't do this, we can run into issues with components on the first load who are not be + // initialized. + xfbml: true, + version: 'v2.5', + cookie: false + }); + }; + } +} + +export default altThirdParty.createStore(FacebookHandler, 'FacebookHandler');