查看“︁MediaWiki:Gadget-sectionObserver.js”︁的源代码
←
MediaWiki:Gadget-sectionObserver.js
跳转到导航
跳转到搜索
因为以下原因,您没有权限编辑该页面:
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。 如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
// Source: https://github.com/wikimedia/mediawiki-skins-Vector/blob/master/resources/skins.vector.js/sectionObserver.js /** @module SectionObserver */ /** * @callback OnIntersection * @param {HTMLElement} element The section that triggered the new intersection change. */ /** * @typedef {Object} SectionObserverProps * @property {NodeList} elements A list of HTML elements to observe for * intersection changes. This list can be updated through the `elements` setter. * @property {OnIntersection} onIntersection Called when a new intersection is observed. * @property {number} [topMargin] The number of pixels to shrink the top of * the viewport's bounding box before calculating intersections. This is useful * for sticky elements (e.g. sticky headers). Defaults to 0 pixels. * @property {number} [throttleMs] The number of milliseconds that the scroll * handler should be throttled. */ /** * @callback initSectionObserver * @param {SectionObserverProps} props * @return {SectionObserver} */ /** * Observe intersection changes with the viewport for one or more elements. This * is intended to be used with the headings in the content so that the * corresponding section(s) in the table of contents can be "activated" (e.g. * bolded). * * When sectionObserver notices a new intersection change, the * `props.onIntersection` callback will be fired with the corresponding section * as a param. * * Because sectionObserver uses a scroll event listener (in combination with * IntersectionObserver), the changes are throttled to a default maximum rate of * 200ms so that the main thread is not excessively blocked. * IntersectionObserver is used to asynchronously calculate the positions of the * observed tags off the main thread and in a manner that does not cause * expensive forced synchronous layouts. * * @param {SectionObserverProps} props * @return {SectionObserver} */ module.exports = function sectionObserver( props ) { props = Object.assign( { topMargin: 0, throttleMs: 200, onIntersection: function() {} }, props ); var /** @type {number | undefined} */ timeoutId; var /** @type {HTMLElement | undefined} */ current; const observer = new IntersectionObserver( function( entries ) { var /** @type {IntersectionObserverEntry | undefined} */ closestNegativeEntry; var /** @type {IntersectionObserverEntry | undefined} */ closestPositiveEntry; const topMargin = /** @type {number} */ ( props.topMargin ); entries.forEach( function( entry ) { const top = entry.boundingClientRect.top - topMargin; if ( top > 0 && ( closestPositiveEntry === undefined || top < closestPositiveEntry.boundingClientRect.top - topMargin ) ) { closestPositiveEntry = entry; } if ( top <= 0 && ( closestNegativeEntry === undefined || top > closestNegativeEntry.boundingClientRect.top - topMargin ) ) { closestNegativeEntry = entry; } } ); const closestTag = /** @type {HTMLElement} */ ( closestNegativeEntry ? closestNegativeEntry.target : /** @type {IntersectionObserverEntry} */ ( closestPositiveEntry ).target ); // If the intersection is new, fire the `onIntersection` callback. if ( current !== closestTag ) { props.onIntersection( closestTag ); } current = closestTag; // When finished finding the intersecting element, stop observing all // observed elements. The scroll event handler will be responsible for // throttling and reobserving the elements again. Because we don't have a // wrapper element around our content headings and their children, we can't // rely on IntersectionObserver (which is optimized to detect intersecting // elements *within* the viewport) to reliably fire this callback without // this manual step. Instead, we offload the work of calculating the // position of each element in an efficient manner to IntersectionObserver, // but do not use it to detect when a new element has entered the viewport. observer.disconnect(); } ); /** * Calculate the intersection of each observed element. */ function calcIntersection() { // IntersectionObserver will asynchronously calculate the boundingClientRect // of each observed element off the main thread after `observe` is called. props.elements.forEach( function( element ) { if ( !element.parentNode ) { mw.log.warn( 'Element being observed is not in DOM', element ); return; } observer.observe( /** @type {HTMLElement} */ ( element ) ); } ); } function handleScroll() { // Throttle the scroll event handler to fire at a rate limited by `props.throttleMs`. if ( !timeoutId ) { timeoutId = window.setTimeout( function() { calcIntersection(); timeoutId = undefined; }, props.throttleMs ); } } function bindScrollListener() { window.addEventListener( 'scroll', handleScroll ); } function unbindScrollListener() { window.removeEventListener( 'scroll', handleScroll ); } /** * Pauses intersection observation until `resume` is called. */ function pause() { unbindScrollListener(); clearTimeout( timeoutId ); timeoutId = undefined; // Assume current is no longer valid while paused. current = undefined; } /** * Resumes intersection observation. */ function resume() { bindScrollListener(); } /** * Cleans up event listeners and intersection observer. Should be called when * the observer is permanently no longer needed. */ function unmount() { unbindScrollListener(); observer.disconnect(); } /** * Set a list of HTML elements to observe for intersection changes. * * @param {NodeList} list */ function setElements( list ) { props.elements = list; } bindScrollListener(); /** * @typedef {Object} SectionObserver * @property {calcIntersection} calcIntersection * @property {pause} pause * @property {resume} resume * @property {unmount} unmount * @property {setElements} setElements */ return { calcIntersection: calcIntersection, pause: pause, resume: resume, unmount: unmount, setElements: setElements }; }; // [[Category:Scripts]]
返回
MediaWiki:Gadget-sectionObserver.js
。
导航菜单
个人工具
未登录
讨论
贡献
创建账号
登录
命名空间
系统消息
讨论
English
查看
阅读
查看源代码
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
快速跳转
快速上手DJMAX RESPECT V
登场角色
收录歌曲列表
Steam成就/Xbox奖杯指南
任务指南
DLC购买指南
其他企划
CDC赛事品牌
DJMAX Entertainment
工具
链入页面
相关更改
特殊页面
页面信息