Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
liamwhite committed Mar 17, 2024
1 parent 3cc9e90 commit ab4198c
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 43 deletions.
26 changes: 14 additions & 12 deletions assets/js/burger.js → assets/js/burger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,38 @@
* Hamburger menu.
*/

function switchClasses(element, oldClass, newClass) {
import { assertNotNull, assertType } from './utils/assert';

function switchClasses(element: HTMLElement, oldClass: string, newClass: string) {
element.classList.remove(oldClass);
element.classList.add(newClass);
}

function open(burger, content, body, root) {
function open(burger: HTMLElement, content: HTMLElement, body: HTMLElement, root: HTMLElement) {
switchClasses(content, 'close', 'open');
switchClasses(burger, 'close', 'open');

root.classList.add('no-overflow-x');
body.classList.add('no-overflow');
}

function close(burger, content, body, root) {
function close(burger: HTMLElement, content: HTMLElement, body: HTMLElement, root: HTMLElement) {
switchClasses(content, 'open', 'close');
switchClasses(burger, 'open', 'close');

/* the CSS animation closing the menu finishes in 300ms */
// The CSS animation closing the menu finishes in 300ms
setTimeout(() => {
root.classList.remove('no-overflow-x');
body.classList.remove('no-overflow');
}, 300);
}

function copyArtistLinksTo(burger) {
const copy = links => {
function copyArtistLinksTo(burger: HTMLElement) {
const copy = (links: HTMLCollection) => {
burger.appendChild(document.createElement('hr'));

[].slice.call(links).forEach(link => {
const burgerLink = link.cloneNode(true);
[...links].forEach(link => {
const burgerLink = assertType(link.cloneNode(true), HTMLElement);

burgerLink.className = '';
burger.appendChild(burgerLink);
Expand All @@ -40,13 +42,13 @@ function copyArtistLinksTo(burger) {

const linksContainers = document.querySelectorAll('.js-burger-links');

[].slice.call(linksContainers).forEach(container => copy(container.children));
[...linksContainers].forEach(container => copy(container.children));
}

function setupBurgerMenu() {
const burger = document.getElementById('burger');
const toggle = document.getElementById('js-burger-toggle');
const content = document.getElementById('container');
const burger = assertNotNull(document.getElementById('burger'));
const toggle = assertNotNull(document.getElementById('js-burger-toggle'));
const content = assertNotNull(document.getElementById('container'));
const body = document.body;
const root = document.documentElement;

Expand Down
11 changes: 0 additions & 11 deletions assets/js/cable.js

This file was deleted.

13 changes: 8 additions & 5 deletions assets/js/captcha.js → assets/js/captcha.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { delegate, leftClick } from './utils/events';
import { clearEl, makeEl } from './utils/dom';

function insertCaptcha(_event, target) {
const { parentNode, dataset: { sitekey } } = target;
function insertCaptcha(_event: Event, target: HTMLElement) {
const { parentElement, dataset: { sitekey } } = target;
if (!parentElement) {
throw new Error('Captcha target not found');
}

const script = makeEl('script', {src: 'https://hcaptcha.com/1/api.js', async: true, defer: true});
const frame = makeEl('div', {className: 'h-captcha'});

frame.dataset.sitekey = sitekey;

clearEl(parentNode);
clearEl(parentElement);

parentNode.insertAdjacentElement('beforeend', frame);
parentNode.insertAdjacentElement('beforeend', script);
parentElement.insertAdjacentElement('beforeend', frame);
parentElement.insertAdjacentElement('beforeend', script);
}

export function bindCaptchaLinks() {
Expand Down
22 changes: 14 additions & 8 deletions assets/js/duplicate_reports.js → assets/js/duplicate_reports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,40 @@
* Interactive behavior for duplicate reports.
*/

import { assertNotNull, assertType } from './utils/assert';
import { $, $$ } from './utils/dom';

function setupDupeReports() {
const [ onion, slider ] = $$('.onion-skin__image, .onion-skin__slider');
const swipe = $('.swipe__image');

if (swipe) setupSwipe(swipe);
if (onion) setupOnionSkin(onion, slider);
if (swipe) {
setupSwipe(assertType(swipe, SVGSVGElement));
}

if (onion) {
setupOnionSkin(assertType(onion, SVGSVGElement), assertType(slider, HTMLInputElement));
}
}

function setupSwipe(swipe) {
function setupSwipe(swipe: SVGSVGElement) {
const [ clip, divider ] = $$('#clip rect, #divider', swipe);
const { width } = swipe.viewBox.baseVal;

function moveDivider({ clientX }) {
function moveDivider({ clientX }: { clientX: number }) {
// Move center to cursor
const rect = swipe.getBoundingClientRect();
const newX = (clientX - rect.left) * (width / rect.width);

divider.setAttribute('x', newX);
clip.setAttribute('width', newX);
divider.setAttribute('x', `${newX}`);
clip.setAttribute('width', `${newX}`);
}

swipe.addEventListener('mousemove', moveDivider);
}

function setupOnionSkin(onion, slider) {
const target = $('#target', onion);
function setupOnionSkin(onion: SVGSVGElement, slider: HTMLInputElement) {
const target = assertNotNull($('#target', onion));

function setOpacity() {
target.setAttribute('opacity', slider.value);
Expand Down
12 changes: 6 additions & 6 deletions assets/js/notifications.js → assets/js/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { fetchJson, handleError } from './utils/requests';
import { $ } from './utils/dom';
import { delegate } from './utils/events';
import store from './utils/store';
import { assertNotNull } from './utils/assert';

const NOTIFICATION_INTERVAL = 600000,
NOTIFICATION_EXPIRES = 300000;
const notificationInterval = 600000;

function makeRequest(verb) {
return fetchJson(verb, '/notifications/unread').then(handleError);
Expand All @@ -17,7 +17,7 @@ function makeRequest(verb) {
function bindSubscriptionLinks() {
delegate(document, 'fetchcomplete', {
'.js-subscription-link': event => {
const target = event.target.closest('.js-subscription-target');
const target = assertNotNull(event.target).closest('.js-subscription-target');
event.detail.text().then(text => {
target.outerHTML = text;
});
Expand All @@ -34,7 +34,7 @@ function getNewNotifications() {
updateNotificationTicker(notifications);
storeNotificationCount(notifications);

setTimeout(getNewNotifications, NOTIFICATION_INTERVAL);
setTimeout(getNewNotifications, notificationInterval);
});
}

Expand All @@ -49,15 +49,15 @@ function updateNotificationTicker(notificationCount) {

function storeNotificationCount(notificationCount) {
// The current number of notifications are stored along with the time when the data expires
store.setWithExpireTime('notificationCount', notificationCount, NOTIFICATION_EXPIRES);
store.setWithExpireTime('notificationCount', notificationCount, notificationTtl);
}


function setupNotifications() {
if (!window.booru.userIsSignedIn) return;

// Fetch notifications from the server at a regular interval
setTimeout(getNewNotifications, NOTIFICATION_INTERVAL);
setTimeout(getNewNotifications, notificationInterval);

// Update the current number of notifications based on the latest page load
storeNotificationCount($('.js-notification-ticker').dataset.notificationCount);
Expand Down
26 changes: 26 additions & 0 deletions assets/js/utils/assert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export function assertNotNull<T>(value: T | null): T {
if (value === null) {
throw new Error('Expected non-null value');
}

return value;
}

export function assertNotUndefined<T>(value: T | undefined): T {
// eslint-disable-next-line no-undefined
if (value === undefined) {
throw new Error('Expected non-undefined value');
}

return value;
}

type Constructor<T> = { new (...args: any[]): T };

Check warning on line 18 in assets/js/utils/assert.ts

View workflow job for this annotation

GitHub Actions / JavaScript Linting and Unit Tests

Unexpected any. Specify a different type

Check warning on line 18 in assets/js/utils/assert.ts

View workflow job for this annotation

GitHub Actions / JavaScript Linting and Unit Tests

Unexpected any. Specify a different type

export function assertType<T>(value: any, c: Constructor<T>): T {

Check warning on line 20 in assets/js/utils/assert.ts

View workflow job for this annotation

GitHub Actions / JavaScript Linting and Unit Tests

Unexpected any. Specify a different type

Check warning on line 20 in assets/js/utils/assert.ts

View workflow job for this annotation

GitHub Actions / JavaScript Linting and Unit Tests

Unexpected any. Specify a different type
if (value instanceof c) {
return value;
}

throw new Error(`Expected value of type '${c}'`);
}
3 changes: 2 additions & 1 deletion assets/js/utils/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export interface PhilomenaAvailableEventsMap {
drop: DragEvent,
click: MouseEvent,
submit: Event,
reset: Event
reset: Event,
fetchcomplete: CustomEvent,
}

export interface PhilomenaEventElement {
Expand Down

0 comments on commit ab4198c

Please sign in to comment.