From 29d15a2e2221e0db70544f595388887a3d89ebd4 Mon Sep 17 00:00:00 2001 From: squidfunk Date: Fri, 14 Feb 2020 15:30:06 +0100 Subject: [PATCH] Added possibility to set viewport offset --- .../observables/agent/viewport/_/index.ts | 113 +++++++----------- .../observables/agent/viewport/index.ts | 3 +- .../agent/viewport/offset/index.ts | 81 +++++++++++++ .../viewport/{relative => size}/index.ts | 54 ++++----- 4 files changed, 154 insertions(+), 97 deletions(-) create mode 100644 src/assets/javascripts/observables/agent/viewport/offset/index.ts rename src/assets/javascripts/observables/agent/viewport/{relative => size}/index.ts (64%) diff --git a/src/assets/javascripts/observables/agent/viewport/_/index.ts b/src/assets/javascripts/observables/agent/viewport/_/index.ts index 08cf2eb0c..74dc79649 100644 --- a/src/assets/javascripts/observables/agent/viewport/_/index.ts +++ b/src/assets/javascripts/observables/agent/viewport/_/index.ts @@ -20,29 +20,23 @@ * IN THE SOFTWARE. */ -import { Observable, combineLatest, fromEvent, merge } from "rxjs" -import { map, shareReplay, startWith } from "rxjs/operators" +import { Observable, combineLatest } from "rxjs" +import { map, shareReplay } from "rxjs/operators" + +import { Header } from "../../../header" +import { + ViewportOffset, + watchViewportOffset +} from "../offset" +import { + ViewportSize, + watchViewportSize +} from "../size" /* ---------------------------------------------------------------------------- * Types * ------------------------------------------------------------------------- */ -/** - * Viewport offset - */ -export interface ViewportOffset { - x: number /* Horizontal offset */ - y: number /* Vertical offset */ -} - -/** - * Viewport size - */ -export interface ViewportSize { - width: number /* Viewport width */ - height: number /* Viewport height */ -} - /** * Viewport */ @@ -52,63 +46,20 @@ export interface Viewport { } /* ---------------------------------------------------------------------------- - * Functions + * Helper types * ------------------------------------------------------------------------- */ /** - * Retrieve viewport offset - * - * @return Viewport offset + * Watch relative options */ -export function getViewportOffset(): ViewportOffset { - return { - x: pageXOffset, - y: pageYOffset - } +interface WatchRelativeOptions { + header$: Observable
/* Header observable */ + viewport$: Observable /* Viewport observable */ } -/** - * Retrieve viewport size - * - * @return Viewport size - */ -export function getViewportSize(): ViewportSize { - return { - width: innerWidth, - height: innerHeight - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch viewport offset - * - * @return Viewport offset observable - */ -export function watchViewportOffset(): Observable { - return merge( - fromEvent(window, "scroll"), - fromEvent(window, "resize") - ) - .pipe( - map(getViewportOffset), - startWith(getViewportOffset()) - ) -} - -/** - * Watch viewport size - * - * @return Viewport size observable - */ -export function watchViewportSize(): Observable { - return fromEvent(window, "resize") - .pipe( - map(getViewportSize), - startWith(getViewportSize()) - ) -} +/* ---------------------------------------------------------------------------- + * Functions + * ------------------------------------------------------------------------- */ /** * Watch viewport @@ -125,3 +76,27 @@ export function watchViewport(): Observable { shareReplay(1) ) } + +/** + * Watch viewport relative to element + * + * @param el - Element + * @param options - Options + * + * @return Viewport observable + */ +export function watchViewportFrom( + el: HTMLElement, { header$, viewport$ }: WatchRelativeOptions +): Observable { + return combineLatest([viewport$, header$]) + .pipe( + map(([{ offset, size }, { height }]) => ({ + offset: { + x: offset.x - el.offsetLeft, + y: offset.y - el.offsetTop + height + }, + size + })), + shareReplay(1) + ) +} diff --git a/src/assets/javascripts/observables/agent/viewport/index.ts b/src/assets/javascripts/observables/agent/viewport/index.ts index 0aed2e77e..7f7cd667b 100644 --- a/src/assets/javascripts/observables/agent/viewport/index.ts +++ b/src/assets/javascripts/observables/agent/viewport/index.ts @@ -21,4 +21,5 @@ */ export * from "./_" -export * from "./relative" +export * from "./offset" +export * from "./size" diff --git a/src/assets/javascripts/observables/agent/viewport/offset/index.ts b/src/assets/javascripts/observables/agent/viewport/offset/index.ts new file mode 100644 index 000000000..4a6f20e80 --- /dev/null +++ b/src/assets/javascripts/observables/agent/viewport/offset/index.ts @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2020 Martin Donath + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +import { Observable, fromEvent, merge } from "rxjs" +import { map, startWith } from "rxjs/operators" + +/* ---------------------------------------------------------------------------- + * Types + * ------------------------------------------------------------------------- */ + +/** + * Viewport offset + */ +export interface ViewportOffset { + x: number /* Horizontal offset */ + y: number /* Vertical offset */ +} + +/* ---------------------------------------------------------------------------- + * Functions + * ------------------------------------------------------------------------- */ + +/** + * Retrieve viewport offset + * + * @return Viewport offset + */ +export function getViewportOffset(): ViewportOffset { + return { + x: pageXOffset, + y: pageYOffset + } +} + +/** + * Retrieve viewport offset + * + * @param offset - Viewport offset + */ +export function setViewportOffset( + { x, y }: Partial +): void { + window.scrollTo(x || 0, y || 0) +} + +/* ------------------------------------------------------------------------- */ + +/** + * Watch viewport offset + * + * @return Viewport offset observable + */ +export function watchViewportOffset(): Observable { + return merge( + fromEvent(window, "scroll"), + fromEvent(window, "resize") + ) + .pipe( + map(getViewportOffset), + startWith(getViewportOffset()) + ) +} diff --git a/src/assets/javascripts/observables/agent/viewport/relative/index.ts b/src/assets/javascripts/observables/agent/viewport/size/index.ts similarity index 64% rename from src/assets/javascripts/observables/agent/viewport/relative/index.ts rename to src/assets/javascripts/observables/agent/viewport/size/index.ts index e281e038f..f4f6ee076 100644 --- a/src/assets/javascripts/observables/agent/viewport/relative/index.ts +++ b/src/assets/javascripts/observables/agent/viewport/size/index.ts @@ -20,22 +20,19 @@ * IN THE SOFTWARE. */ -import { Observable, combineLatest } from "rxjs" -import { map, shareReplay } from "rxjs/operators" - -import { Header } from "../../../header" -import { Viewport } from "../_" +import { Observable, combineLatest, fromEvent, merge } from "rxjs" +import { map, shareReplay, startWith } from "rxjs/operators" /* ---------------------------------------------------------------------------- - * Helper types + * Types * ------------------------------------------------------------------------- */ /** - * Watch options + * Viewport size */ -interface WatchOptions { - header$: Observable
/* Header observable */ - viewport$: Observable /* Viewport observable */ +export interface ViewportSize { + width: number /* Viewport width */ + height: number /* Viewport height */ } /* ---------------------------------------------------------------------------- @@ -43,25 +40,28 @@ interface WatchOptions { * ------------------------------------------------------------------------- */ /** - * Watch viewport relative to element + * Retrieve viewport size * - * @param el - Element - * @param options - Options - * - * @return Viewport observable + * @return Viewport size */ -export function watchViewportFrom( - el: HTMLElement, { header$, viewport$ }: WatchOptions -): Observable { - return combineLatest([viewport$, header$]) +export function getViewportSize(): ViewportSize { + return { + width: innerWidth, + height: innerHeight + } +} + +/* ------------------------------------------------------------------------- */ + +/** + * Watch viewport size + * + * @return Viewport size observable + */ +export function watchViewportSize(): Observable { + return fromEvent(window, "resize") .pipe( - map(([{ offset, size }, { height }]) => ({ - offset: { - x: offset.x - el.offsetLeft, - y: offset.y - el.offsetTop + height - }, - size - })), - shareReplay(1) + map(getViewportSize), + startWith(getViewportSize()) ) }