Skip to content

Instantly share code, notes, and snippets.

@3cp
Forked from bigopon/index.html
Created April 4, 2020 13:01
Show Gist options
  • Save 3cp/b2a721bf90efd9f99ac3ee13a10554b1 to your computer and use it in GitHub Desktop.
Save 3cp/b2a721bf90efd9f99ac3ee13a10554b1 to your computer and use it in GitHub Desktop.
Aurelia Size custom attribute
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dumber Gist</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<base href="/">
</head>
<!--
Dumber gist uses dumber bundler, the default bundle file
is /dist/entry-bundle.js.
The starting module is pointed to aurelia-bootstrapper
(data-main attribute on script) for Aurelia,
The aurelia bootstrapper then loads up user module "main"
(aurelia-app attribute on <body>) which is your src/main.js.
-->
<body aurelia-app="main">
<script src="/dist/entry-bundle.js" data-main="aurelia-bootstrapper"></script>
</body>
</html>
{
"dependencies": {
"aurelia-bootstrapper": "^2.3.3"
}
}
<template>
<require from="./size-observer"></require>
<style>textarea { display: block; }</style>
<!-- Try to create a css/scss/sass/less file then require it here -->
<h1>${message}</h1>
Width: ${size.width || 0} -- Height: ${size.height || 0}
<hr>
<textarea size.bind="size"></textarea>
<!-- <let/> -->
<h1>
Observing size in a reapeat with &lt;let/&gt;
</h1>
<div repeat.for="i of 5">
<let $size.bind="null"></let>
Width: ${$size.width} -- Height: ${$size.height}
<textarea size.bind="$size"></textarea>
</div>
</template>
export class App {
message = 'Hello Aurelia!';
}
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging('info');
aurelia.start().then(() => aurelia.setRoot());
}
import { DOM, customAttribute, bindingMode } from 'aurelia-framework';
@customAttribute('size', bindingMode.fromView)
export class SizeCustomAttribute {
static inject() {
return [DOM.Element];
}
constructor(el) {
this.el = el;
}
bind() {
this.observer = this.getObserver();
this.observer.observe(this.el);
}
unbind() {
this.observer.disconnect();
this.observer = void 0;
}
getObserver(el) {
if (typeof ResizeObserver === 'function') {
return new ResizeObserver(records => {
const rect = records[0].contentRect;
this.value = { width: rect.width, height: rect.height };
});
return observer;
} else {
return new ElementSizeDirtyChecker(size => {
this.value = size;
});
}
}
}
// the interface of this class is kept similar to ResizeObserver
class ElementSizeDirtyChecker {
constructor(callback, rate = 330 /*3 times a second*/) {
this.callback = callback;
this.rate = rate;
this.size = { width: 0, height: 0 };
}
observe(el) {
this.timerId = setInterval(() => {
const { width, height } = el.getBoundingClientRect();
const currentSize = this.size;
if (width !== currentSize.width || height !== currentSize.height) {
this.size = { width: rect.width, height: rect.height };
if (typeof this.callback === 'function') {
this.callback(this.size);
}
}
}, this.rate);
}
disconnect() {
clearInterval(this.timerId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment