Niedzielski has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/392570 )
Change subject: Update: capture wiki link clicks and navigation ...................................................................... Update: capture wiki link clicks and navigation Extract Link.onClick to link-on-click#onClick and use in ContentSection so that visiting wiki pages only loads the minimal content needed inline. Bug: T177367 Change-Id: I5175d9473c128fce87820e9d11788db7b4dd6df1 --- M package.json M src/common/components/content-section/content-section.tsx A src/common/components/link-on-click.ts M src/common/components/link.tsx 4 files changed, 58 insertions(+), 38 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/marvin refs/changes/70/392570/1 diff --git a/package.json b/package.json index 2ff5df7..33ff1af 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "bundlesize": [ { "path": "dist/public/index.*.js", - "maxSize": "3.1KB" + "maxSize": "3.2KB" }, { "path": "dist/public/runtime.*.js", diff --git a/src/common/components/content-section/content-section.tsx b/src/common/components/content-section/content-section.tsx index a87ad83..601fa17 100644 --- a/src/common/components/content-section/content-section.tsx +++ b/src/common/components/content-section/content-section.tsx @@ -1,16 +1,25 @@ +import { History } from "history"; import { h } from "preact"; import { PageSection } from "../../models/page/page"; import Content from "../content/content"; import DynamicHeader from "../dynamic-header/dynamic-header"; +import { onClick } from "../link-on-click"; import "./content-section.css"; export interface Props { section: PageSection; } -export default function ContentSection({ section }: Props): JSX.Element { +export default function ContentSection( + { section }: Props, + context: { history?: History } +): JSX.Element { return ( - <section class="ContentSection" id={section.fragment}> + <section + onClick={event => onClick(context, event)} + class="ContentSection" + id={section.fragment} + > {section.titleHTML && ( // Omit empty headers such as the lead. <DynamicHeader class="ContentSection-header" level={section.level + 1}> <Content dangerouslySetInnerHTML={{ __html: section.titleHTML }} /> diff --git a/src/common/components/link-on-click.ts b/src/common/components/link-on-click.ts new file mode 100644 index 0000000..85c6cc4 --- /dev/null +++ b/src/common/components/link-on-click.ts @@ -0,0 +1,43 @@ +import { History } from "history"; + +function isModifiedEvent(event: MouseEvent): boolean { + return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey; +} + +function isInternalLink(link: HTMLAnchorElement) { + // N.B. link.href is used because browsers will transform relative paths to + // the full path when set on the HTML anchor, which is what is used to check + // against the current origin. + return link.href && link.href.indexOf(window.location.origin) === 0; +} + +// TODO: add unit tests +export function onClick( + context: { history?: History }, + event: MouseEvent +): void { + // When set on an anchor, currentTarget is the anchor. When set on a parent to + // capture all clicks, currentTarget may be something else. Use target and + // walk the DOM inclusively upwards until an anchor is found. + const link = (event.target as HTMLElement).closest( + "a" + ) as HTMLAnchorElement | null; + if ( + link && + isInternalLink(link) && + // onClick not prevented default + !event.defaultPrevented && + // Ignore everything but left clicks + event.button === 0 && + // Let browser handle "target=_blank" etc. + !link.target && + // Ignore clicks with modifier keys + !isModifiedEvent(event) && + // We have a context history + context.history + ) { + event.preventDefault(); + const path = link.href.replace(window.location.origin, ""); + context.history.push(path); + } +} diff --git a/src/common/components/link.tsx b/src/common/components/link.tsx index 75ec31c..668fb96 100644 --- a/src/common/components/link.tsx +++ b/src/common/components/link.tsx @@ -1,13 +1,10 @@ -import { h } from "preact"; import { History } from "history"; +import { h } from "preact"; import { ChildrenProps, classOf, ClassProps } from "./preact-utils"; +import { onClick } from "./link-on-click"; export interface Props extends ClassProps, ChildrenProps { href: string; -} - -function isModifiedEvent(event: MouseEvent): boolean { - return event.metaKey || event.altKey || event.ctrlKey || event.shiftKey; } /** @@ -22,36 +19,7 @@ <a class={classOf("Link", props.class)} href={href} - onClick={event => { - const origin = window.location.origin; - // Use currentTarget as target may be other DOM elements inside the - // anchor element - const link = event.currentTarget as HTMLAnchorElement; - // TODO: Move all the logic to check if an event should be captured to a - // DOM utilities module and add unit tests - if ( - // Check if the href is internal - // - // N.B. link.href is used because browsers will transform relative - // paths to the full path when set on the HTML anchor, which is what - // is used to check against the current origin - link.href && - link.href.indexOf(origin) === 0 && - // onClick not prevented default - !event.defaultPrevented && - // Ignore everything but left clicks - event.button === 0 && - // Let browser handle "target=_blank" etc. - !link.target && - // Ignore clicks with modifier keys - !isModifiedEvent(event) && - // We have a context history - context.history - ) { - event.preventDefault(); - context.history.push(href); - } - }} + onClick={event => onClick(context, event)} > {children} </a> -- To view, visit https://gerrit.wikimedia.org/r/392570 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5175d9473c128fce87820e9d11788db7b4dd6df1 Gerrit-PatchSet: 1 Gerrit-Project: marvin Gerrit-Branch: master Gerrit-Owner: Niedzielski <sniedziel...@wikimedia.org> Gerrit-Reviewer: Sniedzielski <sniedziel...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits