94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
|
module TK {
|
||
|
/**
|
||
|
* Client for Toggle object, allowing to manipulate it
|
||
|
*
|
||
|
* *state* may be:
|
||
|
* - a boolean to require on or off
|
||
|
* - a number to require on for the duration in milliseconds
|
||
|
* - undefined to switch between on and off (based on the client state, not the toggle state)
|
||
|
*
|
||
|
* The function returns the actual state after applying the requirement
|
||
|
*/
|
||
|
export type ToggleClient = (state?: boolean | number) => boolean
|
||
|
|
||
|
/**
|
||
|
* A toggle between two states (on and off).
|
||
|
*
|
||
|
* A toggle will be on if at least one ToggleClient requires it to be on.
|
||
|
*/
|
||
|
export class Toggle {
|
||
|
private on: Function
|
||
|
private off: Function
|
||
|
private status = false
|
||
|
private clients: string[] = []
|
||
|
private scheduled: { [client: string]: any } = {}
|
||
|
private timer = Timer.global
|
||
|
|
||
|
constructor(on: Function = () => null, off: Function = () => null) {
|
||
|
this.on = on;
|
||
|
this.off = off;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the current state is on
|
||
|
*/
|
||
|
isOn(): boolean {
|
||
|
return this.status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Register a client to manipulate the toggle's state
|
||
|
*/
|
||
|
manipulate(client: string): ToggleClient {
|
||
|
return state => {
|
||
|
if (this.scheduled[client]) {
|
||
|
this.timer.cancel(this.scheduled[client]);
|
||
|
this.scheduled[client] = null;
|
||
|
}
|
||
|
|
||
|
if (typeof state == "undefined") {
|
||
|
if (contains(this.clients, client)) {
|
||
|
this.stop(client);
|
||
|
} else {
|
||
|
this.start(client);
|
||
|
}
|
||
|
} else if (typeof state == "number") {
|
||
|
if (state > 0) {
|
||
|
this.start(client);
|
||
|
this.scheduled[client] = this.timer.schedule(state, () => this.stop(client));
|
||
|
} else {
|
||
|
this.stop(client);
|
||
|
}
|
||
|
} else if (!state) {
|
||
|
this.stop(client);
|
||
|
} else {
|
||
|
this.start(client);
|
||
|
}
|
||
|
return this.status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Start the toggle for a client (set the status *on*)
|
||
|
*/
|
||
|
private start(client: string) {
|
||
|
add(this.clients, client);
|
||
|
if (!this.status) {
|
||
|
this.status = true;
|
||
|
this.on();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Stop the toggle (set the status *off*)
|
||
|
*/
|
||
|
private stop(client: string) {
|
||
|
remove(this.clients, client);
|
||
|
if (this.status && this.clients.length == 0) {
|
||
|
this.status = false;
|
||
|
this.off();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|