REFACTOR Capitalizes enumerated controllerEvents for clearer code
[wrfxweb.git] / fdds / js / components / Controller.js
blobdeab9cc759af72046e807339fc1c43a520cb2a52
1 import { debounceInIntervals } from '../util.js';
3 export const controllerEvents = {
4 QUIET: 'QUIET',
5 SIM_RESET: 'SIMULATION_RESET',
6 VALUE_SET: 'VALUE_SET',
7 SLIDING_VALUE: 'SLIDING_VALUE',
8 ALL: 'ALL'
11 /** Class that enables data binding. Allows for callback functions to subscribe to the Controller which will
12 * then be called whenever the value in the controller is updated. */
13 export class Controller {
14 constructor(value=null) {
15 this.listeners = {};
16 this.value = value;
17 this.debouncedSetValue = debounceInIntervals((setArgs) => {
18 this.setValueCallback(setArgs);
19 }, 100);
22 subscribe(callback, eventName=controllerEvents.VALUE_SET) {
23 // this.listeners.push(callback);
24 if (!(eventName in this.listeners)) {
25 this.listeners[eventName] = [];
27 this.listeners[eventName].push(callback);
30 setValue(value, eventName=controllerEvents.VALUE_SET) {
31 this.setValueCallback([value, eventName]);
34 setValueCallback([value, eventName=controllerEvents.VALUE_SET]) {
35 this.value = value;
36 if (eventName != controllerEvents.QUIET) {
37 this.notifyListeners(this.listeners[eventName]);
38 if (eventName != controllerEvents.ALL) {
39 this.notifyListeners(this.listeners[controllerEvents.ALL]);
44 getValue() {
45 return this.value;
48 notifyListeners(listeners, args=null) {
49 if (listeners == null) {
50 return;
52 listeners.map(listener => listener(args));
55 broadcastEvent(event, args=null) {
56 this.notifyListeners(this.listeners[event], args);
60 /** Class to synchronise a function call at the end of two asynchronous events.
61 * Useful for executing a function after both a layer and its colorbar have loaded. */
62 export class SyncController extends Controller {
63 constructor() {
64 super([false, false]);
67 increment(i) {
68 this.value[i] = true;
69 if (this.value[0] && this.value[1]) {
70 this.setValue([false, false]);
75 // global controllers
76 export const controllers = {
77 currentTimestamp: (function createCurrentTimestamp() {
78 var currentTimestamp = new Controller();
79 currentTimestamp.setValue = (value, eventName=controllerEvents.VALUE_SET) => {
80 currentTimestamp.debouncedSetValue([value, eventName]);
82 return currentTimestamp;
83 })(),
84 domainInstance: new Controller(),
85 currentDomain: new Controller(),
86 loadingProgress: (function createLoadProg() {
87 const loadingProgress = new Controller(0);
88 loadingProgress.nFrames = 0;
89 loadingProgress.loadedFrames = 0;
91 loadingProgress.setFrames = (nFrames) => {
92 loadingProgress.nFrames = nFrames;
93 loadingProgress.loadedFrames = 0;
94 loadingProgress.setValue(0);
97 loadingProgress.frameLoaded = (frames = 1) => {
98 loadingProgress.loadedFrames += frames;
99 var progress = loadingProgress.loadedFrames / loadingProgress.nFrames;
100 loadingProgress.setValue(progress);
103 return loadingProgress;
104 })(),
105 timeSeriesMarkers: (function createTimeSeriesMarkers() {
106 var timeSeriesMarkers = new Controller([]);
107 timeSeriesMarkers.removeEvent = 'REMOVE_EVENT';
108 timeSeriesMarkers.add = (newMarker) => {
109 timeSeriesMarkers.value.push(newMarker);
111 timeSeriesMarkers.remove = (removeMarker) => {
112 var index = timeSeriesMarkers.value.indexOf(removeMarker);
113 timeSeriesMarkers.value.splice(index, 1);
114 timeSeriesMarkers.broadcastEvent(timeSeriesMarkers.removeEvent, index);
116 return timeSeriesMarkers;
117 })(),
118 opacity: new Controller(0.5),
119 syncImageLoad: new SyncController(),
120 startDate: (function createStartDate() {
121 var startDateController = new Controller();
123 const subscriptionFunction = () => {
124 var newStartDate = startDateController.getValue();
125 var currentTimestamp = controllers.currentTimestamp.getValue();
127 if (newStartDate > currentTimestamp) {
128 controllers.currentTimestamp.setValue(newStartDate);
131 startDateController.subscribe(subscriptionFunction, controllerEvents.ALL);
132 startDateController.setValue = (value, eventName=controllerEvents.VALUE_SET) => {
133 startDateController.debouncedSetValue([value, eventName]);
136 return startDateController;
137 })(),
138 endDate: (function createEndDate() {
139 var endDateController = new Controller();
141 const subscriptionFunction = ()=> {
142 var newEndDate = endDateController.getValue();
143 var currentTimestamp = controllers.currentTimestamp.getValue();
145 if (newEndDate < currentTimestamp) {
146 controllers.currentTimestamp.setValue(newEndDate);
149 endDateController.subscribe(subscriptionFunction, controllerEvents.ALL);
150 endDateController.setValue = (value, eventName=controllerEvents.VALUE_SET) => {
151 endDateController.debouncedSetValue([value, eventName]);
154 return endDateController;
155 })(),