PluginProbe
Embed Privacy / 1.11.2
Embed Privacy v1.11.2
1.14.0 1.13.0 trunk 0.1 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.10.0 1.10.1 1.10.10 1.10.2 1.10.3 1.10.4 1.10.5 1.10.6 1.10.7 1.10.8 1.10.9 1.11.0 1.11.1 1.11.2 All 68 releases
embed-privacy / assets / js / embed-privacy.js

embed-privacy.js in Embed Privacy 1.11.2, at assets/js/embed-privacy.js

402 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Embed Privacy JavaScript functions.
3 *
4 * @author Epiphyt
5 * @license GPL2
6 * @package epiphyt\Embed_Privacy
7 */
8 document.addEventListener( 'DOMContentLoaded', function() {
9 var checkboxes = document.querySelectorAll( '.embed-privacy-inner .embed-privacy-input' );
10 var labels = document.querySelectorAll( '.embed-privacy-inner .embed-privacy-label' );
11 var overlays = document.querySelectorAll( '.embed-privacy-overlay' );
12 var overlayLinks = document.querySelectorAll( '.embed-privacy-overlay a' );
13
14 initOverlays( overlays, overlayLinks, checkboxes, labels );
15 initBuddyPressActivityStream();
16 optOut();
17 setMinHeight();
18
19 window.addEventListener( 'resize', function() {
20 setMinHeight();
21 } );
22
23 /**
24 * Clicking on a checkbox to always enable/disable an embed provider.
25 *
26 * @since 1.2.0
27 *
28 * @param {HTMLElement} target Target element
29 */
30 function checkboxActivation( target ) {
31 const container = target.closest( '.embed-privacy-container' );
32 var embedProvider = target.getAttribute( 'data-embed-provider' );
33 var cookie = ( get_cookie( 'embed-privacy' ) ? JSON.parse( get_cookie( 'embed-privacy' ) ) : '' );
34
35 if ( target.checked ) {
36 // add|update the cookie's value
37 if ( cookie !== null && Object.keys( cookie ).length !== 0 && cookie.constructor === Object ) {
38 cookie[ embedProvider ] = true;
39
40 set_cookie( 'embed-privacy', JSON.stringify( cookie ), 365 );
41 }
42 else {
43 set_cookie( 'embed-privacy', '{"' + embedProvider + '":true}', 365 );
44 }
45
46 enableAlwaysActiveProviders( document.querySelectorAll( '.embed-privacy-overlay' ) );
47
48 // focus first element in container, but not for opt-out shortcode
49 if ( container ) {
50 container.querySelector( '.embed-privacy-content > :first-child' ).focus();
51 }
52 }
53 else if ( cookie !== null ) {
54 delete cookie[ embedProvider ];
55
56 if ( Object.keys( cookie ).length !== 0 ) {
57 set_cookie( 'embed-privacy', JSON.stringify( cookie ), 365 );
58 }
59 else {
60 remove_cookie( 'embed-privacy' );
61 }
62 }
63 }
64
65 /**
66 * Check whether to enable an always active provider by default.
67 *
68 * @since 1.2.0
69 *
70 * @param {HTMLElement[]} currentOverlays List of current overlays
71 */
72 function enableAlwaysActiveProviders( currentOverlays ) {
73 var cookie = ( get_cookie( 'embed-privacy' ) ? JSON.parse( get_cookie( 'embed-privacy' ) ) : '' );
74
75 if ( ! currentOverlays ) {
76 currentOverlays = overlays;
77 }
78
79 if ( cookie === null || ! Object.keys( cookie ).length ) {
80 return;
81 }
82
83 var providers = Object.keys( cookie );
84
85 for ( var i = 0; i < currentOverlays.length; i++ ) {
86 var provider = currentOverlays[ i ].parentNode.getAttribute( 'data-embed-provider' );
87
88 if ( providers.includes( provider ) ) {
89 currentOverlays[ i ].click();
90 }
91 }
92 }
93
94 /**
95 * Get always active providers from cookie.
96 *
97 * @since 1.4.8
98 *
99 * @return {string[]} List of always active providers
100 */
101 function getAlwaysActiveProviders() {
102 const cookie = ( get_cookie( 'embed-privacy' ) ? JSON.parse( get_cookie( 'embed-privacy' ) ) : '' );
103
104 if ( ! cookie ) {
105 return [];
106 }
107
108 return Object.keys( cookie );
109 }
110
111 /**
112 * Initialize overlay functionality.
113 *
114 * @since 1.11.0
115 *
116 * @param {HTMLElement[]} embedOverlays List of embed overlays
117 * @param {HTMLElement[]} overlayLinks List of embed overlay links
118 * @param {HTMLElement[]} checkboxes List of embed overlay checkbox inputs
119 * @param {HTMLElement[]} labels List of embed overlay labels
120 */
121 function initOverlays( embedOverlays, overlayLinks, checkboxes, labels ) {
122 for ( var i = 0; i < embedOverlays.length; i++ ) {
123 embedOverlays[ i ].addEventListener( 'click', function( event ) {
124 if ( event.currentTarget.tagName !== 'INPUT' ) {
125 overlayClick( event.currentTarget );
126 }
127 } );
128
129 const button = embedOverlays[ i ].parentNode.querySelector( '.embed-privacy-enable' );
130
131 if ( ! button ) {
132 continue;
133 }
134
135 button.addEventListener( 'click', function( event ) {
136 overlayClick( event.currentTarget.parentNode.querySelector( '.embed-privacy-overlay' ) );
137 event.currentTarget.parentNode.removeChild( event.currentTarget ); // IE11 doesn't support .remove()
138 } );
139 button.addEventListener( 'keypress', function( event ) {
140 if ( event.code === 'Enter' || event.code === 'Space' ) {
141 event.preventDefault(); // prevent space from scrolling the page
142 overlayClick( event.currentTarget.parentNode.querySelector( '.embed-privacy-overlay' ) );
143 event.currentTarget.parentNode.removeChild( event.currentTarget ); // IE11 doesn't support .remove()
144 }
145 } );
146 }
147
148 for ( var i = 0; i < overlayLinks.length; i++ ) {
149 overlayLinks[ i ].addEventListener( 'click', function( event ) {
150 // don't trigger the overlays click
151 event.stopPropagation();
152 } );
153 }
154
155 for ( var i = 0; i < checkboxes.length; i++ ) {
156 checkboxes[ i ].addEventListener( 'click', function( event ) {
157 // don't trigger the overlays click
158 event.stopPropagation();
159
160 checkboxActivation( event.currentTarget, [ event.currentTarget.closest( '.embed-privacy-overlay' ) ] );
161 } );
162 }
163
164 for ( var i = 0; i < labels.length; i++ ) {
165 labels[ i ].addEventListener( 'click', function( event ) {
166 // don't trigger the overlays click
167 event.stopPropagation();
168 } );
169 }
170
171 enableAlwaysActiveProviders( embedOverlays );
172 }
173
174 /**
175 * Initialize support for BuddyPress activity stream.
176 */
177 function initBuddyPressActivityStream() {
178 const activityStream = document.getElementById( 'activity-stream' );
179
180 if ( ! activityStream ) {
181 return;
182 }
183
184 const activityObserver = new MutationObserver( ( mutations ) => {
185 for ( const mutation of mutations ) {
186 const checkboxes = mutation.target.querySelectorAll( '.embed-privacy-inner .embed-privacy-input' );
187 const labels = mutation.target.querySelectorAll( '.embed-privacy-inner .embed-privacy-label' );
188 const overlays = mutation.target.querySelectorAll( '.embed-privacy-overlay' );
189 const overlayLinks = mutation.target.querySelectorAll( '.embed-privacy-overlay a' );
190
191 if ( overlays.length ) {
192 initOverlays( overlays, overlayLinks, checkboxes, labels );
193 }
194 }
195 } );
196
197 activityObserver.observe( activityStream, {
198 childList: true,
199 } );
200 }
201
202 /**
203 * Opting in/out for embed providers.
204 *
205 * @since 1.2.0
206 */
207 function optOut() {
208 const optOutContainer = document.querySelector( '.embed-privacy-opt-out' );
209
210 if ( ! optOutContainer ) {
211 return;
212 }
213
214 var optOutCheckboxes = optOutContainer.querySelectorAll( '.embed-privacy-opt-out-input' );
215 const showAll = optOutContainer.getAttribute( 'data-show-all' ) === '1';
216
217 if ( ! optOutCheckboxes ) {
218 return;
219 }
220
221 const alwaysActiveProviders = getAlwaysActiveProviders();
222
223 for ( var i = 0; i < optOutCheckboxes.length; i++ ) {
224 if ( alwaysActiveProviders.indexOf( optOutCheckboxes[ i ].getAttribute( 'data-embed-provider' ) ) !== -1 ) {
225 optOutCheckboxes[ i ].checked = true;
226 }
227 else if ( ! showAll ) {
228 optOutCheckboxes[ i ].parentNode.parentNode.classList.add( 'is-hidden' );
229
230 continue;
231 }
232
233 optOutCheckboxes[ i ].addEventListener( 'click', function( event ) {
234 var currentTarget = event.currentTarget;
235
236 if ( ! currentTarget ) {
237 return;
238 }
239
240 checkboxActivation( currentTarget );
241 } );
242 }
243
244 const nonHiddenProviders = optOutContainer.querySelectorAll( '.embed-privacy-provider:not(.is-hidden)' );
245
246 // remove the container completely if there is no provider to display
247 if ( ! showAll && ! nonHiddenProviders.length ) {
248 optOutContainer.remove();
249 }
250 }
251
252 /**
253 * Clicking on an overlay.
254 *
255 * @since 1.2.0
256 *
257 * @param {element} target Target element
258 */
259 function overlayClick( target ) {
260 var embedContainer = target.parentNode;
261 var embedContent = target.nextElementSibling;
262
263 embedContainer.classList.remove( 'is-disabled' );
264 embedContainer.classList.add( 'is-enabled' );
265 // hide the embed overlay
266 target.style.display = 'none';
267 // get stored content from JavaScript
268 var embedObject = JSON.parse( window[ '_' + target.parentNode.getAttribute( 'data-embed-id' ) ] );
269
270 embedContent.innerHTML = htmlentities_decode( embedObject.embed );
271
272 // reset wrapper inline CSS set in setMinHeight()
273 var wrapper = embedContainer.parentNode;
274
275 if ( wrapper.classList.contains( 'wp-block-embed__wrapper' ) ) {
276 wrapper.style.removeProperty( 'height' );
277 }
278
279 // get all script tags inside the embed
280 var scriptTags = embedContent.querySelectorAll( 'script' );
281
282 // insert every script tag inside the embed as a new script
283 // to execute it
284 for ( var n = 0; n < scriptTags.length; n++ ) {
285 var element = document.createElement( 'script' );
286
287 if ( scriptTags[ n ].src ) {
288 // if script tag has a src attribute
289 element.src = scriptTags[ n ].src;
290 }
291 else {
292 // if script tag has content
293 element.innerHTML = scriptTags[ n ].innerHTML;
294 }
295
296 // append it to body
297 embedContent.appendChild( element );
298 }
299
300 // focus first element in container
301 embedContainer.querySelector( '.embed-privacy-content > :first-child' ).focus();
302
303 if ( typeof jQuery !== 'undefined' ) {
304 const videoShortcode = jQuery( '.wp-video-shortcode' );
305
306 if ( videoShortcode.length ) {
307 videoShortcode.mediaelementplayer();
308 }
309 }
310
311 if ( embedContainer.getAttribute( 'data-embed-provider' ) === 'instagram' ) {
312 const interval = setInterval( () => {
313 if ( window.instgrm ) {
314 window.instgrm.Embeds.process();
315 clearInterval( interval );
316 }
317 }, 100 );
318 }
319 }
320
321 /**
322 * Calculate min height of the embed wrapper depending of the overlay content.
323 */
324 function setMinHeight() {
325 for ( var i = 0; i < overlays.length; i++ ) {
326 var wrapper = overlays[ i ].parentNode.parentNode;
327
328 if ( ! wrapper.classList.contains( 'wp-block-embed__wrapper' ) ) {
329 continue;
330 }
331
332 wrapper.style.removeProperty( 'height' );
333
334 if ( wrapper.offsetHeight < overlays[ i ].offsetHeight ) {
335 wrapper.style.height = overlays[ i ].offsetHeight + 'px';
336 }
337 }
338 }
339 } );
340
341 /**
342 * Get a cookie.
343 *
344 * @link https://stackoverflow.com/a/24103596/3461955
345 *
346 * @param {string} name The name of the cookie
347 */
348 function get_cookie( name ) {
349 var nameEQ = name + '=';
350 var ca = document.cookie.split( ';' );
351 for ( var i = 0; i < ca.length; i++ ) {
352 var c = ca[ i ];
353 while ( c.charAt( 0 ) == ' ' ) c = c.substring( 1, c.length );
354 if ( c.indexOf( nameEQ ) == 0 ) return c.substring( nameEQ.length, c.length );
355 }
356 return null;
357 }
358
359 /**
360 * Decode a string with HTML entities.
361 *
362 * @param {string} content The content to decode
363 * @return {string} The decoded content
364 */
365 function htmlentities_decode( content ) {
366 var textarea = document.createElement( 'textarea' );
367
368 textarea.innerHTML = content;
369
370 return textarea.value;
371 }
372
373 /**
374 * Remove a cookie.
375 *
376 * @link https://stackoverflow.com/a/24103596/3461955
377 *
378 * @param {string} name The name of the cookie
379 */
380 function remove_cookie( name ) {
381 document.cookie = name + '=; expires=0; path=/';
382 }
383
384 /**
385 * Set a cookie.
386 *
387 * @link https://stackoverflow.com/a/24103596/3461955
388 *
389 * @param {string} name The name of the cookie
390 * @param {string} value The value of the cookie
391 * @param {number} days The expiration in days
392 */
393 function set_cookie( name, value, days ) {
394 var expires = '';
395 if ( days ) {
396 var date = new Date();
397 date.setTime( date.getTime() + ( days * 24 * 60 * 60 * 1000 ) );
398 expires = '; expires=' + date.toUTCString();
399 }
400 document.cookie = name + '=' + ( value || '' ) + expires + '; path=/';
401 }
402