blob: 7d0d25e3a2f73cf4e8033245e3faeb5b798d97c5 [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 */
23 create : function (value) {
24 return Object.create(this)._init(value);
25 },
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 t.value = t.values[0];
42 return t;
Akron308a6032019-12-05 16:27:34 +010043 },
44
Akrondf90c592020-10-20 08:42:50 +020045
Akron308a6032019-12-05 16:27:34 +010046 /**
47 * Associate the state with some objects.
48 */
49 associate : function (obj) {
50
51 // Check if the object has a setState() method
52 if (obj.hasOwnProperty("setState")) {
53 this._assoc.push(obj);
54 obj.setState(this.value);
55 } else {
56 console.log("Object " + obj + " has no setState() method");
57 }
58 },
59
Akrondf90c592020-10-20 08:42:50 +020060
Akron308a6032019-12-05 16:27:34 +010061 /**
62 * Set the state to a certain value.
63 * This will set the state to all associated objects as well.
64 */
65 set : function (value) {
66 if (value != this.value) {
67 this.value = value;
Akron678c26f2020-10-09 08:52:50 +020068 this._assoc.forEach(i => i.setState(value));
Akron308a6032019-12-05 16:27:34 +010069 };
70 },
71
Akrondf90c592020-10-20 08:42:50 +020072
Akron308a6032019-12-05 16:27:34 +010073 /**
74 * Get the state value
75 */
76 get : function () {
77 return this.value;
Akronb69cbf12020-10-01 13:04:44 +020078 },
79
80
81 /**
82 * Get the number of associated objects
83 */
84 associates : function () {
85 return this._assoc.length;
Akron38ed5dc2020-10-01 17:33:00 +020086 },
87
Akrondf90c592020-10-20 08:42:50 +020088
Akron38ed5dc2020-10-01 17:33:00 +020089 /**
90 * Clear all associated objects
91 */
92 clear : function () {
93 return this._assoc = [];
Akron237abc42020-10-07 14:14:52 +020094 },
95
Akrondf90c592020-10-20 08:42:50 +020096
Akron237abc42020-10-07 14:14:52 +020097 /**
98 * Roll to the next value.
99 * This may be used for toggling.
100 */
101 roll : function () {
102 let next = 0;
103 for (let i = 0; i < this.values.length - 1; i++) {
104 if (this.value == this.values[i]) {
105 next = i+1;
106 break;
107 };
108 };
109 this.set(this.values[next]);
Akron308a6032019-12-05 16:27:34 +0100110 }
111 }
112});