PageSourceSearch

https://hotglue.me/account/js/account.js

js hotglue.me collected 2026-10-01 08:57:45 UTC 7,273 bytes, 189 lines download raw bytes

1// Vanilla replacement for jQuery + jQuery-Validate + form_stuff.js on the
2// registration form. Native HTML5 attributes (required, pattern, minlength,
3// maxlength, type=email) on the inputs do most of the work; this covers
4// what native can't: the username/password character bans, password-match,
5// and the live "already taken" pre-checks. All of it is UX only -
6// register-open.php validates everything server-side regardless of what
7// this file does or doesn't catch.
8(function () {
9	'use strict';
10
11	var form = document.getElementById('regForm');
12	if (!form) return;
13
14	var usernamed = document.getElementById('usernamed');
15	var username = document.getElementById('username');
16	var password = document.getElementById('pwd');
17	var passwordc = document.getElementById('passwordc');
18	var email = document.getElementById('email');
19	var agree = form.querySelector('input[name="agree"]');
20
21	var messageBoxes = {
22		usernamed: document.getElementById('message-usernamed'),
23		username: document.getElementById('message-username'),
24		password: document.getElementById('message-password'),
25		passwordc: document.getElementById('message-passwordc'),
26		email: document.getElementById('message-email'),
27		agree: document.getElementById('message-agree')
28	};
29
30	// Same DOM shape jQuery-Validate used to produce (a <label class="error">
31	// or <label class="valid"> inside the #message-* span) so the existing
32	// cakestyle.css rules (label.error/label.valid, scoped under #regbox)
33	// keep working with no CSS changes.
34	function showMessage(name, text, ok) {
35		var box = messageBoxes[name];
36		if (!box) return;
37		box.innerHTML = '';
38		if (!text) return;
39		var label = document.createElement('label');
40		label.setAttribute('for', name);
41		label.className = ok ? 'valid' : 'error';
42		label.textContent = text;
43		box.appendChild(label);
44	}
45
46	function debounce(fn, ms) {
47		var t;
48		return function () {
49			clearTimeout(t);
50			var args = arguments;
51			t = setTimeout(function () { fn.apply(null, args); }, ms);
52		};
53	}
54
55	// --- character/word bans the old jQuery custom validators enforced ---
56	function checkNotUsername() {
57		if (/^username|www.*|http.*|ftp.*$/.test(username.value)) {
58			username.setCustomValidity('invalid username!');
59		} else {
60			username.setCustomValidity('');
61		}
62	}
63	function checkNotPassword(field) {
64		if (/^password$/.test(field.value)) {
65			field.setCustomValidity('"password" is not a password!');
66		} else {
67			field.setCustomValidity('');
68		}
69	}
70	function checkPasswordsMatch() {
71		if (passwordc.value && passwordc.value !== password.value) {
72			passwordc.setCustomValidity("passwords don't match!");
73		} else {
74			passwordc.setCustomValidity('');
75		}
76	}
77
78	// --- live "already taken" pre-checks, ported from form_stuff.js's
79	// usernameCheck/emailCheck AJAX methods. Debounced like the original
80	// (500ms). A network hiccup here just means no live feedback - the
81	// server checks again on submit either way. ---
82	function checkTaken(field, name, param, takenMsg, okMsg) {
83		// Clear any "taken"/"already registered" customValidity left over
84		// from a PREVIOUS call before checking validity again - otherwise
85		// a stale customError makes checkValidity() false forever and this
86		// never re-fires for whatever new value the user typed next.
87		field.setCustomValidity('');
88		var value = field.value;
89		if (!value || !field.checkValidity()) return;
90		fetch('check_form.php', {
91			method: 'POST',
92			headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
93			body: param + '=' + encodeURIComponent(value)
94		})
95			.then(function (r) { return r.json(); })
96			.then(function (available) {
97				if (field.value !== value) return; // stale - user kept typing
98				if (available) {
99					field.setCustomValidity('');
100					showMessage(name, okMsg(value), true);
101				} else {
102					field.setCustomValidity(takenMsg);
103					showMessage(name, takenMsg, false);
104				}
105			})
106			.catch(function () {});
107	}
108
109	// checkTaken() itself clears stale customValidity and re-checks native
110	// constraints, so these debounced wrappers don't need to gate on
111	// checkValidity() too - doing it here as well hits the same staleness
112	// trap one level up (a leftover customError would block this outer
113	// check before checkTaken ever gets a chance to clear it).
114	var checkUsernameTaken = debounce(function () {
115		checkTaken(username, 'username', 'username', 'username is taken, sorry!', function (v) {
116			return 'Your URL: http://' + v + '.hotglue.me/';
117		});
118	}, 500);
119
120	var checkEmailTaken = debounce(function () {
121		checkTaken(email, 'email', 'email', 'this email is already registered!', function () {
122			return 'looks good!';
123		});
124	}, 500);
125
126	// --- map native validity failures to the old messages ---
127	var fieldText = {
128		usernamed: { valueMissing: 'your name, please?', tooShort: 'too short!', tooLong: 'too long!' },
129		username: { valueMissing: 'your username?', tooShort: 'too short!', tooLong: 'too long!', patternMismatch: "don't understand those funky symbols!" },
130		email: { valueMissing: 'what is your email?', typeMismatch: 'bad email!', tooLong: 'too long email!' },
131		password: { valueMissing: 'create a password', tooShort: 'too short!', tooLong: 'too long!' },
132		passwordc: { valueMissing: 'confirm your password' }
133	};
134
135	function renderValidity(field, positiveMessage) {
136		var name = field.name;
137		var map = fieldText[name];
138		if (!map) return;
139		var v = field.validity;
140		if (v.valid) {
141			if (positiveMessage) showMessage(name, positiveMessage, true);
142			return;
143		}
144		// customError (set by the checks above) carries its own message -
145		// field.validationMessage is exactly what was passed to
146		// setCustomValidity(), so no separate lookup table needed for it.
147		if (v.customError) { showMessage(name, field.validationMessage, false); return; }
148		if (v.valueMissing) { showMessage(name, map.valueMissing, false); return; }
149		if (v.tooShort) { showMessage(name, map.tooShort, false); return; }
150		if (v.tooLong) { showMessage(name, map.tooLong, false); return; }
151		if (v.patternMismatch) { showMessage(name, map.patternMismatch, false); return; }
152		if (v.typeMismatch) { showMessage(name, map.typeMismatch, false); return; }
153	}
154
155	usernamed.addEventListener('input', function () {
156		renderValidity(usernamed, usernamed.validity.valid ? 'Greetings, ' + usernamed.value + '!' : null);
157	});
158
159	username.addEventListener('input', function () {
160		checkNotUsername();
161		renderValidity(username);
162		// Always schedule the debounced check rather than gating on
163		// validity here - checkTaken() itself decides whether the value is
164		// worth checking, and gating here too would (like the two spots
165		// above) get stuck once a stale "taken" customError is present.
166		checkUsernameTaken();
167	});
168
169	password.addEventListener('input', function () {
170		checkNotPassword(password);
171		renderValidity(password, 'looks good!');
172		checkPasswordsMatch();
173	});
174
175	passwordc.addEventListener('input', function () {
176		checkNotPassword(passwordc);
177		checkPasswordsMatch();
178		renderValidity(passwordc, 'looks good!');
179	});
180
181	email.addEventListener('input', function () {
182		renderValidity(email);
183		checkEmailTaken();
184	});
185
186	agree.addEventListener('change', function () {
187		showMessage('agree', agree.checked ? '' : 'you must accept our Terms of Service', false);
188	});
189})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.