PageSourceSearch

https://www.loria.fr/wp-content/plugins/simple-share-buttons-adder/js/ssba.js?ver=1787302895

js loria.fr collected 2026-09-24 08:27:22 UTC 6,142 bytes, 241 lines download raw bytes

1/**
2 * Main.
3 *
4 * @package SimpleShareButtonsAdder
5 */
6
7/* exported Main */
8var Main = ( function( $, FB ) {
9	'use strict';
10
11	// These open a chat prefilled with a prompt in a new tab, not a share popup.
12	var aiSites = [ 'chatgpt', 'claude', 'grok', 'perplexity' ];
13
14	// These take no prompt in the URL, so it is copied to the clipboard instead.
15	var aiCopySites = [ 'copilot', 'gemini' ];
16
17	// Shown when the prompt travels over the clipboard, and how long to hold the tab.
18	var AI_COPY_MESSAGE = 'Prompt copied — paste it into the chat';
19	var AI_COPY_DELAY = 600;
20
21	// How long the copy notice sits above the button, its fade, and its screen gutter.
22	var COPY_NOTICE_HOLD = 1800;
23	var COPY_NOTICE_FADE = 400;
24	var COPY_NOTICE_MARGIN = 8;
25
26	return {
27		/**
28		 * Holds data.
29		 */
30		data: {},
31
32		/**
33		 * Boot plugin.
34		 *
35		 * @param data
36		 */
37		boot: function( data ) {
38			this.data = data;
39
40			$( document ).ready(
41				function() {
42					this.init();
43				}.bind( this )
44			);
45		},
46
47		/**
48		 * Initialize plugin.
49		 */
50		init: function() {
51			this.listen();
52			this.removeP();
53		},
54
55		/**
56		 * Listener event.
57		 */
58		listen: function() {
59			var self = this;
60
61			// Upon clicking a share button.
62			$( 'body' ).on(
63				'click',
64				'.ssbp-wrap a',
65				function( event ) {
66
67					// Don't go the the href yet.
68					event.preventDefault();
69					self.engageShareButton( this );
70				}
71			);
72		},
73
74		/**
75		 * Open an AI assistant in a new tab rather than a popup.
76		 *
77		 * @param url
78		 */
79		openAiTab: function( url ) {
80			var tab = window.open( url, '_blank' );
81
82			if ( tab ) {
83				tab.opener = null;
84			}
85		},
86
87		/**
88		 * Copy text to the clipboard.
89		 *
90		 * Fire and forget, so the caller stays inside the click gesture.
91		 *
92		 * @param text
93		 */
94		copyToClipboard: function( text ) {
95			if ( ! text ) {
96				return;
97			}
98
99			if ( navigator.clipboard && navigator.clipboard.writeText ) {
100				navigator.clipboard.writeText( text );
101				return;
102			}
103
104			// Fallback for browsers without the async clipboard API.
105			var field   = document.createElement( 'textarea' );
106			field.value          = text;
107			field.setAttribute( 'readonly', '' );
108			field.style.position = 'fixed';
109			field.style.left     = '-9999px';
110			document.body.appendChild( field );
111			field.select();
112
113			try {
114				document.execCommand( 'copy' );
115			} catch ( error ) {
116			}
117
118			field.parentNode.removeChild( field );
119		},
120
121		/**
122		 * Show a transient message above a share button.
123		 *
124		 * The notice is anchored to the top edge of the button so it never covers
125		 * the icon, and is nudged back inside the viewport when it would spill out.
126		 *
127		 * @param event
128		 * @param message
129		 */
130		showCopyNotice: function( event, message ) {
131			var button = $( event ).get( 0 );
132
133			if ( ! button ) {
134				return;
135			}
136
137			// The notice is positioned against the button, so the button has to be
138			// a containing block. Themes leave these links statically positioned.
139			if ( 'static' === window.getComputedStyle( button ).position ) {
140				button.style.position = 'relative';
141			}
142
143			var notice       = document.createElement( 'span' );
144			notice.innerText = message;
145			notice.className = 'copy-notify ssba-copy-notify';
146			button.appendChild( notice );
147
148			// Pull the notice back on screen if centring pushed it past an edge.
149			var bounds = notice.getBoundingClientRect();
150			var overflowLeft  = COPY_NOTICE_MARGIN - bounds.left;
151			var overflowRight = bounds.right - ( document.documentElement.clientWidth - COPY_NOTICE_MARGIN );
152
153			if ( 0 < overflowLeft ) {
154				notice.style.marginLeft = Math.round( overflowLeft ) + 'px';
155			} else if ( 0 < overflowRight ) {
156				notice.style.marginLeft = '-' + Math.round( overflowRight ) + 'px';
157			}
158
159			window.setTimeout(
160				function() {
161					notice.className += ' ssba-copy-notify--hiding';
162
163					window.setTimeout(
164						function() {
165							if ( notice.parentNode ) {
166								notice.parentNode.removeChild( notice );
167							}
168						},
169						COPY_NOTICE_FADE
170					);
171				},
172				COPY_NOTICE_HOLD
173			);
174		},
175
176		/**
177		 * Share button popup
178		 *
179		 * @param event
180		 */
181		engageShareButton: function( event ) {
182
183			// If it's facebook mobile.
184			if ( 'mobile' === $( event ).data( 'facebook' ) ) {
185				FB.ui(
186					{
187						method: 'share',
188						mobile_iframe: true,
189						href: $( event ).data( 'href' )
190					},
191					function( response ) {}
192				);
193			} else if ( -1 !== aiSites.indexOf( $( event ).data( 'site' ) ) ) {
194
195				// AI assistants open a chat in a new tab rather than a popup.
196				this.openAiTab( $( event ).attr( 'href' ) );
197			} else if ( -1 !== aiCopySites.indexOf( $( event ).data( 'site' ) ) ) {
198
199				// These take no prompt in the URL, so hand it over the clipboard.
200				this.copyToClipboard( $( event ).data( 'prompt' ) || '' );
201				this.showCopyNotice( event, AI_COPY_MESSAGE );
202
203				// Let the notice land before the new tab takes focus. The delay 
203stays
204				// well inside the user-activation window, so the tab is not blocked.
205				setTimeout( this.openAiTab.bind( this, $( event ).attr( 'href' ) ), AI_COPY_DELAY );
206			} else {
207				// These share options don't need to have a popup.
208				if ( 'copy' === $( event ).data( 'site' ) || 'email' === $( event ).data( 'site' ) || 'print' === $( event ).data( 'site' ) || 'pinterest' === $( event ).data( 'site' ) ) {
209					if ( 'copy' === $( event ).data( 'site' ) ) {
210						this.copyToClipboard( $( event ).attr( 'href' ) );
211						this.showCopyNotice( event, 'URL Copied!' );
212					} else {
213						// Just redirect.
214						window.location.href = $( event ).attr( 'href' );
215					}
216				} else {
217
218					// Prepare popup window.
219					var width  = 575,
220						height = 520,
221						left   = ( $( window ).width() - width ) / 2,
222						top    = ( $( window ).height() - height ) / 2,
223						opts   = 'status=1' +
224								',width=' + width +
225								',height=' + height +
226								',top=' + top +
227								',left=' + left;
228
229					// Open the share url in a smaller window.
230					window.open( $( event ).attr( 'href' ), 'share', opts );
231				}
232			}
233		},
234
235		/**
236		 * Remove generated p tag from facebook save button.
237		 */
238		removeP: function() {
239		}
240	};
241} )( window.jQuery, window.FB );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.