'use strict';
/**
* Password toggle component.
* @namespace passwordToggle
* @memberof UCASDesignFramework
* @param {object} global - UCASDesignFramework object.
* @param {object} _u - UCASUtilities object.
*/
(function (global, _u) {
var passwordToggles = {}
/**
* Initialises any form items it finds that have a data-password-toggle attribute
* set to true to allow the password to toggle between password and text types.
* @function init
* @memberof! UCASDesignFramework.passwordToggle
* @param {Node} [context=document] - context to limit the selector
* @param {String} [selector=.form-item [data-password-toggle="true"]] - a valid CSS selector for the password toggle data attribute
* @returns {Boolean} - true for success
* @example
* UCASDesignFramework.passwordToggle.init()
*/
function init (context, selector) {
context = context || document
selector = selector || '.form-item [data-password-toggle="true"]'
var formItems = document.querySelectorAll(selector)
if (!formItems) {
_u.log.info('Failed to find any passwords fields to toggle')
return false
} else {
formItems.forEach(function (formItem) {
if (!formItem.id) {
_u.log.info('Form item must have an ID')
return
}
if (passwordToggles[formItem.id]) {
_u.log.info('Already initialised password toggle with ID ' + formItem.id)
return
}
createPasswordToggle(formItem)
})
}
return true
}
/**
* PasswordToggle.
* @class
* @memberof! UCASDesignFramework.passwordToggle
*/
var PasswordToggle = {
init: function (formItem) {
createPasswordToggleButton(formItem)
},
destroy: function (formItem) {
removePasswordToggleButton(formItem)
delete passwordToggles[formItem.id]
}
}
/**
* @function createPasswordToggleButton
* @memberof! UCASDesignFramework.passwordToggle
* @param {Node} formItem - the form element
* @private
*/
function createPasswordToggleButton (formItem) {
// Create the password-toggle wrapper.
passwordToggles[formItem.id].$toggleWrapper = document.createElement('div')
passwordToggles[formItem.id].$toggleButton = document.createElement('a')
var toggleWrapper = passwordToggles[formItem.id].$toggleWrapper
var toggleButton = passwordToggles[formItem.id].$toggleButton
// The node surrounding the wrapper.
var formItemContainer = formItem.parentNode
// Add the required classes, attributes and content to the wrapper and button.
toggleWrapper.classList.add('password-toggle')
toggleButton.classList.add('password-toggle__button')
toggleButton.setAttribute('role', 'button')
// Add the toggle click event to the toggle button.
toggleButton.addEventListener('click', togglePasswordHandler.bind(this, formItem, false), false)
// Insert the wrapper before the form item.
formItemContainer.insertBefore(toggleWrapper, formItem)
// Move the form item into the wrapper.
toggleWrapper.appendChild(formItem)
toggleWrapper.appendChild(toggleButton)
// Call the toggle function with setup set to true to set the initial state of the toggle.
togglePasswordHandler(formItem, true)
}
/**
* @function removePasswordToggleButton
* @memberof! UCASDesignFramework.passwordToggle
* @param {Node} formItem - the form element
* @private
*/
function removePasswordToggleButton (formItem) {
var toggleWrapper = passwordToggles[formItem.id].$toggleWrapper
var toggleButton = passwordToggles[formItem.id].$toggleButton
// The node surrounding the wrapper.
var formItemContainer = toggleWrapper.parentNode
// Set the password type back to password.
formItem.setAttribute('type', 'password')
// Remove the toggle click event from the toggle button.
toggleButton.removeEventListener('click', togglePasswordHandler.bind(this, formItem, false), false)
// Move all children out of the wrapper apart from the button.
while (toggleWrapper.firstChild && toggleWrapper.firstChild !== toggleButton) formItemContainer.insertBefore(toggleWrapper.firstChild, toggleWrapper)
// Remove the wrapper and button.
formItemContainer.removeChild(toggleWrapper)
}
/**
* Handler that toggles the password field between password and text types.
* @function togglePasswordHandler
* @memberof! UCASDesignFramework.passwordToggle
* @param {Node} formItem - the form element
* @param {Boolean} setup - if the toggle is being setup for the first time
* @private
*/
function togglePasswordHandler (formItem, setup) {
var toggleButton = passwordToggles[formItem.id].$toggleButton
var toggleButtonComputedStyle = window.getComputedStyle(toggleButton)
if (!setup) formItem.setAttribute('type', formItem.getAttribute('type') === 'password' ? 'text' : 'password')
toggleButton.innerHTML = formItem.getAttribute('type') === 'password' ? formItem.getAttribute('data-password-toggle-show-text') || 'Show' : formItem.getAttribute('data-password-toggle-hide-text') || 'Hide'
toggleButton.setAttribute('title', formItem.getAttribute('type') === 'password' ? 'Show password' : 'Hide password')
formItem.style.paddingRight = parseFloat(toggleButtonComputedStyle.getPropertyValue('width')) + (parseFloat(toggleButtonComputedStyle.getPropertyValue('right')) * 2) + 'px'
if (!setup) formItem.focus()
}
/**
* Creates and registers a passwordToggle.
* @function create
* @memberof! UCASDesignFramework.passwordToggle
* @param {Node} formItem - the form element
* @return {PasswordToggle} - the PasswordToggle object
* @example
* UCASDesignFramework.passwordToggle.create($myFormItem)
*/
function createPasswordToggle (formItem) {
if (passwordToggles[formItem.id] === undefined) {
if (formItem.id) {
passwordToggles[formItem.id] = Object.create(PasswordToggle)
passwordToggles[formItem.id].init(formItem)
return passwordToggles[formItem.id]
} else {
_u.log.info('Form item must have an ID')
}
}
}
/**
* @function destroy
* @memberof! UCASDesignFramework.passwordToggle
* @param {Node} formItem - the form element
* @example
* UCASDesignFramework.passwordToggle.destroy($myFormItem)
*/
function destroyPasswordToggle (formItem) {
if (passwordToggles[formItem.id]) {
passwordToggles[formItem.id].destroy(formItem)
} else {
_u.log.info('Form item must have an ID')
}
}
// Expose public methods and properties.
global.passwordToggle = {
addSubscriptions: true,
init: init,
initOnLoad: true,
create: createPasswordToggle,
destroy: destroyPasswordToggle
}
})(UCASDesignFramework, UCASUtilities)