Password Strength and confirmation

Sample Registration form and its validations.

by Yashwanth M

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.4/angular-material.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-material/1.1.4/angular-material.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0-beta.2/angular-animate.js"></script>
<body ng-app="loginModule">
<div class="main-container">
<div class="form-container">
<h2 class="form-label">Sign Up</h2>

<div class="form-container" data-ng-controller="registerController" >
	<form name="registerForm" role="form" data-ng-submit="formSubmit()">
		<div class="form-group"><!-- Display Name -->
			<div class="row">
				<!-- 
				The Bootstrap grid system has four classes: xs (phones), sm (tablets), md (desktops), and lg (larger desktops).
				The classes can be combined to create more dynamic and flexible layouts. -->
				<div class="col-md-12 col-xs-12">
				<div class="row inner">
				
					<div class="col-md-6 col-sm-6 col-xs-6  left">
					<div class="error form-hint" 
					data-ng-show="registerForm.firstname.$dirty && registerForm.firstname.$error.required" 
					data-ng-cloak>{{"This field is required."}}
					</div>
					<input type="text" class="form-control" name="firstname" placeholder="First name" 
					data-ng-class="(registerForm.firstname.$dirty && registerForm.firstname.$invalid) ? 'error' : ''"
					data-ng-required="true" data-ng-model="firstName">
					</div>
					
					<div class="col-md-6 col-sm-6 col-xs-6  right">
					<div...

CSS

[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak {
    display: none !important;
}

body {
    background: white;
    margin: 0;
    padding: 0;
}

.main-container {
    display: table;
    width: 400px;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}

.form-container {
    position: relative;
    bottom: 0;
    display: table-cell;
    vertical-align: middle;
}

.form-container form > div {
    padding: 0 15px;
}

.form-container form > button {
    margin-left: 15px;
}

legend.form-label {
    font-size: 24pt;
    padding: 0 15px;
}

.form-control.error {
    border-color: red;
}

.form-hint {
    font-size: 7pt;
    line-height: 9pt;
    margin: -5px auto 5px;
    color: #999;
}

.form-hint.error {
    color: #C00;
    font-weight: bold;
    font-size: 8pt;
}

/* Word Count Button */
.password-count {
	float: right;
	position: relative;
	bottom: 24px;
	right: 10px;
}

.label-success {
  background-color: #5cb85c;
}
.label-danger {
  background-color: #d9534f;
}

/* Strength Meter */
.strength-meter {
	position: relative;
	height: 3px;
	background: #DDD;
	margin: 10px auto 20px;
	border-radius: 3px;
}

.strength-meter:before,
.strength-meter:after {
	content: '';
	height: inherit;
	background: transparent;
	display: block;
	border-color: #FFF;
	border-style: solid;
	border-width: 0 5px 0 5px;
	position: absolute;
	width: 80px;
	z-index: 10;
}

.strength-meter:before {
	left: 70px;
}

.strength-meter:after {
	right: 70px;
}

.strength-meter-fill {
	background: transparent;
	height: inherit;
	position: absolute;
	width: 0;
	border-radius: inherit;
	transition: width 0.5s ease-in-out, background 0.25s;
}

.strength-meter-fill[data-strength='0'] {
	background: darkred;
	width: 20%;
}

.strength-meter-fill[data-strength='1'] {
	background: orangered;
	width: 40%;
}

.strength-meter-fill[data-strength='2'] {
	background: orange;
	width: 60%;
}

.strength-meter-fill[data-strength='3']...

JavaScript

(function( ng ) {

	var loginModule = ng.module('loginModule', ['ngMaterial']);
	
	loginModule.constant('USERCONSTANTS', (function() {
		return {
			PASSWORD_LENGTH: 7
		}
	})());

	loginModule.controller('registerController', ['$scope','$http', '$window', '$location', '$mdDialog', registerControllerFun]);
	function registerControllerFun($scope, $http, $window, $location, $mdDialog) {
		console.log(' registerControllerFun...');
    
    //https://material.angularjs.org/latest/demo/dialog
    $scope.showAlert = function(ev) {
    // Appending dialog to document.body to cover sidenav in docs app
    // Modal dialogs should fully cover application
    // to prevent interaction outside of dialog
    $mdDialog.show(
      $mdDialog.alert()
        .parent(angular.element(document.querySelector('#popupContainer')))
        .clickOutsideToClose(true)
        .title('This is an alert title')
        .textContent('You can specify some description text in here.')
        .ariaLabel('Alert Dialog Demo')
        .ok('Got it!')
        .targetEvent(ev)
    );
  };
	}
	loginModule.factory('myfactory', [function() {
		return {
			score: function() {
				//console.log('arguments List : ', arguments);
				var score = 0, value = arguments[0], passwordLength = arguments[1];
				var containsLetter = /[a-zA-Z]/.test(value), containsDigit = /\d/.test(value), containsSpecial = /[^a-zA-Z\d]/.test(value);
				var containsAll = containsLetter && containsDigit && containsSpecial;
				
				console.log(" containsLetter - ", containsLetter,
						" : containsDigit - ", containsDigit,
						" : containsSpecial - ", containsSpecial);
				
				if( value.length == 0 ) {
					score = 0;
				} else {
					if( containsAll ) {
						score += 3;
					} else {
						if( containsLetter ) score += 1;
						if( containsDigit ) score += 1;
						if( containsSpecial ) score += 1;
					}
					if(value.length >= passwordLength ) score += 1;
				}
				/*console.log('Factory Arguments : ', value, " « Score : ",...