3 * Common JavaScript code for Chopwood
5 * (c) 2013 Mark Wooding
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Chopwood: a password-changing service.
12 * Chopwood is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Affero General Public License as
14 * published by the Free Software Foundation; either version 3 of the
15 * License, or (at your option) any later version.
17 * Chopwood is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
22 * You should have received a copy of the GNU Affero General Public
23 * License along with Chopwood; if not, see
24 * <http://www.gnu.org/licenses/>.
27 /*----- Some utilities ----------------------------------------------------*/
30 /* Return the element with the requested ID. */
31 return document
.getElementById(id
);
34 function map(func
, list
) {
35 /* Apply FUNC to each element of LIST, which may actually be any object;
36 * return a new object mapping the same keys to the images of the values in
41 for (i
in list
) out
[i
] = func(list
[i
]);
45 /*----- Form validation ---------------------------------------------------*/
48 /* A map of form names to information about them. Each form is an object
49 * with the following slots:
51 * * elts: A list of element-ids for the form widgets. These widgets will
52 * be checked periodically to see whether the input data is acceptable.
54 * * check: A function of no arguments, which returns either `null' if
55 * everything is OK, or an error message as a string.
57 * Form names aren't just for show. Some element-ids are constructed using
58 * the form name as a base:
60 * * FORM-whinge: An output element in which to display an error message if
61 * the form's input is unacceptable.
63 * * FORM-submit: The Submit button, which needs hooking to inhibit
64 * submitting a form with invalid data.
67 function update(obj
, slot
, value
) {
68 /* Update an object slot only if we're gping to change its value. */
69 if (obj
[slot
] !== value
) obj
[slot
] = value
;
73 /* Check through the various forms to make sure they're filled in OK. If
74 * not, set the `F-whinge' elements, and disable `F-submit'.
80 we
= elt(f
+ '-whinge');
81 sb
= elt(f
+ '-submit');
82 whinge
= form
.check();
83 if (sb
!== null) update(sb
, 'disabled', whinge
!== null);
85 update(we
, 'textContent', whinge
|| 'OK');
86 update(we
, 'className', whinge
=== null ? 'whinge' : 'whinge wrong');
90 // We can't catch all possible change events: in particular, it seems
91 // really hard to capture changes as a result of selections from a menu --
92 // e.g., delete or paste. Accept this, and just recheck periodically.
97 /* The timer for the periodic validation job. */
99 function check_again(when
) {
100 /* Arrange to check the forms again in WHEN milliseconds. */
101 if (timer
!== null) clearTimeout(timer
);
102 timer
= setTimeout(check
, when
);
106 function check_soon(ev
) {
107 /* Arrange to check the forms again very soon. */
111 function check_presubmit(ev
, f
) {
112 /* Check the form F now, popping up an alert and preventing the event EV if
113 * there's something wrong.
115 var whinge
= FORMS
[f
].check();
117 if (whinge
!== null) {
124 /* Attach event handlers to the various widgets so that we can keep track
125 * of how well things are being filled in.
129 // Start watching for changes.
132 for (f
in FORMS
) (function (f
, form
) {
134 // Ugh. We have to lambda-bind `f' here so that we can close over it
136 for (w
in form
.elts
) {
137 if ((e
= elt(f
+ '-' + form
.elts
[w
])) === null) continue;
138 e
.addEventListener('click', check_soon
, false);
139 e
.addEventListener('change', check_soon
, false);
140 e
.addEventListener('keypress', check_soon
, false);
141 e
.addEventListener('blur', check_soon
, false);
143 if ((e
= elt(f
+ '-submit')) !== null) {
144 e
.addEventListener('click', function (ev
) {
145 return check_presubmit(ev
, f
)
151 window
.addEventListener('load', init
, false);
153 /*----- That's all, folks -------------------------------------------------*/