var CFSLogin = {
options: {
emailField: "#email",
passwordField: "#password",
gotoURL: "",
gravDefault: "mm",
allowRegistration: false,
seed: "",
magic: {
set: false
}
},
data: {
cachedAccounts: [],
selectedAccount: null,
urlAfterPasswordChange: "/",
autoCountdownInterval: null
},
passwordStengthResults: {
0: "OK",
1: "Error, not logged in.",
2: "Error, no connection",
3: "Error, no user",
10: "Not matched current",
11: "Choose a password you haven't used for this site before.",
12: "Choose a password you haven't used for this site before.",
13: "Use at least 1 uppercase letter.",
14: "Use at least 1 lowercase letter.",
15: "Use at least 1 number.",
16: "Use a symbol (!£$%^&*()-@#.).",
17: "Use at least 8 characters.",
18: "This password may have been compromised."
},
init: function () {
var self = this;
$(self.options.emailField).keyup(function (event) {
if (event.keyCode == 13) {
self.testEmail();
}
});
$(self.options.passwordField).keyup(function (event) {
if (event.keyCode == 13) {
self.login();
}
});
$("#validate-ga-code").keyup(function (event) {
if (event.keyCode == 13) {
self.validate2FACode();
}
});
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf("_cfs_px_accsn=") == 0) {
var accs = c.substring(14, c.length);
accs = accs.replace(/[^a-zA-Z0-9~|@•. ']-/g, "");
if (accs != "") {
var savedAccounts = accs.split("||");
for (var x = 0; x < savedAccounts.length; x++) {
var px = savedAccounts[x].split("~");
self.data.cachedAccounts.push({ account: px[0], type: px[1], email: px[2] });
}
}
}
}
self.displayHistory();
self.setupAutoCountDown();
if (self.options.magic.set === true) {
$(".a-section").hide();
$(".magic-section").show();
$('body.login-page').addClass('magic-loading');
self.data.selectedAccount = { account: self.options.magic.code, type: "magic" };
// delay the login by 1s if using a magic link, to make sure that it is visible before the 2FA screen (otherwise it looks like a bug)
setTimeout(() => self.login(), 1000);
}
// new login page input handling for removing error state on keypress
if ($('.login-page.-auto').length > 0) {
const inputs = $('input');
inputs.off('keydown.invalidMessage')
inputs.on('keydown.invalidMessage', function () {
$(this).removeClass('invalid');
const field = $(this).closest('.md-field-holder');
field.find('#strengthometer').removeClass('fail');
field.find('.invalid-message').text('');
})
}
// enable new 6 box inputs
this.splitInputHandling();
},
setupAutoCountDown: function () {
var self = this;
clearInterval(self.data.autoCountdownInterval);
this.data.autoCountdownInterval = setInterval(function () {
$(".auto-countdown").each(function () {
var c = parseInt($(this).html().replace("seconds", "").replace("second", "").replace("in", "")) - 1;
$(this).html("in " + c + (c == 1 ? " second" : " seconds"));
if (c <= 0) {
self.unlockField($(this).attr("data-field"));
$(this).html("").removeClass("auto-countdown");
}
});
}, 1000);
},
passwordCodeRequest: function () {
$(".a-section").hide();
$(".password-lost-section").show();
$(".reset-code-email").html(this.data.selectedAccount.email);
$(".invalid").removeClass("invalid");
},
processPasswordCodeRequest: function () {
var self = this;
var email = self.data.selectedAccount.type == "id" ? self.data.selectedAccount.id : self.data.selectedAccount.account;
var acc = this.data.selectedAccount.type + "|:" + email;
self.showLoader();
Durell.CFS.Website.SecureLogin.SendPasswordResetCode(acc, function (rsp) {
if (rsp.Success) {
self.passwordCodeSent();
} else {
self.showFeedback(rsp.ErrorDescription, true,false);
self.hideLoader();
}
});
},
passwordCodeSent: function () {
var self = this;
$(".a-section").hide();
$(".password-email-sent-section").show();
$("#validate-code").focus();
self.hideLoader();
},
validatePasswordCode: function () {
var self = this;
self.showLoader();
var code = '';
// new way
if ($("#validate-code").is('.split-input-holder')) {
$(`#validate-code > input`).each(function () {
providedCode += $(this).val();
})
}
// old way
else code = $("#validate-code").val();
if (code == "") {
self.showInvalidMessage($("#validate-code"), "Enter a code.");
}
else if (code.length != 6) {
self.showInvalidMessage($("#validate-code"), "Wrong number of digits. Try again.");
if ($("#validate-code").is('.split-input-holder')) $('#validate-code > input').val('');
}
else {
var email = self.data.selectedAccount.type == "id" ? self.data.selectedAccount.id : self.data.selectedAccount.account;
var acc = this.data.selectedAccount.type + "|:" + email;
Durell.CFS.Website.SecureLogin.ValidateVerificationCode(acc, code, function (rsp) {
if (rsp.Success) {
self.hideLoader();
// All good, go ahead and log the user in and ask them to choose a new password before going any further ...
$(self.options.passwordField).val(code);
self.login();
}
else {
self.showInvalidMessage($("#validate-code"), rsp.ErrorDescription, true);
if (rsp.AdditionalInfo == "LockPassword") {
self.lockField("#validate-code");
}
}
});
}
},
preValidatePasswordStrengthOnboarding: function (passwordField) {
var self = this;
var pw = $(passwordField).val();
var level = 1;
var showLevel = function (rspLevel, level) {
$(".strength-ometer").removeClass("level-1").removeClass("level-2").removeClass("level-3").removeClass("level-4").addClass("level-" + level);
if (level < 4) {
$("#onboard-pass1").addClass("invalid"); //.focus();
$("#onboarding-change-pass footer a.main").addClass("disabled");
if (rspLevel != "") {
$("#onboarding-change-pass footer p.invalid-message").html(self.passwordStengthResults[rspLevel]).show();
}
} else {
$(passwordField).removeClass("invalid");
$("#onboarding-change-pass footer a.main").removeClass("disabled");
$("#onboarding-change-pass footer p.invalid-message").hide();
}
}
if (pw == "" || pw.length <= 5) {
showLevel("17", 1);
}
else {
Durell.CFS.Website.SecureLogin.PreValidatePasswordStrength("", pw, function (rsp) {
if (rsp.Success) {
if (rsp.ResponseText == "0") level = 4;
else if (parseInt(rsp.ResponseText) < 13) level = 2;
else if (parseInt(rsp.ResponseText) <= 17) level = 3;
showLevel(rsp.ResponseText, level);
}
});
}
},
preValidatePasswordStrength: function (passwordField) {
var self = this;
var pw = $(passwordField).val();
Durell.CFS.Website.SecureLogin.PreValidatePasswordStrength($(self.options.passwordField).val(), pw, function (rsp) {
if (rsp.Success) {
if (self.passwordStengthResults[rsp.ResponseText] != "OK") {
if ($('#strengthometer').is('.2026')) {
$("#strengthometer").html("Weak
" + self.passwordStengthResults[rsp.ResponseText] + '
').addClass("fail");
}
else $("#strengthometer").html("Weak
" + self.passwordStengthResults[rsp.ResponseText] + "
").addClass("fail");
$(passwordField).addClass("invalid"); //.focus();
$(".password-reset-section a.standard-button-style").addClass("disabled");
}
else {
$("#strengthometer").html("OK").removeClass("fail");
$(passwordField).removeClass("invalid");
$(".password-reset-section a.standard-button-style").removeClass("disabled");
}
}
});
},
updatePasswordAndLogin: function () {
var self = this;
var newPassword1 = $("#new-password"), newPasswordRepeat = $("#new-password-repeat");
if (onboarding) {
newPassword1 = $("#onboard-pass1");
newPasswordRepeat = $("#onboard-pass2");
}
if (newPassword1.hasClass("invalid")) return;
if (newPassword1.val() != newPasswordRepeat.val()) {
self.showInvalidMessage(newPasswordRepeat, "Passwords do not match.");
newPasswordRepeat.focus();
return;
}
else {
$(".password-reset-section a.standard-button-style").addClass("disabled");
newPassword1.attr("disabled", "disabled").addClass("disabled");
newPasswordRepeat.attr("disabled", "disabled").addClass("disabled").removeClass("invalid");
$("p.invalid-message").hide();
self.showLoader();
self.data.selectedAccount.changedPassword = newPassword1.val();
self.login();
}
},
displayHistory: function (isReturn) {
var self = this;
if (self.data.cachedAccounts.length > 0) {
$("#email-have-history").show();
$(".a-section").hide();
$(".history-section .accs").html("");
var idx = 0;
$(self.data.cachedAccounts).each(function () {
$(".history-section .accs").append("
" + this.account + "
");
idx++;
});
$(".history-section").show();
}
else {
$("#email-have-history").hide();
if (isReturn === true) self.cancelPassword();
$(".a-section").hide();
$(".email-section").show();
}
},
selectHistory: function (index) {
var self = this;
self.cancelPassword();
$(this.options.emailField).val(self.data.cachedAccounts[index].account);
self.testEmail();
//self.data.selectedAccount = self.data.cachedAccounts[index];
//self.promptPassword();
},
removeHistory: function (index) {
var self = this;
self.data.cachedAccounts.splice(index, 1);
self.displayHistory();
self.storeCacheInCookie();
},
allowPasswordEntry: function () {
//AttemptsBlocked
var self = this;
Durell.CFS.Website.SecureLogin.AttemptsBlocked(function (rsp) {
if (!rsp.Success) {
self.showInvalidMessage($(self.options.passwordField), rsp.ErrorDescription, true);
self.lockField(self.options.passwordField);
}
});
},
lockField: function (fld) {
$(fld).attr("disabled", "disabled").addClass("disabled");
$(".standard-button-style.main").addClass("disabled");
this.setupAutoCountDown();
},
unlockField: function (fld) {
$(fld).removeAttr("disabled").removeClass("disabled").removeClass("invalid").focus();
$(".standard-button-style.main").removeClass("disabled");
$("p.invalid-message").hide();
},
testEmail: function (em) {
var self = this;
self.showLoader();
var email = em ? em : $(this.options.emailField).val();
if (email == "") {
self.showInvalidMessage($(self.options.emailField), "Enter an email or username.");
} else {
try {
Durell.CFS.Website.SecureLogin.TestEmail(email, function (rsp) {
if (!rsp.Success) {
if (rsp.Message == null || rsp.Message == "") {
self.showInvalidMessage($(self.options.emailField), "Invalid login details.");
} else {
if (rsp.StatusIndicator == "MultiAccount") {
self.promptAccount();
self.data.selectedAccount = { account: email, type: "", email: "" };
} else {
self.showInvalidMessage($(self.options.emailField), rsp.Message);
}
}
}
else {
self.data.selectedAccount = { account: email, type: rsp.LoginType, email: rsp.AccountEmail };
self.promptPassword();
self.hideLoader();
}
}, function (error) {
console.error("Got error during login", error);
if (error._statusCode == 403) {
self.showInvalidMessage($(self.options.emailField), "Access to this login form has been restricted as you have made too many failed login attempts. Please try again later.
ID:" + CFSLogin.options.seed);
} else {
self.showInvalidMessage($(self.options.emailField), "Something went wrong, please try again.");
}
});
} catch (ex) {
console.error("Got ex during login", ex);
}
}
},
promptPasswordChange: function () {
$("#new-password, #new-password-repeat").attr("disabled", false).removeClass("disabled").removeClass("invalid").val("");
$(".a-section").hide();
$(".password-reset-section").show();
this.hideLoader();
},
prompt2FA: function () {
// make sure we disable the fancy magic loading state
$('body.login-page.magic-loading').removeClass('magic-loading');
$('#validate-ga-code').val("");
$(".a-section").hide();
$(".two-factor-entry-ga").show();
this.hideLoader();
},
prompt2FASetup: function (imgUrl, setupCode, invalidAttempt) {
// make sure we disable the fancy magic loading state
$('body.login-page.magic-loading').removeClass('magic-loading');
var self = this;
if (onboarding) {
$("#onboarding-verify-email").hide();
$("#onboarding-setup-2fa").show();
console.warn("Need to setup onboarding 2FA code...", imgUrl, setupCode, invalidAttempt)
} else {
$("#img-2fa").attr("src", imgUrl);
var setupCodeHTML = "";
for (var x = 0; x < setupCode.length; x++) {
setupCodeHTML += setupCode[x] + ((x + 1) % 4 == 0 ? " " : "");
}
$("#code-2fa").html(setupCodeHTML);
$(".a-section").hide();
$(".two-factor-setup").show();
}
if (invalidAttempt) {
self.showInvalidMessage($("#validate-lp-setup-code"), "Invalid code. Try again.", true);
}
self.hideLoader();
},
validate2FACode: function (setup) {
var self = this;
var providedCode = '';
const inputId = "#" + setup === true ? "validate-lp-setup-code" : "validate-ga-code"
// using new inputs
if ($(inputId).is('.split-input-holder')) {
$(`${inputId} > input`).each(function () {
providedCode += $(this).val();
})
}
// old way
else providedCode = $("#" + (setup === true ? "validate-lp-setup-code" : "validate-ga-code")).val();
self.data.selectedAccount.secondFactor = providedCode;
self.login();
},
promptAccount: function () {
$('#validate-user-code').val("");
$(".a-section").hide();
$(".email-section-multi-account").show();
this.hideLoader();
},
promptPassword: function (fromAccount) {
var self = this;
if (fromAccount === true) {
if ($('#validate-user-code').val() == "") {
self.showInvalidMessage($("#validate-user-code"), "Enter a valid number.");
return;
}
self.data.selectedAccount.type = "id";
self.data.selectedAccount.id = $('#validate-user-code').val();
self.data.selectedAccount.email = " the email address associated with your account.";
}
$("p.email").html("" + self.data.selectedAccount.account + "");
$("img.gravatar.main").attr("src", "//gravatar.com/avatar/" + hex_md5(self.data.selectedAccount.account) + "?default=" + self.options.gravDefault + "&s=100");
$(".a-section").hide();
$(".password-section").show();
$(self.options.passwordField).val("").focus();
$(".invalid").removeClass("invalid");
self.allowPasswordEntry();
$(".password-section .help").css("display", (self.data.selectedAccount.email == null || self.data.selectedAccount.email == "" ? "none" : "block"));
},
cancelPassword: function () {
$(this.options.emailField).val("");
$(this.options.passwordField).val("");
$(".a-section").hide();
$(".email-section").show();
$("img.gravatar.main").attr("src", "//gravatar.com/avatar/53444f91e698c0c7caa2dbc3bdbf93fc?default=mm&s=100");
$(this.options.emailField).focus();
//$("a, input").show();
},
onboardingPasswordSet: false,
login: function () {
var self = this;
var f = $(self.options.passwordField);
self.showLoader();
var email = self.data.selectedAccount.type == "id" ? self.data.selectedAccount.id : self.data.selectedAccount.account, password = f.val();
var verify = "";
if (email == "") email = $(self.options.emailField).val();
console.debug("Login with type ", self.data.selectedAccount.type);
switch (self.data.selectedAccount.type) {
case "google":
email = self.data.selectedAccount.email;
password = self.data.selectedAccount.name;
verify = self.data.selectedAccount.googleVerify + "|" + self.data.selectedAccount.googleToken;
break;
case "magic":
email = self.options.magic.code;
password = self.options.magic.code;
self.data.selectedAccount.passwordPreChange = self.options.magic.code;
break;
}
if (!self.data.selectedAccount.changedPassword) self.data.selectedAccount.changedPassword = "";
if (self.data.selectedAccount.changedPassword != "") {
if (self.data.selectedAccount.passwordPreChange != "") {
password = self.data.selectedAccount.passwordPreChange;
}
}
if (password == "" && self.data.selectedAccount.type != "magic") {
self.showInvalidMessage(f, "Enter a password");
}
else {
var onboardingPassChange = function () {
setTimeout(function () {
$(".onboarding-setup aside ol.steppers").removeClass("activeStep-1").removeClass("activeStep-2").removeClass("activeStep-3").removeClass("activeStep-4").removeClass("activeStep-5").addClass("activeStep-3");
$("#onboarding-verify-email, #onboarding-setup-2fa, #onboarding-magic-failed").hide();
$("#onboarding-change-pass").show();
// make sure we disable the fancy magic loading state
$('body.login-page.magic-loading').removeClass('magic-loading');
self.onboardingPasswordSet = true;
}, 2000);
}
if (!self.data.selectedAccount.secondFactor) self.data.selectedAccount.secondFactor = "";
Durell.CFS.Website.SecureLogin.AttemptLoginNew(self.data.selectedAccount.type + "|:" + email, password, verify, self.options.gotoURL, "00/00/0000", self.data.selectedAccount.secondFactor, self.data.selectedAccount.changedPassword, function (response) {
if (!response.Success) {
if (response.StatusIndicator == null) response.StatusIndicator = "";
if (response.StatusIndicator == "Request2Factor") {
self.prompt2FA();
}
else if (response.StatusIndicator == "Failed2Factor") {
self.prompt2FA();
self.showInvalidMessage($("#validate-ga-code"), "Invalid code. Try again.", true);
if ($("#validate-ga-code").is('.split-input-holder')) $('#validate-code > input').val('');
}
else if (response.StatusIndicator == "Request2FASetup") {
if (onboarding) {
if (self.onboardingPasswordSet === true) {
location.href = "/Portal/Login.aspx?magic=" + self.options.magic.code;
} else {
onboardingPassChange();
}
}
else {
var prts = response.Message.split("||");
self.prompt2FASetup(prts[0], prts[1], prts[2] == "True");
}
}
else if (response.StatusIndicator == "PassChangeOnboarding" && $(".onboarding-setup").length > 0) {
onboardingPassChange();
}
else if (response.StatusIndicator == "PassChangeInitial" || response.StatusIndicator == "PassChangeOnboarding") {
$("#change-password-reason").html("Please choose your own password to continue, include numbers, symbols and a mix of letters for extra security.");
self.data.selectedAccount.passwordPreChange = password;
self.promptPasswordChange();
}
else if (response.StatusIndicator == "PassChangeInsecure") {
$("#change-password-reason").html("Your password is not secure enough and must be changed.");
self.data.selectedAccount.passwordPreChange = password;
self.promptPasswordChange();
} else if (response.StatusIndicator == "PassChangeExpired") {
$("#change-password-reason").html("Your password has expired and must be changed.");
self.data.selectedAccount.passwordPreChange = password;
self.promptPasswordChange();
}
else if (response.StatusIndicator == "PassChangeInsecureChange") {
$("#change-password-reason").html("Sorry you can't use that password, please enter a new one.");
self.data.selectedAccount.passwordPreChange = password;
self.promptPasswordChange();
}
else if (self.data.selectedAccount.type == "magic") {
if (onboarding) {
$("#onboarding-verify-email, #onboarding-setup-2fa, #onboarding-change-pass").hide();
$("#onboarding-magic-failed").show().find("p").html(response.Message);
if (response.StatusIndicator == "MagicCanResend") {
$("#onboard-link-email").val(response.AccountEmail + "");
$("#onboarding-magic-failed footer").show();
}
} else {
// login 2026 specific
if ($(".magic-loader").length > 0) {
$('.a-section').hide();
$('.email-section').show();
$('body.magic-loading').removeClass('magic-loading');
self.showInvalidMessage($("#email"), response.Message, true);
}
else {
$(".magic-section").addClass("magic-failed");
$(".magic-section > p").html(response.Message);
}
$(".load-bar").hide();
}
}
else {
self.showInvalidMessage(f, response.Message, true);
if (response.StatusIndicator == "LockPassword") {
self.lockField(self.options.passwordField);
}
if (!document.getElementById("toast")) {
$("body").append("
");
}
$("#toast").html(response.Message).fadeIn().addClass("error");
setTimeout(function () { $("#toast").fadeOut(); }, 10000);
if (googleAuth === "True") {
gapi.auth2.getAuthInstance().signOut();
}
//durell.cfs.showFeedback(response.ErrorDescription, true, false);
}
}
else {
if (self.data.selectedAccount.type != "google" && self.data.selectedAccount.type != "magic" && $('#remember-email').attr("checked")) {
/* Make sure we haven't already remembered the email */
var alreadyStored = false;
$(self.data.cachedAccounts).each(function () {
if (this.account == self.data.selectedAccount.account) {
alreadyStored = true;
}
});
if (!alreadyStored) {
/* Add the clicked item to the top of the history array */
self.data.cachedAccounts.splice(0, 0, self.data.selectedAccount);
}
self.storeCacheInCookie();
}
if (response.Message.indexOf("=") > -1 && (response.Message + "").split("=")[0] == "/ChangePassword.aspx?URL") {
console.info("Prompt initial password change for verification code usage.");
self.hideLoader();
$(".a-section").hide();
$(".password-reset-section").show();
// make sure we disable the fancy magic loading state
$('body.login-page.magic-loading').removeClass('magic-loading');
}
else {
location.href = response.Message;
}
}
}, function (error) {
if (error._statusCode == 403) {
self.showInvalidMessage(f, "Access to this login form has been restricted as you have made too many failed login attempts. Please try again later.
ID:" + CFSLogin.options.seed);
} else {
self.showInvalidMessage(f, "Something went wrong, please try again.");
}
});
}
},
storeCacheInCookie: function () {
var self = this;
/* Limit the number of items in the history to 5 */
if (self.data.cachedAccounts.length > 5) self.data.cachedAccounts.length = 5;
var accs = "";
$(self.data.cachedAccounts).each(function () {
accs += this.account + "~" + this.type + "~" + this.email + "||";
});
if (accs != "") accs = accs.substr(0, accs.length - 2);
var exdate = new Date(); exdate.setDate(exdate.getDate() + 7);
document.cookie = "_cfs_px_accsn=" + accs + "; expires=" + exdate.toUTCString();
},
showInvalidMessage: function (field, message, noDelay) {
mdDialogCloseBox();
console.warn(message);
field.addClass("invalid");
if (field.parent().find(".invalid-message").length > 0) {
$(".invalid-message", field.parent()).html(message).show();
}
else {
field.parent().append("" + message + "
");
}
field.next().show();
this.hideLoader(noDelay === true ? 0 : 300);
},
showLoader: function () {
$(".standard-button-style:not(.disabled)").addClass("loading").addClass("disabled");
$(".login-box .load-bar").show();
},
hideLoader: function (delay) {
if (!delay || delay == 0) {
$(".standard-button-style.disabled.loading").removeClass("loading").removeClass("disabled");
$(".login-box .load-bar").fadeOut();
}
else {
setTimeout(function () {
$(".standard-button-style.disabled.loading").removeClass("loading").removeClass("disabled");
$(".login-box .load-bar").fadeOut();
}, delay)
}
},
// enable custom input handling for the new 6-box 2FA screen
splitInputHandling: function () {
var fields = $('.split-input-holder');
// doing this as a loop to avoid having to have the query to find the relevant input group on each keypress
fields.each(function () {
var inputs = $(this).find('> input');
const submitOnComplete = () => {
var allInputsFilled = true;
$(inputs).each(function () {
if ($(this).val() === '') return allInputsFilled = false;
})
if (allInputsFilled === true) CFSLogin.validate2FACode();
}
// this is async because we are reading from the clipboard which needs to be async according to the mozilla docs
inputs.off('keydown.login');
inputs.on('keydown.login', function (e) {
// add keys to this array to keep their default behaviour
if (['Tab', 'Escape'].includes(e.key) || (e.key === 'v' && e.ctrlKey)) return;
// prevent default so that we can just do our own thing
e.preventDefault();
// handle moving to the next input when number is entered
if (/^[0-9]+$/.test(e.key)) {
$(this).val(e.key);
// auto submit form when last input is filled
if ($(this).is(inputs.last())) $(this).blur();
else $(this).next().focus();
submitOnComplete();
}
// not 100% sure on the UX of this but we shall see
if (e.key === 'Backspace') {
$(this).val('');
if (!$(this).is(inputs.first())) $(this).prev().focus();
}
if (e.key === 'ArrowLeft') $(this).prev().focus();
if (e.key === 'ArrowRight') $(this).next().focus();
// submit when enter is pressed
if (e.key === 'Enter') {
CFSLogin.validate2FACode();
}
})
inputs.off('paste.login');
inputs.on('paste.login', async function (e) {
try {
var clipboard = await navigator.clipboard.readText();
}
catch (err) {
console.warn("Can't paste from clipboard: " + err);
inputs.blur();
return;
}
// get only the correct amount of numeric characters from the clipboard string
var code = clipboard.replace(/\D/g, "").slice(0, inputs.length);
var startIndex = $(this).index();
inputs.each(function (i) {
var thisIndex = i + startIndex;
if (thisIndex > inputs.length) return;
inputs.eq(thisIndex).val(code[i]);
})
inputs.blur();
submitOnComplete();
})
inputs.off('focus.login');
inputs.on('focus.login', function (e) {
// make sure that the first empty field is always the first one selected, to function similar to a regular input field
if ($(this).val() === '' && $(this).prev().val() === '' && $(this).index() !== 0) {
$(this).prev().focus();
}
else $(this).select();
})
})
},
showPassword: function (f) {
var input = f.closest('.md-input-holder').find('> input').first();
if (input.length === 0) return;
var type = input.attr('type');
if (type === 'password') {
input.attr('type', 'text');
f.addClass('mdi-eye-off');
f.removeClass('mdi-eye');
}
else {
input.attr('type', 'password');
f.addClass('mdi-eye');
f.removeClass('mdi-eye-off');
}
},
showFeedback: function (message, isError, noHide, buttons = [], duration = null, isMD3 = false) {
let toast = document.getElementById("toast")
if (!toast) {
$("body").append("
");
toast = document.getElementById("toast")
}
let html = message
if (Array.isArray(buttons) && buttons.length > 0) {
html += ""
buttons.forEach((button) => {
html += `${button.text}`
})
html += ""
}
$("#toast").removeClass("error").removeClass('clickable').removeClass('md3').html(html).fadeIn();
const lastTimeoutId = toast.getAttribute('data-toast-timeout-id')
if (lastTimeoutId)
clearTimeout(lastTimeoutId)
var durationSecs = duration || 3;
if (isError === "soft") { $("#toast").addClass("soft-error"); durationSecs = 10; }
if (isError === true) { $("#toast").addClass("error"); durationSecs = 10; }
if (Array.isArray(buttons) && buttons.length > 0) $("#toast").addClass("clickable");
if (noHide !== true) {
const timeoutId = setTimeout("CFSLogin.hideToast()", durationSecs * 1000);
toast.setAttribute('data-toast-timeout-id', timeoutId)
}
if (isMD3)
$("#toast").addClass("md3");
},
hideToast: function () {
$("#toast").fadeOut();
const toast = document.getElementById('toast')
if (toast)
toast.setAttribute('data-toast-timeout-id', '')
}
};