All files / src/internal/client/dom/elements/bindings window.js

98.7% Statements 76/77
85% Branches 17/20
100% Functions 4/4
98.64% Lines 73/74

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 752x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 6x 6x 6x 2x 2x 2x 2x 2x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 4x 6x 6x 6x 6x 14x 14x 14x 6x 14x 4x 4x 4x   4x 4x 4x 4x 4x 6x 6x 6x 6x 6x 8x 8x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 2x 2x 2x 2x 2x 2x 8x 8x  
import { effect, render_effect } from '../../../reactivity/effects.js';
import { yield_updates } from '../../../runtime.js';
import { listen } from './shared.js';
 
/**
 * @param {'x' | 'y'} type
 * @param {() => number} get_value
 * @param {(value: number) => void} update
 * @returns {void}
 */
export function bind_window_scroll(type, get_value, update) {
	var is_scrolling_x = type === 'x';
 
	var target_handler = () => {
		scrolling = true;
		clearTimeout(timeout);
		timeout = setTimeout(clear, 100); // TODO use scrollend event if supported (or when supported everywhere?)
 
		yield_updates(() => update(window[is_scrolling_x ? 'scrollX' : 'scrollY']));
	};
 
	addEventListener('scroll', target_handler, {
		passive: true
	});
 
	var scrolling = false;
 
	/** @type {ReturnType<typeof setTimeout>} */
	var timeout;
	var clear = () => {
		scrolling = false;
	};
	var first = true;
 
	render_effect(() => {
		var latest_value = get_value();
		// Don't scroll to the initial value for accessibility reasons
		if (first) {
			first = false;
		} else if (!scrolling && latest_value != null) {
			scrolling = true;
			clearTimeout(timeout);
			if (is_scrolling_x) {
				scrollTo(latest_value, window.scrollY);
			} else {
				scrollTo(window.scrollX, latest_value);
			}
			timeout = setTimeout(clear, 100);
		}
	});
 
	// Browsers fire the scroll event only if the scroll position is not 0.
	// This effect is (almost) guaranteed to run after the scroll event would've fired.
	effect(() => {
		var value = window[is_scrolling_x ? 'scrollX' : 'scrollY'];
		if (value === 0) {
			yield_updates(() => update(value));
		}
	});
 
	render_effect(() => {
		return () => {
			removeEventListener('scroll', target_handler);
		};
	});
}
 
/**
 * @param {'innerWidth' | 'innerHeight' | 'outerWidth' | 'outerHeight'} type
 * @param {(size: number) => void} update
 */
export function bind_window_size(type, update) {
	listen(window, ['resize'], () => yield_updates(() => update(window[type])));
}