import { isElement , isString } from './checking' ; import { pInt } from './str-num' ; param elem param attr export function getNumberValueOfStyle ( elem , attr ) { const value = window . getComputedStyle ( elem ) [ attr ] ; if ( isString ( value ) ) { const numberValue = ( value as string ) . match ( /\d+/ ) ; if ( numberValue ) { return pInt ( numberValue [ 0 ] ) ; } } } param elem export function offset ( elem ) { const bounding = elem . getBoundingClientRect ( ) ; return { left : window . pageXOffset + bounding . left , top : window . pageYOffset + bounding . top , } ; } /**
 * 不管是 MutationObserver 还是 DOMNodeRemoved，
 * 当监听某个具体的元素时，如果祖先节点被删除了，并不会触发该元素被移除的事件，
 * 所以要监听整个文档，每次移除事件都得递归遍历要监听的元素是否被删除。
 */ export const observeElementRemoved = ( ( ) => { const MutationObserver = window . MutationObserver || window . WebKitMutationObserver ; const checkElementRemoved = ( node , element ) => { if ( node === element ) { return true ; } if ( isElement ( node ) ) { const children = ( node as HTMLElement ) . children ; let length = children . length ; while ( length -- ) { if ( checkElementRemoved ( children [ length ] , element ) ) { return true ; } } } return false ; } ; const useMutation = ( element , callback ) => { const observer = new MutationObserver ( ( mutations , observer ) => { let i = mutations . length ; while ( i -- ) { const removeNodes = mutations [ i ] . removedNodes ; let j = removeNodes . length ; while ( j -- ) { if ( checkElementRemoved ( removeNodes [ j ] , element ) ) { observer . disconnect ( ) ; return callback ( ) ; } } } } ) ; observer . observe ( document , { childList : true , subtree : true , } ) ; } ; const useDOMNodeRemoved = ( element , callback ) => { const DOMNodeRemoved = ( e ) => { if ( checkElementRemoved ( e . target as Node , element ) ) { document . removeEventListener ( 'DOMNodeRemoved' , DOMNodeRemoved ) ; callback ( ) ; } } ; document . addEventListener ( 'DOMNodeRemoved' , DOMNodeRemoved ) ; } ; return MutationObserver ? useMutation : useDOMNodeRemoved ; } ) ( ) ;