[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 import * as __WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__ from "@wordpress/interactivity"; 2 /******/ // The require scope 3 /******/ var __webpack_require__ = {}; 4 /******/ 5 /************************************************************************/ 6 /******/ /* webpack/runtime/define property getters */ 7 /******/ (() => { 8 /******/ // define getter functions for harmony exports 9 /******/ __webpack_require__.d = (exports, definition) => { 10 /******/ for(var key in definition) { 11 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { 12 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); 13 /******/ } 14 /******/ } 15 /******/ }; 16 /******/ })(); 17 /******/ 18 /******/ /* webpack/runtime/hasOwnProperty shorthand */ 19 /******/ (() => { 20 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) 21 /******/ })(); 22 /******/ 23 /************************************************************************/ 24 var __webpack_exports__ = {}; 25 26 // EXPORTS 27 __webpack_require__.d(__webpack_exports__, { 28 o: () => (/* binding */ actions), 29 w: () => (/* binding */ state) 30 }); 31 32 ;// CONCATENATED MODULE: external "@wordpress/interactivity" 33 var x = (y) => { 34 var x = {}; __webpack_require__.d(x, y); return x 35 } 36 var y = (x) => (() => (x)) 37 const interactivity_namespaceObject = x({ ["getConfig"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.getConfig), ["privateApis"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.privateApis), ["store"]: () => (__WEBPACK_EXTERNAL_MODULE__wordpress_interactivity_8e89b257__.store) }); 38 ;// CONCATENATED MODULE: ./node_modules/@wordpress/interactivity-router/build-module/index.js 39 var _getConfig$navigation; 40 /** 41 * WordPress dependencies 42 */ 43 44 45 /** 46 * Internal dependencies 47 */ 48 49 const { 50 directivePrefix, 51 getRegionRootFragment, 52 initialVdom, 53 toVdom, 54 render, 55 parseServerData, 56 populateServerData, 57 batch 58 } = (0,interactivity_namespaceObject.privateApis)('I acknowledge that using private APIs means my theme or plugin will inevitably break in the next version of WordPress.'); 59 // Check if the navigation mode is full page or region based. 60 const navigationMode = (_getConfig$navigation = (0,interactivity_namespaceObject.getConfig)('core/router').navigationMode) !== null && _getConfig$navigation !== void 0 ? _getConfig$navigation : 'regionBased'; 61 62 // The cache of visited and prefetched pages, stylesheets and scripts. 63 const pages = new Map(); 64 const headElements = new Map(); 65 66 // Helper to remove domain and hash from the URL. We are only interesting in 67 // caching the path and the query. 68 const getPagePath = url => { 69 const u = new URL(url, window.location.href); 70 return u.pathname + u.search; 71 }; 72 73 // Fetch a new page and convert it to a static virtual DOM. 74 const fetchPage = async (url, { 75 html 76 }) => { 77 try { 78 if (!html) { 79 const res = await window.fetch(url); 80 if (res.status !== 200) { 81 return false; 82 } 83 html = await res.text(); 84 } 85 const dom = new window.DOMParser().parseFromString(html, 'text/html'); 86 return regionsToVdom(dom); 87 } catch (e) { 88 return false; 89 } 90 }; 91 92 // Return an object with VDOM trees of those HTML regions marked with a 93 // `router-region` directive. 94 const regionsToVdom = async (dom, { 95 vdom 96 } = {}) => { 97 const regions = { 98 body: undefined 99 }; 100 let head; 101 if (false) {} 102 if (navigationMode === 'regionBased') { 103 const attrName = `data-$directivePrefix}-router-region`; 104 dom.querySelectorAll(`[$attrName}]`).forEach(region => { 105 const id = region.getAttribute(attrName); 106 regions[id] = vdom?.has(region) ? vdom.get(region) : toVdom(region); 107 }); 108 } 109 const title = dom.querySelector('title')?.innerText; 110 const initialData = parseServerData(dom); 111 return { 112 regions, 113 head, 114 title, 115 initialData 116 }; 117 }; 118 119 // Render all interactive regions contained in the given page. 120 const renderRegions = page => { 121 batch(() => { 122 if (false) {} 123 if (navigationMode === 'regionBased') { 124 populateServerData(page.initialData); 125 const attrName = `data-$directivePrefix}-router-region`; 126 document.querySelectorAll(`[$attrName}]`).forEach(region => { 127 const id = region.getAttribute(attrName); 128 const fragment = getRegionRootFragment(region); 129 render(page.regions[id], fragment); 130 }); 131 } 132 if (page.title) { 133 document.title = page.title; 134 } 135 }); 136 }; 137 138 /** 139 * Load the given page forcing a full page reload. 140 * 141 * The function returns a promise that won't resolve, useful to prevent any 142 * potential feedback indicating that the navigation has finished while the new 143 * page is being loaded. 144 * 145 * @param href The page href. 146 * @return Promise that never resolves. 147 */ 148 const forcePageReload = href => { 149 window.location.assign(href); 150 return new Promise(() => {}); 151 }; 152 153 // Listen to the back and forward buttons and restore the page if it's in the 154 // cache. 155 window.addEventListener('popstate', async () => { 156 const pagePath = getPagePath(window.location.href); // Remove hash. 157 const page = pages.has(pagePath) && (await pages.get(pagePath)); 158 if (page) { 159 renderRegions(page); 160 // Update the URL in the state. 161 state.url = window.location.href; 162 } else { 163 window.location.reload(); 164 } 165 }); 166 167 // Initialize the router and cache the initial page using the initial vDOM. 168 // Once this code is tested and more mature, the head should be updated for 169 // region based navigation as well. 170 if (false) {} 171 pages.set(getPagePath(window.location.href), Promise.resolve(regionsToVdom(document, { 172 vdom: initialVdom 173 }))); 174 175 // Check if the link is valid for client-side navigation. 176 const isValidLink = ref => ref && ref instanceof window.HTMLAnchorElement && ref.href && (!ref.target || ref.target === '_self') && ref.origin === window.location.origin && !ref.pathname.startsWith('/wp-admin') && !ref.pathname.startsWith('/wp-login.php') && !ref.getAttribute('href').startsWith('#') && !new URL(ref.href).searchParams.has('_wpnonce'); 177 178 // Check if the event is valid for client-side navigation. 179 const isValidEvent = event => event && event.button === 0 && 180 // Left clicks only. 181 !event.metaKey && 182 // Open in new tab (Mac). 183 !event.ctrlKey && 184 // Open in new tab (Windows). 185 !event.altKey && 186 // Download. 187 !event.shiftKey && !event.defaultPrevented; 188 189 // Variable to store the current navigation. 190 let navigatingTo = ''; 191 let hasLoadedNavigationTextsData = false; 192 const navigationTexts = { 193 loading: 'Loading page, please wait.', 194 loaded: 'Page Loaded.' 195 }; 196 const { 197 state, 198 actions 199 } = (0,interactivity_namespaceObject.store)('core/router', { 200 state: { 201 url: window.location.href, 202 navigation: { 203 hasStarted: false, 204 hasFinished: false, 205 message: '' 206 } 207 }, 208 actions: { 209 /** 210 * Navigates to the specified page. 211 * 212 * This function normalizes the passed href, fetchs the page HTML if 213 * needed, and updates any interactive regions whose contents have 214 * changed. It also creates a new entry in the browser session history. 215 * 216 * @param href The page href. 217 * @param [options] Options object. 218 * @param [options.force] If true, it forces re-fetching the URL. 219 * @param [options.html] HTML string to be used instead of fetching the requested URL. 220 * @param [options.replace] If true, it replaces the current entry in the browser session history. 221 * @param [options.timeout] Time until the navigation is aborted, in milliseconds. Default is 10000. 222 * @param [options.loadingAnimation] Whether an animation should be shown while navigating. Default to `true`. 223 * @param [options.screenReaderAnnouncement] Whether a message for screen readers should be announced while navigating. Default to `true`. 224 * 225 * @return Promise that resolves once the navigation is completed or aborted. 226 */ 227 *navigate(href, options = {}) { 228 const { 229 clientNavigationDisabled 230 } = (0,interactivity_namespaceObject.getConfig)(); 231 if (clientNavigationDisabled) { 232 yield forcePageReload(href); 233 } 234 const pagePath = getPagePath(href); 235 const { 236 navigation 237 } = state; 238 const { 239 loadingAnimation = true, 240 screenReaderAnnouncement = true, 241 timeout = 10000 242 } = options; 243 navigatingTo = href; 244 actions.prefetch(pagePath, options); 245 246 // Create a promise that resolves when the specified timeout ends. 247 // The timeout value is 10 seconds by default. 248 const timeoutPromise = new Promise(resolve => setTimeout(resolve, timeout)); 249 250 // Don't update the navigation status immediately, wait 400 ms. 251 const loadingTimeout = setTimeout(() => { 252 if (navigatingTo !== href) { 253 return; 254 } 255 if (loadingAnimation) { 256 navigation.hasStarted = true; 257 navigation.hasFinished = false; 258 } 259 if (screenReaderAnnouncement) { 260 a11ySpeak('loading'); 261 } 262 }, 400); 263 const page = yield Promise.race([pages.get(pagePath), timeoutPromise]); 264 265 // Dismiss loading message if it hasn't been added yet. 266 clearTimeout(loadingTimeout); 267 268 // Once the page is fetched, the destination URL could have changed 269 // (e.g., by clicking another link in the meantime). If so, bail 270 // out, and let the newer execution to update the HTML. 271 if (navigatingTo !== href) { 272 return; 273 } 274 if (page && !page.initialData?.config?.['core/router']?.clientNavigationDisabled) { 275 yield renderRegions(page); 276 window.history[options.replace ? 'replaceState' : 'pushState']({}, '', href); 277 278 // Update the URL in the state. 279 state.url = href; 280 281 // Update the navigation status once the the new page rendering 282 // has been completed. 283 if (loadingAnimation) { 284 navigation.hasStarted = false; 285 navigation.hasFinished = true; 286 } 287 if (screenReaderAnnouncement) { 288 a11ySpeak('loaded'); 289 } 290 291 // Scroll to the anchor if exits in the link. 292 const { 293 hash 294 } = new URL(href, window.location.href); 295 if (hash) { 296 document.querySelector(hash)?.scrollIntoView(); 297 } 298 } else { 299 yield forcePageReload(href); 300 } 301 }, 302 /** 303 * Prefetchs the page with the passed URL. 304 * 305 * The function normalizes the URL and stores internally the fetch 306 * promise, to avoid triggering a second fetch for an ongoing request. 307 * 308 * @param url The page URL. 309 * @param [options] Options object. 310 * @param [options.force] Force fetching the URL again. 311 * @param [options.html] HTML string to be used instead of fetching the requested URL. 312 */ 313 prefetch(url, options = {}) { 314 const { 315 clientNavigationDisabled 316 } = (0,interactivity_namespaceObject.getConfig)(); 317 if (clientNavigationDisabled) { 318 return; 319 } 320 const pagePath = getPagePath(url); 321 if (options.force || !pages.has(pagePath)) { 322 pages.set(pagePath, fetchPage(pagePath, { 323 html: options.html 324 })); 325 } 326 } 327 } 328 }); 329 330 /** 331 * Announces a message to screen readers. 332 * 333 * This is a wrapper around the `@wordpress/a11y` package's `speak` function. It handles importing 334 * the package on demand and should be used instead of calling `ally.speak` direacly. 335 * 336 * @param messageKey The message to be announced by assistive technologies. 337 */ 338 function a11ySpeak(messageKey) { 339 if (!hasLoadedNavigationTextsData) { 340 hasLoadedNavigationTextsData = true; 341 const content = document.getElementById('wp-script-module-data-@wordpress/interactivity-router')?.textContent; 342 if (content) { 343 try { 344 const parsed = JSON.parse(content); 345 if (typeof parsed?.i18n?.loading === 'string') { 346 navigationTexts.loading = parsed.i18n.loading; 347 } 348 if (typeof parsed?.i18n?.loaded === 'string') { 349 navigationTexts.loaded = parsed.i18n.loaded; 350 } 351 } catch {} 352 } else { 353 // Fallback to localized strings from Interactivity API state. 354 if (state.navigation.texts?.loading) { 355 navigationTexts.loading = state.navigation.texts.loading; 356 } 357 if (state.navigation.texts?.loaded) { 358 navigationTexts.loaded = state.navigation.texts.loaded; 359 } 360 } 361 } 362 const message = navigationTexts[messageKey]; 363 if (false) {} else { 364 state.navigation.message = 365 // Announce that the page has been loaded. If the message is the 366 // same, we use a no-break space similar to the @wordpress/a11y 367 // package: https://github.com/WordPress/gutenberg/blob/c395242b8e6ee20f8b06c199e4fc2920d7018af1/packages/a11y/src/filter-message.js#L20-L26 368 message + (state.navigation.message === message ? '\u00A0' : ''); 369 } 370 } 371 372 // Add click and prefetch to all links. 373 if (false) {} 374 375 var __webpack_exports__actions = __webpack_exports__.o; 376 var __webpack_exports__state = __webpack_exports__.w; 377 export { __webpack_exports__actions as actions, __webpack_exports__state as state };
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Tue Sep 24 08:20:01 2024 | Cross-referenced by PHPXref |