This repository has been archived on 2022-09-16. You can view files and clone it, but cannot push or open issues/pull-requests.
tlaternet-templates/src/index.ts

120 lines
3.1 KiB
TypeScript

import jQuery from "jquery";
// Helpers
/**
* "Types" out a DOM element, emulating the way a human might.
*/
class Typer {
private element: JQuery;
private text: string;
private cursor: boolean;
private typed: number;
private min: number;
private max: number;
private blink_tick: number;
private blink_timeout: number;
private end?: number;
/**
* Create the typer.
* @param {HTMLElement} element - The element to type.
* @param {number} blink - The time between cursor blinks.
* @param {number} blink_timeout - How long the cursor should keep
* blinking for after the text
* finishes typing.
*/
constructor(element: JQuery<HTMLElement>, blink: number, blink_timeout: number) {
// Retrieve the current content and wipe it. We also make the
// element visible if it was hidden.
this.element = element;
this.text = this.element.html();
this.element.html("");
this.element.css("visibility", "visible");
this.cursor = false;
this.typed = 0;
this.min = 20;
this.max = 70;
this.blink_tick = blink;
this.blink_timeout = blink_timeout;
this.end = null;
}
/**
* Start typing.
*/
type() {
this._type();
this._blink();
}
/**
* Draw the current text line, i.e., anything that has been typed
* so far, and a cursor if it is currently supposed to be on.
* @private
*/
_draw() {
let text = this.text.slice(0, this.typed);
if (this.cursor) {
text += "\u2588";
}
window.requestAnimationFrame(() => this.element.html(text));
}
/**
* Type the next character, and prepare to draw the next one. If
* no new characters are to be drawn, set the end timestamp.
* @private
*/
_type() {
this.typed += 1;
this._draw();
if (this.typed != this.text.length)
setTimeout(this._type.bind(this), this._type_tick());
else {
this.end = Date.now();
}
}
/**
* Make the cursor change blink status, and prepare for the next
* blink.
* @private
*/
_blink() {
this.cursor = !this.cursor;
this._draw();
// As long as we are typing, keep blinking
if (this.typed != this.text.length)
setTimeout(this._blink.bind(this), this.blink_tick);
// Once typing ends, keep going for a little bit
else if (Date.now() - this.end < this.blink_timeout)
setTimeout(this._blink.bind(this), this.blink_tick);
// Make sure we get rid of the cursor in the end
else {
this.cursor = true;
setTimeout(this._blink.bind(this), this.blink_tick);
}
}
/**
* Calculate a "human" time for the next character to type.
* @private
*/
_type_tick() {
return Math.round(Math.random() * this.max) + this.min;
}
}
jQuery(($) => {
const typer = new Typer($(".head-line .typed").first(), 500, 3000);
typer.type();
});