Skip to content

Instantly share code, notes, and snippets.

@jdanyow
Forked from AquilaSands/app.html
Last active December 10, 2017 22:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdanyow/e85d11d7d7098c641162c3362ff15bbb to your computer and use it in GitHub Desktop.
Save jdanyow/e85d11d7d7098c641162c3362ff15bbb to your computer and use it in GitHub Desktop.
Aurelia Gist
<template>
<require from="./outer"></require>
<require from="./inner"></require>
<h1>${message}</h1>
<outer><inner></inner></outer>
</template>
import './event-manager';
export class App {
message = 'Hello World!';
}
import {DOM} from 'aurelia-pal';
import {EventManager, delegationStrategy} from 'aurelia-binding';
import {Container} from 'aurelia-dependency-injection';
//Note: path and deepPath are designed to handle v0 and v1 shadow dom specs respectively
function findOriginalEventTarget(event) {
return (event.path && event.path[0]) || (event.deepPath && event.deepPath[0]) || event.target;
}
function stopPropagation() {
this.standardStopPropagation();
this.propagationStopped = true;
}
function handleCapturedEvent(event) {
event.propagationStopped = false;
let target = findOriginalEventTarget(event);
let orderedCallbacks = [];
/**
* During capturing phase, event 'bubbles' down from parent. Needs to reorder callback from root down to target
*/
while (target) {
if (target.capturedCallbacks) {
let callback = target.capturedCallbacks[event.type];
if (callback) {
if (event.stopPropagation !== stopPropagation) {
event.standardStopPropagation = event.stopPropagation;
event.stopPropagation = stopPropagation;
}
orderedCallbacks.push(callback);
}
}
target = target.parentNode;
}
for (let i = orderedCallbacks.length - 1; i >= 0 && !event.propagationStopped; i--) {
let orderedCallback = orderedCallbacks[i];
if ('handleEvent' in orderedCallback) {
orderedCallback.handleEvent(event);
} else {
orderedCallback(event);
}
}
}
class CapturedHandlerEntry {
constructor(eventName) {
this.eventName = eventName;
this.count = 0;
}
increment() {
this.count++;
if (this.count === 1) {
DOM.addEventListener(this.eventName, handleCapturedEvent, true);
}
}
decrement() {
this.count--;
if (this.count === 0) {
DOM.removeEventListener(this.eventName, handleCapturedEvent, true);
}
}
}
function handleDelegatedEvent(event) {
event.propagationStopped = false;
let target = findOriginalEventTarget(event);
while (target && !event.propagationStopped) {
if (target.delegatedCallbacks) {
let callback = target.delegatedCallbacks[event.type];
if (callback) {
if (event.stopPropagation !== stopPropagation) {
event.standardStopPropagation = event.stopPropagation;
event.stopPropagation = stopPropagation;
}
if ('handleEvent' in callback) {
callback.handleEvent(event);
} else {
callback(event);
}
}
}
target = target.parentNode;
}
}
class DelegateHandlerEntry {
constructor(eventName) {
this.eventName = eventName;
this.count = 0;
}
increment() {
this.count++;
if (this.count === 1) {
DOM.addEventListener(this.eventName, handleDelegatedEvent, false);
}
}
decrement() {
this.count--;
if (this.count === 0) {
DOM.removeEventListener(this.eventName, handleDelegatedEvent);
}
}
}
class DefaultEventStrategy {
delegatedHandlers = {};
capturedHandlers = {};
subscribe(target, targetEvent, callback, strategy) {
let delegatedHandlers;
let capturedHandlers;
let handlerEntry;
if (strategy === delegationStrategy.bubbling) {
delegatedHandlers = this.delegatedHandlers;
handlerEntry = delegatedHandlers[targetEvent] || (delegatedHandlers[targetEvent] = new DelegateHandlerEntry(targetEvent));
let delegatedCallbacks = target.delegatedCallbacks || (target.delegatedCallbacks = {});
handlerEntry.increment();
delegatedCallbacks[targetEvent] = callback;
return function() {
handlerEntry.decrement();
delegatedCallbacks[targetEvent] = null;
};
}
if (strategy === delegationStrategy.capturing) {
capturedHandlers = this.capturedHandlers;
handlerEntry = capturedHandlers[targetEvent] || (capturedHandlers[targetEvent] = new CapturedHandlerEntry(targetEvent));
let capturedCallbacks = target.capturedCallbacks || (target.capturedCallbacks = {});
handlerEntry.increment();
capturedCallbacks[targetEvent] = callback;
return function() {
handlerEntry.decrement();
capturedCallbacks[targetEvent] = null;
};
}
target.addEventListener(targetEvent, callback, false);
return function() {
target.removeEventListener(targetEvent, callback);
};
}
}
Container.instance.get(EventManager).defaultEventStrategy = new DefaultEventStrategy();
<!doctype html>
<html>
<head>
<title>Aurelia</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body aurelia-app>
<h1>Loading...</h1>
<script src="https://jdanyow.github.io/rjs-bundle/node_modules/requirejs/require.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/config.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/aurelia.js"></script>
<script src="https://jdanyow.github.io/rjs-bundle/bundles/babel.js"></script>
<script>
require(['aurelia-bootstrapper']);
</script>
</body>
</html>
.inner {
height: 100%;
width: 100px;
background-color: #efefef;
border: 1px solid blue;
margin: 0 auto;
}
<template>
<require from="./inner.css"></require>
<div class="inner" click.delegate="innerClick($event)">
<p>Inner content</p>
<a href="https://www.google.co.uk" target="_blank" rel="noreferrer noopener">Google</a>
</div>
</template>
export class Inner {
innerClick = (evt) => {
if (evt.target instanceof HTMLAnchorElement) {
// allow hyperlink
console.log("inner propagation stopped");
evt.stopPropagation();
return true;
} else {
// do default card action
console.log("inner click allowed");
}
}
}
.outer {
height: 250px;
width: 400px;
background-color: #ababab;
border: 1px solid red;
}
<template>
<require from="./outer.css"></require>
<div class="outer" click.capture="outerClick($event)">
<slot></slot>
</div>
</template>
export class Outer {
outerClick = (evt) => {
console.log("outer clicked");
//return true; // uncomment to allow link navigation
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment