nodegame-widgets
Version:
Collections of useful and reusable javascript / HTML snippets for nodeGame
420 lines (367 loc) • 12.9 kB
JavaScript
/**
* # EmailForm
* Copyright(c) 2021 Stefano Balietti <ste@nodegame.org>
* MIT Licensed
*
* Displays a form to input email
*
* www.nodegame.org
*/
(function(node) {
"use strict";
node.widgets.register('EmailForm', EmailForm);
// ## Meta-data
EmailForm.version = '0.13.1';
EmailForm.description = 'Displays a configurable email form.';
EmailForm.title = false;
EmailForm.className = 'emailform';
EmailForm.texts = {
label: 'Enter your email:',
errString: 'Not a valid email address, ' +
'please correct it and submit it again.',
sent: 'Sent!'
};
/**
* ## EmailForm constructor
*
* @param {object} options configuration option
*/
function EmailForm(opts) {
/**
* ### EmailForm.onsubmit
*
* Options passed to `getValues` when the submit button is pressed
*
* @see EmailForm.getValues
*/
if (!opts.onsubmit) {
this.onsubmit = {
emailOnly: true,
send: true,
updateUI: true
};
}
else if ('object' === typeof opts.onsubmit) {
this.onsubmit = opts.onsubmit;
}
else {
throw new TypeError('EmailForm constructor: opts.onsubmit ' +
'must be object or undefined. Found: ' +
opts.onsubmit);
}
/**
* ### EmailForm._email
*
* Internal storage of the value of the email
*
* This value is used when the form has not been created yet
*
* @see EmailForm.createForm
*/
this._email = opts.email || null;
/**
* ### EmailForm.attempts
*
* Invalid emails tried
*/
this.attempts = [];
/**
* ### EmailForm.timeInput
*
* Time when the email was inserted (first character, last attempt)
*/
this.timeInput = null;
/**
* ### EmailForm.formElement
*
* The email's HTML form
*/
this.formElement = null;
/**
* ### EmailForm.inputElement
*
* The email's HTML input form
*/
this.inputElement = null;
/**
* ### EmailForm.buttonElement
*
* The email's HTML submit button
*/
this.buttonElement = null;
/**
* ### EmailForm.setMsg
*
* If TRUE, a set message is sent instead of a data msg
*
* Default: FALSE
*/
this.setMsg = !!opts.setMsg || false;
/**
* ### EmailForm.showSubmitBtn
*
* If TRUE, a set message is sent instead of a data msg
*
* Default: FALSE
*/
this.showSubmitBtn = 'undefined' === typeof opts.showSubmitBtn ?
true : !!opts.showSubmitBtn;
}
// ## EmailForm methods
EmailForm.prototype.createForm = function() {
var that;
var formElement, labelElement, inputElement, buttonElement;
that = this;
formElement = document.createElement('form');
formElement.className = 'emailform-form';
labelElement = document.createElement('label');
labelElement.innerHTML = this.getText('label');
inputElement = document.createElement('input');
inputElement.setAttribute('type', 'text');
inputElement.setAttribute('placeholder', 'Email');
inputElement.className = 'emailform-input form-control';
formElement.appendChild(labelElement);
formElement.appendChild(inputElement);
// Store references.
this.formElement = formElement;
this.inputElement = inputElement;
if (this.showSubmitBtn) {
buttonElement = document.createElement('input');
buttonElement.setAttribute('type', 'submit');
buttonElement.setAttribute('value', 'Submit email');
buttonElement.className = 'btn btn-lg btn-primary ' +
'emailform-submit';
formElement.appendChild(buttonElement);
// Add listeners on input form.
J.addEvent(formElement, 'submit', function(event) {
event.preventDefault();
that.getValues(that.onsubmit);
}, true);
J.addEvent(formElement, 'input', function() {
if (!that.timeInput) that.timeInput = J.now();
if (that.isHighlighted()) that.unhighlight();
}, true);
// Store reference.
this.buttonElement = buttonElement;
}
// If a value was previously set, insert it in the form.
if (this._email) this.formElement.value = this._email;
this._email = null;
return formElement;
};
/**
* ### EmailForm.verifyInput
*
* Verify current email, updates interface, and optionally marks attempt
*
* @param {boolean} markAttempt Optional. If TRUE, the current email
* is added to the attempts array. Default: TRUE
* @param {boolean} updateUI Optional. If TRUE, the interface is updated.
* Default: FALSE
*
* @return {boolean} TRUE, if the email is valid
*
* @see EmailForm.getValues
* @see getEmail
*/
EmailForm.prototype.verifyInput = function(markAttempt, updateUI) {
var email, res;
email = getEmail.call(this);
res = J.isEmail(email);
if (res && updateUI) {
if (this.inputElement) this.inputElement.disabled = true;
if (this.buttonElement) {
this.buttonElement.disabled = true;
this.buttonElement.value = this.getText('sent');
}
}
else {
if (updateUI && this.buttonElement) {
this.buttonElement.value = this.getText('errString');
}
if ('undefined' === typeof markAttempt || markAttempt) {
this.attempts.push(email);
}
}
return res;
};
/**
* ### EmailForm.append
*
* Appends widget to this.bodyDiv
*/
EmailForm.prototype.append = function() {
this.createForm();
this.bodyDiv.appendChild(this.formElement);
};
/**
* ### EmailForm.setValues
*
* Set the value of the email input form
*/
EmailForm.prototype.setValues = function(options) {
var email;
options = options || {};
if (!options.email) email = J.randomEmail();
else email = options.email;
if (!this.inputElement) this._email = email;
else this.inputElement.value = email;
this.timeInput = J.now();
};
/**
* ### EmailForm.getValues
*
* Returns the email and paradata
*
* @param {object} opts Optional. Configures the return value.
* Available optionts:
*
* - emailOnly: If TRUE, returns just the email (default: FALSE),
* - verify: If TRUE, check if the email is valid (default: TRUE),
* - reset: If TRUTHY and the email is valid, then it resets
* the email value before returning (default: FALSE),
* - markAttempt: If TRUE, getting the value counts as an attempt
* (default: TRUE),
* - updateUI: If TRUE, the UI (form, input, button) is updated.
* Default: FALSE.
* - highlight: If TRUE, if email is not the valid, widget is
* is highlighted. Default: (updateUI || FALSE).
* - send: If TRUE, and the email is valid, then it sends
* a data or set msg. Default: FALSE.
* - sendAnyway: If TRUE, it sends a data or set msg regardless of
* the validity of the email. Default: FALSE.
* - say: same as send, but deprecated.
* - sayAnyway: same as sendAnyway, but deprecated
*
* @return {string|object} The email, and optional paradata
*
* @see EmailForm.sendValues
* @see EmailForm.verifyInput
* @see getEmail
*/
EmailForm.prototype.getValues = function(opts) {
var email, res;
opts = opts || {};
if ('undefined' !== typeof opts.say) {
console.log('***EmailForm.getValues: option say is deprecated, ' +
' use send.***');
opts.send = opts.say;
}
if ('undefined' !== typeof opts.sayAnyway) {
console.log('***EmailForm.getValues: option sayAnyway is ' +
'deprecated, use sendAnyway.***');
opts.sendAnyway = opts.sayAnyway;
}
if ('undefined' === typeof opts.markAttempt) opts.markAttempt = true;
if ('undefined' === typeof opts.highlight) opts.highlight = true;
email = getEmail.call(this);
if (opts.verify !== false) {
res = this.verifyInput(opts.markAttempt, opts.updateUI);
}
// Only value.
if (!opts.emailOnly) {
email = {
time: this.timeInput,
email: email,
attempts: this.attempts,
};
if (opts.markAttempt) email.isCorrect = res;
}
if (res === false) {
if (opts.updateUI || opts.highlight) this.highlight();
this.timeInput = null;
}
// Send the message.
if ((opts.send && res) || opts.sendAnyway) {
this.sendValues({ values: email });
}
if (opts.reset) this.reset();
return email;
};
/**
* ### EmailForm.sendValues
*
* Sends a DATA message with label 'email' with current email and paradata
*
* @param {object} opts Optional. Options to pass to the `getValues`
* method. Additional options:
*
* - values: actual values to send, instead of the return
* value of `getValues`
* - to: recipient of the message. Default: 'SERVER'
*
* @return {string|object} The email, and optional paradata
*
* @see EmailForm.getValues
*/
EmailForm.prototype.sendValues = function(opts) {
var values;
opts = opts || { emailOnly: true };
values = opts.values || this.getValues(opts);
if (this.setMsg) {
if ('string' === typeof values) values = { email: values };
node.set(values, opts.to || 'SERVER');
}
else {
node.say('email', opts.to || 'SERVER', values);
}
return values;
};
/**
* ### EmailForm.highlight
*
* Highlights the email form
*
* @param {string} The style for the form border. Default: '1px solid red'
*
* @see EmailForm.highlighted
*/
EmailForm.prototype.highlight = function(border) {
if (border && 'string' !== typeof border) {
throw new TypeError('EmailForm.highlight: border must be ' +
'string or undefined. Found: ' + border);
}
if (!this.inputElement || this.highlighted === true) return;
this.inputElement.style.border = border || '3px solid red';
this.highlighted = true;
this.emit('highlighted', border);
};
/**
* ### EmailForm.unhighlight
*
* Removes highlight from the form
*
* @see EmailForm.highlighted
*/
EmailForm.prototype.unhighlight = function() {
if (!this.inputElement || this.highlighted !== true) return;
this.inputElement.style.border = '';
this.highlighted = false;
this.emit('unhighlighted');
};
/**
* ### EmailForm.reset
*
* Resets email and collected paradata
*/
EmailForm.prototype.reset = function() {
this.attempts = [];
this.timeInput = null;
this._email = null;
if (this.inputElement) this.inputElement.value = '';
if (this.isHighlighted()) this.unhighlight();
};
// ## Helper methods.
/**
* ### getEmail
*
* Returns the value of the email in form or in `_email`
*
* Must be invoked with right context
*
* @return {string|null} The value of the email, if any
*/
function getEmail() {
return this.inputElement ? this.inputElement.value : this._email;
}
})(node);