From 75df6f42097da1a7efe4a5a5be0ebe20ae89164e Mon Sep 17 00:00:00 2001 From: goldpbear <tcroxson@gmail.com> Date: Thu, 30 Mar 2017 20:50:41 -0700 Subject: [PATCH] Accommodate variable dataset slugs in social media sharing functionality --- .../place-detail-promotion-bar.html | 4 +- src/base/static/js/handlebars-helpers.js | 8 --- src/base/static/js/routes.js | 1 + src/base/static/js/utils.js | 61 +++++++++++++++++++ src/base/static/js/views/place-detail-view.js | 12 +++- src/base/static/js/views/place-list-view.js | 10 +++ src/base/static/scss/_content.scss | 18 +++--- src/base/templates/base.html | 1 + src/flavors/duwamish_flavor/config.yml | 3 + .../duwamish_flavor/templates/index.html | 48 +++++---------- 10 files changed, 111 insertions(+), 55 deletions(-) diff --git a/src/base/jstemplates/place-detail-promotion-bar.html b/src/base/jstemplates/place-detail-promotion-bar.html index cc5d3fc70b..ba25552d26 100644 --- a/src/base/jstemplates/place-detail-promotion-bar.html +++ b/src/base/jstemplates/place-detail-promotion-bar.html @@ -2,8 +2,8 @@ <div class="support {{#if story}}single-line{{/if}}"></div> <div class="social {{#if story}}single-line{{/if}}"> <ul class="sharing unstyled-list"> - <li class="share-link share-twitter"><a href="https://twitter.com/intent/tweet?url={{ place_url id }}&text={{ name }}" target="_blank" data-shareto="twitter">{{#_}}Tweet This{{/_}}</a></li> - <li class="share-link share-facebook"><a href="https://www.facebook.com/sharer/sharer.php?u={{ place_url id }}" target="_blank" data-shareto="facebook">{{#_}}Recommend on Facebook{{/_}}</a></li> + <li class="share-link share-twitter">{{#_}}Tweet This{{/_}}</li> + <li class="share-link share-facebook">{{#_}}Recommend on Facebook{{/_}}</li> </ul> </div> </section> diff --git a/src/base/static/js/handlebars-helpers.js b/src/base/static/js/handlebars-helpers.js index b10aa6587e..11134b4bd0 100644 --- a/src/base/static/js/handlebars-helpers.js +++ b/src/base/static/js/handlebars-helpers.js @@ -253,14 +253,6 @@ return result; }); - Handlebars.registerHelper('place_url', function(place_id) { - var l = window.location, - protocol = l.protocol, - host = l.host; - - return [protocol, '//', host, '/place/', place_id].join(''); - }); - // Get the current url Handlebars.registerHelper('windowLocation', function(place_id) { return window.location; diff --git a/src/base/static/js/routes.js b/src/base/static/js/routes.js index f76bfd8893..2e580372a1 100644 --- a/src/base/static/js/routes.js +++ b/src/base/static/js/routes.js @@ -106,6 +106,7 @@ Shareabouts.Util = Util; this.appView = new AppView({ el: 'body', + appConfig: options.appConfig, activities: this.activities, places: this.places, landmarks: this.landmarks, diff --git a/src/base/static/js/utils.js b/src/base/static/js/utils.js index 3188afad56..546be5725a 100644 --- a/src/base/static/js/utils.js +++ b/src/base/static/js/utils.js @@ -29,6 +29,67 @@ var self = module.exports = { } }, + // Given a model, update social media meta tags with the model's information, + // or generic information from the appConfig as a fallback. + updateSocialMetaTags: function(model, appConfig) { + var siteName = appConfig.title, + title = model.get("title") || + model.get("name") || + appConfig.title, + description = model.get("description") || + appConfig.meta_description, + imgSrc = (model.get("attachments").length > 0) ? + model.get("attachments")[0].file : + appConfig.thumbnail, + submitter = model.get("submitter"); + + // Twitter meta tags + $("meta[name='twitter:title']").attr("content", title); + $("meta[name='twitter:description']").attr("content", description); + $("meta[name='twitter:img:src']").attr("content", imgSrc); + $("meta[name='twitter:creator']").attr("content", submitter); + + // Facebook meta tags + $("meta[name='og:site_name']").attr("content", siteName); + $("meta[name='og:title']").attr("content", title); + $("meta[name='og:description']").attr("content", description); + $("meta[name='og:image']").attr("content", imgSrc); + + return title; + }, + + getPathname: function(model) { + if (model.get("url-title")) { + return model.get("url-title"); + } else if (model.get("datasetSlug")) { + return model.get("datasetSlug") + "/" + model.get("id"); + } else { + return model.get("id"); + } + }, + + onSocialShare: function(model, service) { + var appConfig = Shareabouts.Config.app, + title = this.updateSocialMetaTags(model, appConfig), + protocol = window.location.protocol, + host = window.location.host, + pathname = this.getPathname(model), + url = [protocol, "//", host, "/", pathname].join(""), + shareUrl; + + if (service === "twitter") { + shareUrl = ["https://twitter.com/intent/tweet?url=", + url, + "&text=", + title].join(""); + } else if (service === "facebook") { + shareUrl = ["https://www.facebook.com/sharer/sharer.php?u=", + url].join(""); + } + + window.open(shareUrl, "_blank"); + }, + // Given the information provided in a url (that is, an id and possibly a slug), // attempt to find the corresponding model within all collections on the page. // Three conditions are possible: diff --git a/src/base/static/js/views/place-detail-view.js b/src/base/static/js/views/place-detail-view.js index 295dd54e6f..dd1e8bc1cf 100644 --- a/src/base/static/js/views/place-detail-view.js +++ b/src/base/static/js/views/place-detail-view.js @@ -8,7 +8,9 @@ module.exports = Backbone.View.extend({ events: { 'click .place-story-bar .btn-previous-story-nav': 'onClickStoryPrevious', - 'click .place-story-bar .btn-next-story-nav': 'onClickStoryNext' + 'click .place-story-bar .btn-next-story-nav': 'onClickStoryNext', + 'click .share-twitter': 'onShareTwitter', + 'click .share-facebook': 'onShareFacebook' }, initialize: function() { var self = this; @@ -54,6 +56,14 @@ }); }, + onShareTwitter: function() { + Util.onSocialShare(this.model, "twitter"); + }, + + onShareFacebook: function() { + Util.onSocialShare(this.model, "facebook"); + }, + onClickStoryPrevious: function() { this.options.router.navigate(this.model.attributes.story.previous, {trigger: true}); }, diff --git a/src/base/static/js/views/place-list-view.js b/src/base/static/js/views/place-list-view.js index 066e83ca52..7c66a6b395 100644 --- a/src/base/static/js/views/place-list-view.js +++ b/src/base/static/js/views/place-list-view.js @@ -22,6 +22,10 @@ 'hide': 'hide', 'change': 'render' }, + events: { + 'click .share-twitter': 'onShareTwitter', + 'click .share-facebook': 'onShareFacebook' + }, initialize: function() { var supportType = Shareabouts.Config.support.submission_type; @@ -37,6 +41,12 @@ userToken: Shareabouts.Config.userToken }); }, + onShareTwitter: function() { + Util.onSocialShare(this.model, "twitter"); + }, + onShareFacebook: function() { + Util.onSocialShare(this.model, "facebook"); + }, onBeforeRender: function() { // if an attachmentCollection has models in it, make sure the place // model's attachment attribute is set for the attachments to be diff --git a/src/base/static/scss/_content.scss b/src/base/static/scss/_content.scss index ffcd399b5d..be6d0112cc 100644 --- a/src/base/static/scss/_content.scss +++ b/src/base/static/scss/_content.scss @@ -165,21 +165,19 @@ a.minimize-btn { float: right; padding: 0 !important; margin-left: 10px; - - a { - display: block; - width: 32px; - height: 32px; - overflow: hidden; - text-indent: -9999px; - } + display: block; + width: 32px; + height: 32px; + overflow: hidden; + text-indent: -9999px; + cursor: pointer; } -.share-twitter a { +.share-twitter { background: url(images/twitter-32.png) 0 0 no-repeat scroll; } -.share-facebook a { +.share-facebook { background: url(images/facebook-32.png) 0 0 no-repeat scroll; } diff --git a/src/base/templates/base.html b/src/base/templates/base.html index f3a2659969..ae0021909b 100644 --- a/src/base/templates/base.html +++ b/src/base/templates/base.html @@ -304,6 +304,7 @@ <h3> 'user:' + S.bootstrapped.currentUser.id : {{ user_token_json|safe }}), + app: {{ config.app|as_json }}, flavor: {{ config.data|as_json }}, place: {{ config.place|as_json }}, placeTypes: {{ config.place_types|as_json }}, diff --git a/src/flavors/duwamish_flavor/config.yml b/src/flavors/duwamish_flavor/config.yml index 82c849cb02..168b68207d 100644 --- a/src/flavors/duwamish_flavor/config.yml +++ b/src/flavors/duwamish_flavor/config.yml @@ -9,6 +9,9 @@ app: # Meta author that will show up in Google search results meta_author: SmarterCleanup.org + # Fallback image to use for sharing on social services if no model image is present + thumbnail: /static/css/images/fb-thumbnail.png + # When the map loads, existing places will be loaded in chunks. By default, # the size of the chunks will be a reasonable default dictated by the API # server. If you would like to override the chunk size, use this setting: diff --git a/src/flavors/duwamish_flavor/templates/index.html b/src/flavors/duwamish_flavor/templates/index.html index ae2b6a1bb0..9976f5c345 100644 --- a/src/flavors/duwamish_flavor/templates/index.html +++ b/src/flavors/duwamish_flavor/templates/index.html @@ -8,40 +8,20 @@ {% endblock %} {% block meta %} - {% if place %} - <!-- Twitter --> - <meta name="twitter:widgets:csp" content="on"> <!--- # Added by LMS for SSL compatibility ---> - <meta name="twitter:card" content="summary"> - <meta name="twitter:title" content="{{ place.properties.name }}"> - <meta name="twitter:description" content="{{ place.properties.description }}"> - {% with attachment=place.properties.attachments|first %} - <meta name="twitter:image:src" content="{{ attachment.file }}"> - {% endwith %} - {% comment %} TODO: Fill this in when we know if the username is from twitter - <meta name="twitter:creator" content="place.submitter.username"> - {% endcomment %} - - <!-- Facebook --> - <meta property="og:site_name" content="{{ config.app.title }}" /> - <meta property="og:title" content="{{ place.properties.name }}" /> - <meta property="og:description" content="{{ place.properties.description }}" /> - {% with attachment=place.properties.attachments|first %} - <meta name="og:image" content="{{ attachment.file }}"> - {% endwith %} - {% else %} - <!-- Twitter --> - <meta name="twitter:card" content="summary"> - <meta name="twitter:title" content="{{ config.app.title }}"> - <meta name="twitter:description" content="{{ config.app.meta_description }}"> - <meta name="twitter:widgets:csp" content="on"> <!--- # Added by LMS for SSL compatibility ---> - - <!-- Facebook --> - <meta property="og:site_name" content="{{ config.app.title }}" /> - <meta property="og:title" content="{{ config.app.title }}" /> - <meta property="og:description" content="{{ config.app.meta_description }}" /> - <meta name="og:image" content="{{STATIC_URL}}css/images/fb-thumbnail.png"> - - {% endif%} + <!-- NOTE: social meta tag content gets populated client-side. --> + <!-- Twitter --> + <meta name="twitter:card" content="summary"> + <meta name="twitter:widgets:csp" content="on"> + <meta name="twitter:title" content=""> + <meta name="twitter:description" content=""> + <meta name="twitter:image:src" content=""> + <meta name="twitter:creator" content=""> + + <!-- Facebook --> + <meta property="og:site_name" content="" /> + <meta property="og:title" content="" /> + <meta property="og:description" content="" /> + <meta name="og:image" content=""> {% endblock %} <!--