Typescriptify ResizeChecker and render complete (#20531) (#20550)

* Typescriptify ResizeChecker and render complete

* Simplify getSize method
This commit is contained in:
Tim Roes 2018-07-09 13:41:21 +02:00 committed by GitHub
parent 167b29b2b0
commit a2c33a5b33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 62 deletions

View file

@ -234,6 +234,7 @@
"@types/getopts": "^2.0.0",
"@types/glob": "^5.0.35",
"@types/jest": "^22.2.3",
"@types/jquery": "3.3.1",
"@types/listr": "^0.13.0",
"@types/lodash": "^3.10.1",
"@types/minimatch": "^2.0.29",

View file

@ -19,18 +19,18 @@
import './directive';
const dispatchCustomEvent = (el, eventName) => {
// we're using the native events so that we aren't tied to the jQuery custom events,
const dispatchCustomEvent = (el: HTMLElement, eventName: string) => {
// we're using the native events so that we aren't tied to the jQuery custom events,
// otherwise we have to use jQuery(element).on(...) because jQuery's events sit on top
// of the native events per https://github.com/jquery/jquery/issues/2476
el.dispatchEvent(new CustomEvent(eventName, { bubbles: true }));
};
export function dispatchRenderComplete(el) {
export function dispatchRenderComplete(el: HTMLElement) {
dispatchCustomEvent(el, 'renderComplete');
}
export function dispatchRenderStart(el) {
export function dispatchRenderStart(el: HTMLElement) {
dispatchCustomEvent(el, 'renderStart');
}

View file

@ -20,34 +20,33 @@
const attributeName = 'data-render-complete';
export class RenderCompleteHelper {
constructor(element) {
this._element = element;
constructor(private readonly element: HTMLElement) {
this.setup();
}
_start = () => {
this._element.setAttribute(attributeName, false);
return true;
};
public destroy() {
this.element.removeEventListener('renderStart', this.start);
this.element.removeEventListener('renderComplete', this.complete);
}
_complete = () => {
this._element.setAttribute(attributeName, true);
return true;
};
public setup() {
this.element.setAttribute(attributeName, 'false');
this.element.addEventListener('renderStart', this.start);
this.element.addEventListener('renderComplete', this.complete);
}
destroy = () => {
this._element.removeEventListener('renderStart', this._start);
this._element.removeEventListener('renderComplete', this._complete);
};
setup = () => {
this._element.setAttribute(attributeName, false);
this._element.addEventListener('renderStart', this._start);
this._element.addEventListener('renderComplete', this._complete);
};
disable = () => {
this._element.setAttribute(attributeName, 'disabled');
public disable() {
this.element.setAttribute(attributeName, 'disabled');
this.destroy();
}
private start = () => {
this.element.setAttribute(attributeName, 'false');
return true;
};
private complete = () => {
this.element.setAttribute(attributeName, 'true');
return true;
};
}

View file

@ -17,25 +17,26 @@
* under the License.
*/
import { EventEmitter } from 'events';
import $ from 'jquery';
import ResizeObserver from 'resize-observer-polyfill';
import { isEqual } from 'lodash';
import EventEmitter from 'events';
import ResizeObserver from 'resize-observer-polyfill';
function validateElArg(el) {
function validateElArg(el: HTMLElement) {
// the ResizeChecker historically accepted jquery elements,
// so we wrap in jQuery then extract the element
const $el = $(el);
if ($el.length !== 1) {
throw new TypeError('ResizeChecker must be constructed with a single DOM element.');
throw new TypeError(
'ResizeChecker must be constructed with a single DOM element.'
);
}
return $el.get(0);
}
function getSize(el) {
function getSize(el: HTMLElement): [number, number] {
return [el.clientWidth, el.clientHeight];
}
@ -43,15 +44,20 @@ function getSize(el) {
* ResizeChecker receives an element and emits a "resize" event every time it changes size.
*/
export class ResizeChecker extends EventEmitter {
constructor(el, args = {}) {
private destroyed: boolean = false;
private el: HTMLElement | null;
private observer: ResizeObserver | null;
private expectedSize: [number, number] | null = null;
constructor(el: HTMLElement, args: { disabled?: boolean } = {}) {
super();
this._el = validateElArg(el);
this.el = validateElArg(el);
this._observer = new ResizeObserver(() => {
if (this._expectedSize) {
const sameSize = isEqual(getSize(this._el), this._expectedSize);
this._expectedSize = null;
this.observer = new ResizeObserver(() => {
if (this.expectedSize) {
const sameSize = isEqual(getSize(el), this.expectedSize);
this.expectedSize = null;
if (sameSize) {
// don't trigger resize notification if the size is what we expect
@ -68,49 +74,49 @@ export class ResizeChecker extends EventEmitter {
}
}
enable() {
if (this._destroyed) {
public enable() {
if (this.destroyed) {
// Don't allow enabling an already destroyed resize checker
return;
}
// the width and height of the element that we expect to see
// on the next resize notification. If it matches the size at
// the time of starting observing then it we will be ignored.
this._expectedSize = getSize(this._el);
this._observer.observe(this._el);
// We know that observer and el are not null since we are not yet destroyed.
this.expectedSize = getSize(this.el!);
this.observer!.observe(this.el!);
}
/**
* Run a function and ignore all resizes that occur
* while it's running.
*
* @return {undefined}
*/
modifySizeWithoutTriggeringResize(block) {
public modifySizeWithoutTriggeringResize(block: () => void): void {
try {
block();
} finally {
this._expectedSize = getSize(this._el);
if (this.el) {
this.expectedSize = getSize(this.el);
}
}
}
/**
* Tell the ResizeChecker to shutdown, stop listenings, and never
* emit another resize event.
*
* Cleans up it's listeners and timers.
*
* @method destroy
* @return {void}
*/
destroy() {
if (this._destroyed) return;
this._destroyed = true;
* Tell the ResizeChecker to shutdown, stop listenings, and never
* emit another resize event.
*
* Cleans up it's listeners and timers.
*/
public destroy(): void {
if (this.destroyed) {
return;
}
this.destroyed = true;
this._observer.disconnect();
this._observer = null;
this._expectedSize = null;
this._el = null;
this.observer!.disconnect();
this.observer = null;
this.expectedSize = null;
this.el = null;
this.removeAllListeners();
}
}

View file

@ -330,6 +330,10 @@
version "22.2.3"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-22.2.3.tgz#0157c0316dc3722c43a7b71de3fdf3acbccef10d"
"@types/jquery@3.3.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.1.tgz#55758d44d422756d6329cbf54e6d41931d7ba28f"
"@types/json-schema@*":
version "6.0.1"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-6.0.1.tgz#a761975746f1c1b2579c62e3a4b5e88f986f7e2e"