11// Code related to parsing and showing webmentions
2+ // And Share button
23
34// Gets the webmentions json data from current URL
45async function getWebmentions ( targetURL ) {
@@ -51,17 +52,23 @@ function setReactionsLabel(length, reactionLabel) {
5152
5253 // Singular
5354 if ( plural_rules . select ( length ) === "one" ) {
54- reactionLabel . textContent = reactionLabel . getAttribute ( "data- singular" ) ;
55+ reactionLabel . textContent = reactionLabel . dataset . singular ;
5556 return ;
5657 }
5758
5859 // Few - alternative plural (Used by "ru" and "uk")
59- if ( reactionLabel . getAttribute ( "data-plural-alt" ) !== "" && plural_rules . select ( length ) === "few" ) {
60- reactionLabel . textContent = reactionLabel . getAttribute ( "data-plural-alt" ) ;
61- return ;
60+ if ( reactionLabel . dataset . plural_alt !== "" && plural_rules . select ( length ) === "few" ) {
61+ reactionLabel . textContent = reactionLabel . dataset . plural_alt ;
62+ return ;
63+ }
64+
65+ // If a plural exists use that.
66+ if ( reactionLabel . dataset . plural ) {
67+ reactionLabel . textContent = reactionLabel . dataset . plural ;
68+ return ;
6269 }
6370
64- // Everything else sticks with the default plural
71+ // Everything else sticks with the default
6572 return ;
6673
6774}
@@ -174,7 +181,7 @@ function renderReactions(webmentions, reactionType, wmProperty) {
174181 const reactionASource = document . createElement ( "a" ) ;
175182 reactionASource . setAttribute ( "class" , "webmention-source" ) ;
176183 reactionASource . setAttribute ( "href" , reaction [ "url" ] ) ;
177- reactionASource . textContent = document . querySelector ( ".reactions" ) . getAttribute ( "data- source" ) ;
184+ reactionASource . textContent = document . querySelector ( ".reactions" ) . dataset . source ;
178185
179186 reactionDivMeta . appendChild ( reactionTime ) ;
180187 reactionDivMeta . appendChild ( reactionSpan ) ;
@@ -212,7 +219,12 @@ function setActiveTab() {
212219
213220// Parses and renders mentions into likes, reposts, replies and mentions
214221function renderWebmentions ( webmentions ) {
222+ if ( ! document . querySelector ( '.webmentions-cta' ) ) {
223+ return ;
224+ }
225+
215226 if ( ! webmentions . length ) {
227+ document . querySelector ( '#cta-container' ) . classList . remove ( 'invisible' ) ;
216228 return ;
217229 }
218230
@@ -221,6 +233,14 @@ function renderWebmentions(webmentions) {
221233 renderReactions ( webmentions , "replies" , "in-reply-to" ) ;
222234 renderReactions ( webmentions , "mentions" , "mention-of" ) ;
223235
236+ // Show count of reactions (except if 0)
237+ if ( webmentions . length > 0 ) {
238+ document . querySelectorAll ( '.num-reactions' ) . forEach ( t => t . innerText = webmentions . length ) ;
239+ document . querySelectorAll ( '.reactions-label' ) . forEach ( t => setReactionsLabel ( webmentions . length , t ) ) ;
240+ document . querySelector ( '.webmentions-cta' ) . classList . remove ( 'hidden' ) ;
241+ }
242+ document . querySelector ( '#cta-container' ) . classList . remove ( 'invisible' ) ;
243+
224244 // Set the first active tab (in case no "likes" so that tab is hidden)
225245 setActiveTab ( ) ;
226246}
@@ -301,6 +321,63 @@ function addTabListeners() {
301321}
302322
303323
324+ // Change tabs for webmentions UI
325+ function handleShareButton ( ) {
326+ // DOM references
327+ const button = document . querySelector ( '.share-cta' ) ;
328+ const appleIcon = button . querySelector ( '.apple-icon' ) ;
329+ const androidIcon = button . querySelector ( '.android-icon' ) ;
330+ const canonical = document . querySelector ( 'link[rel="canonical"]' ) ;
331+
332+ // Feature detection to see if the Web Share API is supported.
333+ if ( ! ( 'share' in navigator ) ) {
334+ return ;
335+ }
336+
337+ // Find out if the user is on a device made by Apple and, if so, switch the icon.
338+ if ( / M a c | i P h o n e / . test ( navigator . platform ) ) {
339+ appleIcon . classList . remove ( 'hidden' ) ;
340+ androidIcon . classList . add ( 'hidden' ) ;
341+ }
342+
343+ button . addEventListener ( 'click' , async ( ) => {
344+ // Title and text are identical, since the title may actually be ignored.
345+ const title = document . title ;
346+ const text = document . title ;
347+ // Use the canonical URL, if it exists, else, the current location.
348+ const url = canonical ?. href || location . href ;
349+
350+ gtag ( 'event' , 'WebShare' , {
351+ 'event_category' : 'clicks' ,
352+ 'event_label' : url ,
353+ 'transport_type' : 'beacon' ,
354+ 'value' : 1
355+ } )
356+
357+ try {
358+ await navigator . share ( {
359+ url,
360+ text,
361+ title,
362+ } ) ;
363+ return ;
364+ } catch ( err ) {
365+ // If the user cancels, an `AbortError` is thrown.
366+ if ( err . name !== "AbortError" ) {
367+ console . error ( err . name , err . message ) ;
368+ gtag ( 'event' , 'error' , {
369+ 'event_category' : 'WebShare' ,
370+ 'event_label' : err . message ,
371+ 'transport_type' : 'beacon' ,
372+ 'value' : 1
373+ } )
374+ }
375+ }
376+ } ) ;
377+ button . classList . remove ( 'hidden' ) ;
378+ }
379+
380+ handleShareButton ( ) ;
304381addTabListeners ( ) ;
305382const BASE_URL = "https://almanac.httparchive.org" ;
306383processWebmentions ( BASE_URL + window . location . pathname ) ;
0 commit comments