| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 /** 2 * @output wp-includes/js/wp-embed-template.js 3 */ 4 5 /** 6 * IIFE setup function. 7 * 8 * @param {Window} window The global window object. 9 * @param {Document} document The global document object. 10 */ 11 (function ( window, document ) { 12 'use strict'; 13 14 var supportedBrowser = ( document.querySelector && window.addEventListener ), 15 loaded = false, 16 secret, 17 secretTimeout, 18 resizing; 19 20 /** 21 * Sends a message to the parent window. 22 * 23 * @param {string} message The message type (e.g., 'height', 'link'). 24 * @param {*} value The message value. Type depends on message (number for height, string for link). 25 */ 26 function sendEmbedMessage( message, value ) { 27 window.parent.postMessage( { 28 message: message, 29 value: value, 30 secret: secret 31 }, '*' ); 32 } 33 34 /** 35 * Send the height message to the parent window. 36 */ 37 function sendHeightMessage() { 38 sendEmbedMessage( 'height', Math.ceil( document.body.getBoundingClientRect().height ) ); 39 } 40 41 /** 42 * Runs on DomContentLoaded and load event. 43 * 44 * Exits early on the load event if the earlier event has 45 * successfully fired. 46 */ 47 function onLoad() { 48 if ( loaded ) { 49 return; 50 } 51 loaded = true; 52 53 var share_dialog = document.querySelector( '.wp-embed-share-dialog' ), 54 share_dialog_open = document.querySelector( '.wp-embed-share-dialog-open' ), 55 share_dialog_close = document.querySelector( '.wp-embed-share-dialog-close' ), 56 share_input = document.querySelectorAll( '.wp-embed-share-input' ), 57 share_dialog_tabs = document.querySelectorAll( '.wp-embed-share-tab-button button' ), 58 featured_image = document.querySelector( '.wp-embed-featured-image img' ), 59 i; 60 61 if ( share_input ) { 62 for ( i = 0; i < share_input.length; i++ ) { 63 share_input[ i ].addEventListener( 'click', function ( event ) { 64 event.target.select(); 65 } ); 66 } 67 } 68 69 /** 70 * Open share dialog within embed iframe. 71 */ 72 function openSharingDialog() { 73 share_dialog.className = share_dialog.className.replace( 'hidden', '' ); 74 // Initial focus should go on the currently selected tab in the dialog. 75 document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ).focus(); 76 } 77 78 /** 79 * Close share dialog within embed iframe. 80 */ 81 function closeSharingDialog() { 82 share_dialog.className += ' hidden'; 83 document.querySelector( '.wp-embed-share-dialog-open' ).focus(); 84 } 85 86 if ( share_dialog_open ) { 87 share_dialog_open.addEventListener( 'click', function () { 88 openSharingDialog(); 89 } ); 90 } 91 92 if ( share_dialog_close ) { 93 share_dialog_close.addEventListener( 'click', function () { 94 closeSharingDialog(); 95 } ); 96 } 97 98 /** 99 * Click event handler for share button. 100 * 101 * @param {MouseEvent} event Event handler. 102 */ 103 function shareClickHandler( event ) { 104 var currentTab = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ); 105 currentTab.setAttribute( 'aria-selected', 'false' ); 106 document.querySelector( '#' + currentTab.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); 107 108 event.target.setAttribute( 'aria-selected', 'true' ); 109 document.querySelector( '#' + event.target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); 110 } 111 112 /** 113 * Keyboard event handler for share button. 114 * 115 * @param {KeyboardEvent} event Event handler. 116 * @return {boolean|void} Returns false if default action is to be prevented. 117 */ 118 function shareKeyHandler( event ) { 119 var target = event.target, 120 previousSibling = target.parentElement.previousElementSibling, 121 nextSibling = target.parentElement.nextElementSibling, 122 newTab, newTabChild; 123 124 if ( 37 === event.keyCode ) { 125 newTab = previousSibling; 126 } else if ( 39 === event.keyCode ) { 127 newTab = nextSibling; 128 } else { 129 return false; 130 } 131 132 if ( 'rtl' === document.documentElement.getAttribute( 'dir' ) ) { 133 newTab = ( newTab === previousSibling ) ? nextSibling : previousSibling; 134 } 135 136 if ( newTab ) { 137 newTabChild = newTab.firstElementChild; 138 139 target.setAttribute( 'tabindex', '-1' ); 140 target.setAttribute( 'aria-selected', false ); 141 document.querySelector( '#' + target.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'true' ); 142 143 newTabChild.setAttribute( 'tabindex', '0' ); 144 newTabChild.setAttribute( 'aria-selected', 'true' ); 145 newTabChild.focus(); 146 document.querySelector( '#' + newTabChild.getAttribute( 'aria-controls' ) ).setAttribute( 'aria-hidden', 'false' ); 147 } 148 } 149 150 if ( share_dialog_tabs ) { 151 for ( i = 0; i < share_dialog_tabs.length; i++ ) { 152 share_dialog_tabs[ i ].addEventListener( 'click', shareClickHandler ); 153 154 share_dialog_tabs[ i ].addEventListener( 'keydown', shareKeyHandler ); 155 } 156 } 157 158 document.addEventListener( 'keydown', function ( event ) { 159 if ( 27 === event.keyCode && -1 === share_dialog.className.indexOf( 'hidden' ) ) { 160 closeSharingDialog(); 161 } else if ( 9 === event.keyCode ) { 162 constrainTabbing( event ); 163 } 164 }, false ); 165 166 /** 167 * Constrain tabbing to share dialog when open. 168 * 169 * @param {KeyboardEvent} event Event object. 170 */ 171 function constrainTabbing( event ) { 172 // Need to re-get the selected tab each time. 173 var firstFocusable = document.querySelector( '.wp-embed-share-tab-button [aria-selected="true"]' ); 174 175 if ( share_dialog_close === event.target && ! event.shiftKey ) { 176 firstFocusable.focus(); 177 event.preventDefault(); 178 } else if ( firstFocusable === event.target && event.shiftKey ) { 179 share_dialog_close.focus(); 180 event.preventDefault(); 181 } 182 } 183 184 if ( window.self === window.top ) { 185 return; 186 } 187 188 // Send this document's height to the parent (embedding) site. 189 sendHeightMessage(); 190 191 // Send the document's height again after the featured image has been loaded. 192 if ( featured_image ) { 193 featured_image.addEventListener( 'load', sendHeightMessage ); 194 } 195 196 /** 197 * Detect clicks to external (_top) links. 198 * 199 * @param {MouseEvent} event 200 */ 201 function linkClickHandler( event ) { 202 /* 203 * The href property resolves to an absolute URL, which the parent window requires. 204 * Elements whose href is not a string, such as SVG anchors, are skipped. 205 */ 206 var link = event.target.closest( '[href]' ), 207 href = 'string' === typeof link?.href ? link.href : null; 208 209 // Only catch clicks from the primary mouse button, without any modifiers. 210 if ( event.altKey || event.ctrlKey || event.metaKey || event.shiftKey ) { 211 return; 212 } 213 214 // Send link target to the parent (embedding) site. 215 if ( href ) { 216 sendEmbedMessage( 'link', href ); 217 event.preventDefault(); 218 } 219 } 220 221 document.addEventListener( 'click', linkClickHandler ); 222 } 223 224 /** 225 * Iframe resize handler. 226 */ 227 function onResize() { 228 if ( window.self === window.top ) { 229 return; 230 } 231 232 clearTimeout( resizing ); 233 234 resizing = setTimeout( sendHeightMessage, 100 ); 235 } 236 237 /** 238 * Message handler. 239 * 240 * @param {MessageEvent} event 241 */ 242 function onMessage( event ) { 243 var data = event.data; 244 245 if ( ! data ) { 246 return; 247 } 248 249 if ( event.source !== window.parent ) { 250 return; 251 } 252 253 if ( ! ( data.secret || data.message ) ) { 254 return; 255 } 256 257 if ( data.secret !== secret ) { 258 return; 259 } 260 261 if ( 'ready' === data.message ) { 262 sendHeightMessage(); 263 } 264 } 265 266 /** 267 * Re-get the secret when it was added later on. 268 */ 269 function getSecret() { 270 if ( window.self === window.top || !!secret ) { 271 return; 272 } 273 274 secret = window.location.hash.replace( /.*secret=([\d\w]{10}).*/, '$1' ); 275 276 clearTimeout( secretTimeout ); 277 278 secretTimeout = setTimeout( function () { 279 getSecret(); 280 }, 100 ); 281 } 282 283 if ( supportedBrowser ) { 284 getSecret(); 285 document.documentElement.className = document.documentElement.className.replace( /\bno-js\b/, '' ) + ' js'; 286 document.addEventListener( 'DOMContentLoaded', onLoad, false ); 287 window.addEventListener( 'load', onLoad, false ); 288 window.addEventListener( 'resize', onResize, false ); 289 window.addEventListener( 'message', onMessage, false ); 290 } 291 })( window, document );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Fri Sep 11 08:20:31 2026 | Cross-referenced by PHPXref |