Skip to content

Commit

Permalink
feat: new DOM feature HandleHashChangeFeature
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jsamr committed Sep 25, 2020
1 parent 7a158d9 commit 9b7c47a
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 0 deletions.
59 changes: 59 additions & 0 deletions packages/core/src/features/HandleHashChangeFeature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import linkPressScript from './HandleHashChangeFeature.webjs';
import { FeatureBuilder } from '../FeatureBuilder';
import type { DOMRect, PropDefinition } from '../types';
import type { FeatureConstructor } from '../Feature';

/**
* An object describing customization for the hash change feature.
*
* @public
*/
export interface HandleHashChangeOptions {
/**
* Reset the hash to the empty string after triggering the event.
* This is recommended if you want to make sure any upcoming link press on
* an anchor with a local hash `href` will trigger the `hashchange` event.
*
* @defaultValue false
*/
shouldResetHashOnEvent?: boolean;
}

/**
* A hash change event.
*
* @public
*/
export interface HashChangeEvent {
/**
* The hash (“#” included).
*/
hash: string;
/**
* The bounding rectangle of the element targeted by hash.
* See {@link https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect | Element.getBoundingClientRect()}
*/
targetElementBoundingRect: DOMRect;
}

const defaultOptions: HandleHashChangeOptions = {
shouldResetHashOnEvent: false
};

/**
* This feature allows to intercept clicks on anchors (`<a>`). By default, it
* will prevent the click from propagating. But you can disable this option.
*
* @public
*/
export const HandleHashChangeFeature: FeatureConstructor<
HandleHashChangeOptions,
[PropDefinition<{ onDOMHashChange?: (e: HashChangeEvent) => void }>]
> = new FeatureBuilder({
script: linkPressScript,
defaultOptions,
className: 'HandleHashChangeFeature',
featureIdentifier: 'org.formidable-webview/webshell.handle-hash-change'
})
.withEventHandlerProp<HashChangeEvent, 'onDOMHashChange'>('onDOMHashChange')
.build();
31 changes: 31 additions & 0 deletions packages/core/src/features/HandleHashChangeFeature.webjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function HandleHashChangeFeature(context) {
var postMessage = context.postMessage;
var options = context.options || {};
var shouldResetHashOnEvent = !!options.shouldResetHashOnEvent;
var handleHashChangeEvent = context.makeCallbackSafe(function () {
var newhash = document.location.hash;
var name = newhash.substr(1);
var targetEl =
document.getElementById(name) ||
document.querySelector('a[name="' + name + '"]');
shouldResetHashOnEvent && (document.location.hash = '');
if (targetEl) {
var rect = targetEl.getBoundingClientRect();
var targetElementBoundingRect = {
x: rect.x,
y: rect.y,
top: rect.top,
left: rect.left,
bottom: rect.bottom,
right: rect.right,
width: rect.width,
height: rect.height
};
postMessage({
hash: newhash,
targetElementBoundingRect: targetElementBoundingRect
});
}
});
window.addEventListener('hashchange', handleHashChangeEvent);
}

0 comments on commit 9b7c47a

Please sign in to comment.