blob: a4254d6a6b159acb2d4be8150f0b58e83e342187 [file] [log] [blame]
Akron308a6032019-12-05 16:27:34 +01001/**
2 * Create a state object, that can have a single value
3 * (mostly boolean) and multiple objects associated to it.
4 * Whenever the state changes, all objects are informed
5 * by their setState() method of the value change.
6 *
7 * @author Nils Diewald
8 */
Akronb69cbf12020-10-01 13:04:44 +02009/*
10 * TODO:
Akron237abc42020-10-07 14:14:52 +020011 * Require names for states, that should be quite short, so they
12 * can easily be serialized and kept between page turns (via cookie
13 * and/or query param)
Akronb69cbf12020-10-01 13:04:44 +020014 */
Akrondf90c592020-10-20 08:42:50 +020015"use strict";
16
Akron308a6032019-12-05 16:27:34 +010017define(function () {
Akron308a6032019-12-05 16:27:34 +010018 return {
19
20 /**
21 * Constructor
22 */
Akron72c1c9d2021-11-05 10:46:34 +010023 create : function (values) {
24 return Object.create(this)._init(values);
Akron308a6032019-12-05 16:27:34 +010025 },
26
Akrondf90c592020-10-20 08:42:50 +020027
Akron308a6032019-12-05 16:27:34 +010028 // Initialize
Akron237abc42020-10-07 14:14:52 +020029 _init : function (values) {
Akrondf90c592020-10-20 08:42:50 +020030 const t = this;
31 t._assoc = [];
Akron237abc42020-10-07 14:14:52 +020032 if (values == undefined) {
Akrondf90c592020-10-20 08:42:50 +020033 t.values = [false,true];
Akron237abc42020-10-07 14:14:52 +020034 }
35 else if (Array.isArray(values)) {
Akrondf90c592020-10-20 08:42:50 +020036 t.values = values;
Akron237abc42020-10-07 14:14:52 +020037 }
38 else {
Akrondf90c592020-10-20 08:42:50 +020039 t.values = [values];
Akron237abc42020-10-07 14:14:52 +020040 }
Akrondf90c592020-10-20 08:42:50 +020041 return t;
Akron308a6032019-12-05 16:27:34 +010042 },
43
Akrondf90c592020-10-20 08:42:50 +020044
Akron308a6032019-12-05 16:27:34 +010045 /**
46 * Associate the state with some objects.
47 */
48 associate : function (obj) {
49
50 // Check if the object has a setState() method
51 if (obj.hasOwnProperty("setState")) {
Akronda32e7a2021-11-16 17:28:57 +010052
Akron308a6032019-12-05 16:27:34 +010053 this._assoc.push(obj);
Akronda32e7a2021-11-16 17:28:57 +010054 if (this.value != undefined) {
55 obj.setState(this.value);
56 };
Akron308a6032019-12-05 16:27:34 +010057 } else {
58 console.log("Object " + obj + " has no setState() method");
59 }
60 },
61
Akrondf90c592020-10-20 08:42:50 +020062
Akron308a6032019-12-05 16:27:34 +010063 /**
64 * Set the state to a certain value.
65 * This will set the state to all associated objects as well.
66 */
67 set : function (value) {
68 if (value != this.value) {
69 this.value = value;
Akron678c26f2020-10-09 08:52:50 +020070 this._assoc.forEach(i => i.setState(value));
Akron308a6032019-12-05 16:27:34 +010071 };
72 },
73
Akrondf90c592020-10-20 08:42:50 +020074
Akron308a6032019-12-05 16:27:34 +010075 /**
Akron72c1c9d2021-11-05 10:46:34 +010076 * Set the state to a default value.
77 * This will only be set, if no other value is set yet.
78 */
79 setIfNotYet : function (value) {
80 if (this.value == undefined) {
81 this.set(value);
82 };
83 },
84
85
86 /**
Akron308a6032019-12-05 16:27:34 +010087 * Get the state value
88 */
89 get : function () {
Akron72c1c9d2021-11-05 10:46:34 +010090 if (this.value == undefined) {
91 this.value = this.values[0];
92 };
93
Akron308a6032019-12-05 16:27:34 +010094 return this.value;
Akronb69cbf12020-10-01 13:04:44 +020095 },
96
97
98 /**
99 * Get the number of associated objects
100 */
101 associates : function () {
102 return this._assoc.length;
Akron38ed5dc2020-10-01 17:33:00 +0200103 },
104
Akrondf90c592020-10-20 08:42:50 +0200105
Akron38ed5dc2020-10-01 17:33:00 +0200106 /**
107 * Clear all associated objects
108 */
109 clear : function () {
110 return this._assoc = [];
Akron237abc42020-10-07 14:14:52 +0200111 },
112
Akrondf90c592020-10-20 08:42:50 +0200113
Akron237abc42020-10-07 14:14:52 +0200114 /**
115 * Roll to the next value.
116 * This may be used for toggling.
117 */
118 roll : function () {
119 let next = 0;
120 for (let i = 0; i < this.values.length - 1; i++) {
Akron72c1c9d2021-11-05 10:46:34 +0100121 if (this.get() == this.values[i]) {
Akron237abc42020-10-07 14:14:52 +0200122 next = i+1;
123 break;
124 };
125 };
126 this.set(this.values[next]);
Akron308a6032019-12-05 16:27:34 +0100127 }
128 }
129});