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.
68 /* Check through the various forms to make sure they're filled in OK. If
69 * not, set the `F-whinge' elements, and disable `F-submit'.
75 we = elt(f + '-whinge');
76 sb = elt(f + '-submit');
77 whinge = form.check();
78 if (sb !== null) sb.disabled = (whinge !== null);
80 we.textContent = whinge || 'OK';
81 we.className = whinge === null ? 'whinge' : 'whinge wrong';
85 // We can't catch all possible change events: in particular, it seems
86 // really hard to capture changes as a result of selections from a menu --
87 // e.g., delete or paste. Accept this, and just recheck periodically.
92 /* The timer for the periodic validation job. */
94 function check_again(when) {
95 /* Arrange to check the forms again in WHEN milliseconds. */
96 if (timer !== null) clearTimeout(timer);
97 timer = setTimeout(check, when);
101 function check_soon(ev) {
102 /* Arrange to check the forms again very soon. */
106 function check_presubmit(ev, f) {
107 /* Check the form F now, popping up an alert and preventing the event EV if
108 * there's something wrong.
110 var whinge = FORMS[f].check();
112 if (whinge !== null) {
119 /* Attach event handlers to the various widgets so that we can keep track
120 * of how well things are being filled in.
124 // Start watching for changes.
127 for (f in FORMS) (function (f, form) {
129 // Ugh. We have to lambda-bind `f' here so that we can close over it
131 for (w in form.elts) {
132 if ((e = elt(f + '-' + form.elts[w])) === null) continue;
133 e.addEventListener('click', check_soon, false);
134 e.addEventListener('change', check_soon, false);
135 e.addEventListener('keypress', check_soon, false);
136 e.addEventListener('blur', check_soon, false);
138 if ((e = elt(f + '-submit')) !== null) {
139 e.addEventListener('click', function (ev) {
140 return check_presubmit(ev, f)
146 window.addEventListener('load', init, false);
148 /*----- That's all, folks -------------------------------------------------*/