(function ($, Drupal) {
Drupal.BootstrapPassword = function (element) {
var self = this;
var $element = $(element);
this.settings = Drupal.settings.password;
this.$wrapper = $element.parent().parent();
this.$row = $('
').prependTo(this.$wrapper);
// The password object.
this.password = {
$input: $element,
$label: $element.parent().find('label'),
$wrapper: $element.parent().addClass('col-sm-6 col-md-4 has-feedback').appendTo(self.$row)
};
this.password.$icon = $('
').appendTo(this.password.$wrapper);
// Strength meter.
this.strength = {
$label: $('
').appendTo(this.password.$label),
$progress: $('
').appendTo(this.password.$wrapper)
};
this.strength.$bar = this.strength.$progress.find('.progress-bar');
// The confirmation object.
this.confirm = {
$input: this.$wrapper.find('input.password-confirm')
};
this.confirm.$wrapper = this.confirm.$input.parent().addClass('col-sm-6 col-md-4 has-feedback').appendTo(self.$row);
this.confirm.$icon = $('
').appendTo(this.confirm.$wrapper);
// Bind events.
this.password.$input.on('keyup focus blur', function () {
self.validateStrength();
});
this.confirm.$input.on('keyup blur', function () {
self.validateMatch();
});
// Add password help at the of row.
this.$helpBlock = $('
').appendTo(this.$row);
return this;
};
/**
* Helper method to switch classes on elements based on status.
*
* @param {jQuery} $element
* The jQuery element to modify.
* @param {string} type
* The name of the class to switch to. Can be one of: "danger", "info",
* "success" or "warning".
* @param {string} prefix
* The prefix to use. Typically this would be something like "label" or
* "progress-bar".
*/
Drupal.BootstrapPassword.prototype.switchClass = function ($element, type, prefix) {
prefix = prefix + '-' || '';
var types = prefix === 'has-' ? ['error', 'warning', 'success'] : ['danger', 'info', 'success', 'warning'];
if (type) {
type = types.splice($.inArray(type, types), 1).shift();
$element.addClass(prefix + type);
}
$element.removeClass(prefix + types.join(' ' + prefix));
};
/**
* Validates the strength of a password.
*/
Drupal.BootstrapPassword.prototype.validateStrength = function () {
var result = Drupal.evaluatePasswordStrength(this.password.$input.val(), Drupal.settings.password);
// Ensure visibility.
this.$helpBlock.show();
this.strength.$label.show();
this.strength.$bar.show();
// Update the suggestions for how to improve the password.
this.$helpBlock.html(result.message);
// Only show the description box if there is a weakness in the password.
this.$helpBlock[result.strength === 100 ? 'hide' : 'show']();
// Update the strength indication text.
this.strength.$label.html(result.indicatorText);
// Adjust the length of the strength indicator.
this.strength.$bar.attr('aria-valuenow', result.strength);
this.strength.$bar.css('width', result.strength + '%');
// Change the classes (color) of the strength meter based on result level.
switch (result.indicatorText) {
case this.settings.weak:
this.switchClass(this.password.$wrapper, 'error', 'has');
this.switchClass(this.strength.$label, 'danger', 'label');
this.switchClass(this.strength.$bar, 'danger', 'progress-bar');
this.password.$icon.addClass('glyphicon-remove').removeClass('glyphicon-warning-sign glyphicon-ok');
break;
case this.settings.fair:
case this.settings.good:
this.switchClass(this.password.$wrapper, 'warning', 'has');
this.switchClass(this.strength.$label, 'warning', 'label');
this.switchClass(this.strength.$bar, 'warning', 'progress-bar');
this.password.$icon.addClass('glyphicon-warning-sign').removeClass('glyphicon-remove glyphicon-ok');
break;
case this.settings.strong:
this.switchClass(this.password.$wrapper, 'success', 'has');
this.switchClass(this.strength.$label, 'success', 'label');
this.switchClass(this.strength.$bar, 'success', 'progress-bar');
this.password.$icon.addClass('glyphicon-ok').removeClass('glyphicon-warning-sign glyphicon-remove');
break;
}
this.validateMatch();
};
/**
* Validates both original and confirmation passwords to ensure they match.
*/
Drupal.BootstrapPassword.prototype.validateMatch = function () {
var password = this.password.$input.val();
// Passwords match.
if (password && password === this.confirm.$input.val()) {
this.switchClass(this.password.$wrapper, 'success', 'has');
this.switchClass(this.confirm.$wrapper, 'success', 'has');
this.$helpBlock.hide();
this.strength.$label.hide();
this.strength.$bar.hide();
this.password.$icon.addClass('glyphicon-ok').removeClass('glyphicon-warning-sign glyphicon-remove');
this.confirm.$icon.addClass('glyphicon-ok').removeClass('glyphicon-remove');
}
// Passwords do not match.
else if (password) {
this.switchClass(this.confirm.$wrapper, 'error', 'has');
this.confirm.$icon.addClass('glyphicon-remove').removeClass('glyphicon-ok');
}
// No password.
else {
this.confirm.$icon.removeClass('glyphicon-ok glyphicon-remove');
this.confirm.$input.val('');
this.switchClass(this.confirm.$wrapper, '', 'has');
}
};
/**
* Overrides core JS for password strength and confirmation.
*
* Attach handlers to evaluate the strength of any password fields and to check
* that its confirmation is correct.
*/
Drupal.behaviors.password = {
attach: function (context) {
$('input.password-field', context).once('password', function () {
new Drupal.BootstrapPassword(this);
});
}
};
})(jQuery, window.Drupal);