Personally not pleased with the speed of the AJAX portion of this. Perhaps I'll learn some performance and optimization tricks as I get more familiar with it.
View with scripting disabled.
Source Code
<!--- password_strength ---> <cfparam name="url.action" default=""> <cfscript> app = StructNew(); app.valid_data = 1; app.errormessage = 'We encountered errors in the information you submitted. Please check the fields marked below and try again.'; app.errorPrefix = '<p class="error">'; app.errorSuffix = '</p>'; error = StructNew(); </cfscript> <cfswitch expression="#LCase(url.action)#"> <cfcase value=""> <cfinclude template="password_strength/act_password_strength.cfm"> <cfif LCase(cgi.request_method) EQ "post"> <cfinclude template="password_strength/val_password_strength.cfm"> <cfinclude template="password_strength/pro_password_strength.cfm"> </cfif> <cfinclude template="password_strength/dsp_password_strength.cfm"> </cfcase> <cfcase value="strength"> <cfinclude template="password_strength/ajx_password_strength.cfm"> </cfcase> </cfswitch>
<!--- act_password_strength ---> <cfparam name="url.js" default="1"> <cfparam name="form.js" default="#Val(url.js)#"> <cfparam name="form.password" default=""> <cfparam name="form.strength_password" default="0"> <cfscript> levels_strength_password = ListToArray('Not rated,Weak,Medium,Strong,Super Strong'); error.password = ''; error.strength_password = ''; </cfscript>
<!--- dsp_strength_password ---> <cfoutput> <cf_head tag="script" type="text/javascript"> function initPasswordStrength() { }; </cf_head> <cf_head tag="script" type="text/javascript" src="/scripts/password.ajax.js"> <cf_head tag="script" type="text/javascript" src="/scripts/ajax/prototype.js"> <cfif NOT Val(app.valid_data)> #app.errorPrefix##app.errorMessage##app.errorSuffix# </cfif> <cfif FileExists(app.starting_disk_path & app.static.root & "/content/" & app.section & "/" & app.subsection & "/" & app.subsubsection & ".txt")> <cfinclude template="#app.mapping##app.static.root#/content/#app.section#/#app.subsection#/#app.subsubsection#.txt"> </cfif> <p>View with scripting <cfif Val(form.js)><a href="?js=0">disabled</a><cfelse><a href="?js=1">enabled</a></cfif>.</p> <form name="example" action="#app.script_name#" method="post"> <input type="hidden" name="js" value="#Val(form.js)#" /> <p><strong>Bold</strong> fields are required.</p> <fieldset><legend>Login Information</legend> <div class="notes"> <h4>Login Information</h4> <p>Your password must be at least 8 characters long and are case-sensitive. Please do not enter accented characters.</p> <p>We recommend that your password is not a word you can find in the dictionary, includes both capital and lower case letters, and contains at least one special character (1-9, !, *, _, etc.).</p> <p class="last">We do <strong>not</strong> log the passwords used in testing this example. However, SSL is not used and care should be taken to not expose mission-critical passwords.</p> </div> <div class="required<cfif Len(error.password)> error</cfif>"> #error.password# <label for="password">Password:</label> <input type="password" name="password" id="password" class="inputPassword" size="10" maxlength="25" value="#Replace(form.password, """", """, "ALL")#" /> <small>Must be 8-25 characters long.</small> </div> <div id="password_updater"></div> <div class="optional<cfif Len(error.strength_password)> error</cfif>"> #error.strength_password# <label>Password Strength:</label><cfloop from="1" to="#ArrayLen(levels_strength_password)#" index="level"> <label for="strength_password_#Val(level)#" class="labelRadio"><input type="radio" name="strength_password" id="strength_password_#Val(level)#" class="inputRadio" value="#Val(level - 1)#"<cfif Val(form.strength_password) EQ Val(level - 1)> checked="checked"</cfif> disabled="disabled" /> <span>#Trim(levels_strength_password[level])#</span></label></cfloop> <cfif Val(form.js)> <script language="JavaScript" type="text/javascript"> <!-- initPasswordStrength(document.forms['example'], 'password'); //--> </script> </cfif> </div> </fieldset> <fieldset class="submit"> <input type="submit" class="inputSubmit" value="Submit »" /> </fieldset> </form> </cfoutput>
/* password.ajax.js */
var nLevels = [[198, '#ffffff', '#666666'], [67, '#ff4545', '#000000'], [133, '#ffd35e', '#000000'], [198, '#3abb1c', '#000000'], [198, '#000000', '#ffffff']];
function initPasswordStrength(oForm)
{
var i = 1;
var oPassword = oForm.password;
if(oPassword)
{
oPassword.onkeyup = function() { getPasswordStrengthRemote(this); };
// oPassword.onmouseout = function() { getPasswordStrengthRemote(this); };
// oPassword.onblur = function() { getPasswordStrengthRemote(this); };
for(i = 1; i <= nLevels.length; i++)
{
oElement = oForm.strength_password[i - 1];
if(oElement)
{
oElement.style.display = 'none';
oElement.disabled = false;
oLabel = oElement.parentNode;
if(oLabel)
{
oLabel.style.width = '206px';
oLabel.style.color = nLevels[i - 1][2];
oLabel.style.border = '2px inset #ffffff';
oLabel.style.fontSize = '100%';
oLabel.style.padding = '0px 0px 0px 0px';
oLabel.style.margin = '0px 0px 0px 140px';
oLabel.style.textIndent = '0px';
oLabel.style.display = (!oElement.checked) ? 'none' : '';
oSpan = oLabel.getElementsByTagName('SPAN')[0];
oSpan.style.display = 'block';
oSpan.style.width = nLevels[i - 1][0] + 'px';
oSpan.style.backgroundColor = nLevels[i - 1][1];
oSpan.style.padding = '1px 4px';
oSpan.style.textAlign = 'center';
oSpan.style.fontSize = '100%';
oSpan.style.fontWeight = (i == 1) ? 'normal' : 'bold';
}
}
}
}
};
function getPasswordStrengthRemote(oElement)
{
var oForm = oElement.form;
var sPassword = oElement.value;
var passwordAJAX = new Ajax.Request(
'/code/coldfusion/password_strength'
, {
method: 'get'
, parameters: 'action=strength&password=" + escape(sPassword)
, onComplete: setPasswordStrengthRemote
}
);
}
function setPasswordStrengthRemote(response)
{
var oForm = $("strength_password').form;
var nStrength = parseInt(response.responseText, 10);
for(i = 0; i < nLevels.length; i++)
{
var oElement = oForm.strength_password[i];
if(oElement)
{
if(i == nStrength)
oElement.checked = true;
var oLabel = oElement.parentNode;
if(oLabel)
oLabel.style.display = (i != nStrength) ? 'none' : '';
}
}
}
<!--- ajx_password_strength ---> <cfparam name="url.password" default=""> <cfscript> password_strength_checker = CreateObject('component', 'webservices.password').Instantiate(); strength_password = password_strength_checker.GetStrength(url.password); </cfscript> <cfcontent reset="Yes" type="text/plain"> <cfoutput>#Val(strength_password)#</cfoutput> <cfabort>
<!--- val_password_strength ---> <cfscript> if(NOT Len(form.password)) error.password = 'Required.'; else if(Len(form.password) LT 8) error.password = 'The password entered is too short. It must be at least 8 characters.'; else if(Len(form.password) GT 25) error.password = 'The password entered is too long. It cannot be longer than 25 characters.'; password_strength_checker = CreateObject('component', 'webservices.password').Instantiate(); form.strength_password = password_strength_checker.GetStrength(form.password); if(Val(form.strength_password) LT 3) error.strength_password = 'Password Strength must be at least ' & levels_strength_password[4] & ' or better.'; for(key IN error) { if(Len(error[key])) { error[key] = app.errorPrefix & error[key] & app.errorSuffix; app.valid_data = 0; } } </cfscript>
<!--- pro_password_strength ---> <cfif Val(app.valid_data)> <!--- Everything is validated, do whatever the app is supposed to do with valid data ---> </cfif>