Skip to content

Commit 9b7c47a

Browse files
committed
feat: new DOM feature HandleHashChangeFeature
This feature will send events when the hash fragment of the current URL changes. This is useful to implement in-page navigation in a WebView.
1 parent 7a158d9 commit 9b7c47a

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import linkPressScript from './HandleHashChangeFeature.webjs';
2+
import { FeatureBuilder } from '../FeatureBuilder';
3+
import type { DOMRect, PropDefinition } from '../types';
4+
import type { FeatureConstructor } from '../Feature';
5+
6+
/**
7+
* An object describing customization for the hash change feature.
8+
*
9+
* @public
10+
*/
11+
export interface HandleHashChangeOptions {
12+
/**
13+
* Reset the hash to the empty string after triggering the event.
14+
* This is recommended if you want to make sure any upcoming link press on
15+
* an anchor with a local hash `href` will trigger the `hashchange` event.
16+
*
17+
* @defaultValue false
18+
*/
19+
shouldResetHashOnEvent?: boolean;
20+
}
21+
22+
/**
23+
* A hash change event.
24+
*
25+
* @public
26+
*/
27+
export interface HashChangeEvent {
28+
/**
29+
* The hash (“#” included).
30+
*/
31+
hash: string;
32+
/**
33+
* The bounding rectangle of the element targeted by hash.
34+
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect | Element.getBoundingClientRect()}
35+
*/
36+
targetElementBoundingRect: DOMRect;
37+
}
38+
39+
const defaultOptions: HandleHashChangeOptions = {
40+
shouldResetHashOnEvent: false
41+
};
42+
43+
/**
44+
* This feature allows to intercept clicks on anchors (`<a>`). By default, it
45+
* will prevent the click from propagating. But you can disable this option.
46+
*
47+
* @public
48+
*/
49+
export const HandleHashChangeFeature: FeatureConstructor<
50+
HandleHashChangeOptions,
51+
[PropDefinition<{ onDOMHashChange?: (e: HashChangeEvent) => void }>]
52+
> = new FeatureBuilder({
53+
script: linkPressScript,
54+
defaultOptions,
55+
className: 'HandleHashChangeFeature',
56+
featureIdentifier: 'org.formidable-webview/webshell.handle-hash-change'
57+
})
58+
.withEventHandlerProp<HashChangeEvent, 'onDOMHashChange'>('onDOMHashChange')
59+
.build();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
function HandleHashChangeFeature(context) {
2+
var postMessage = context.postMessage;
3+
var options = context.options || {};
4+
var shouldResetHashOnEvent = !!options.shouldResetHashOnEvent;
5+
var handleHashChangeEvent = context.makeCallbackSafe(function () {
6+
var newhash = document.location.hash;
7+
var name = newhash.substr(1);
8+
var targetEl =
9+
document.getElementById(name) ||
10+
document.querySelector('a[name="' + name + '"]');
11+
shouldResetHashOnEvent && (document.location.hash = '');
12+
if (targetEl) {
13+
var rect = targetEl.getBoundingClientRect();
14+
var targetElementBoundingRect = {
15+
x: rect.x,
16+
y: rect.y,
17+
top: rect.top,
18+
left: rect.left,
19+
bottom: rect.bottom,
20+
right: rect.right,
21+
width: rect.width,
22+
height: rect.height
23+
};
24+
postMessage({
25+
hash: newhash,
26+
targetElementBoundingRect: targetElementBoundingRect
27+
});
28+
}
29+
});
30+
window.addEventListener('hashchange', handleHashChangeEvent);
31+
}

0 commit comments

Comments
 (0)