You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

jquery.strengthify.js 8.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /**
  2. * Strengthify - show the weakness of a password (uses zxcvbn for this)
  3. * https://github.com/MorrisJobke/strengthify
  4. *
  5. * Version: 0.5.5
  6. * Author: Morris Jobke (github.com/MorrisJobke) - original
  7. * Eve Ragins @ Eve Corp (github.com/eve-corp)
  8. *
  9. *
  10. * License:
  11. *
  12. * The MIT License (MIT)
  13. *
  14. * Copyright (c) 2013-2016 Morris Jobke <morris.jobke@gmail.com>
  15. *
  16. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  17. * this software and associated documentation files (the "Software"), to deal in
  18. * the Software without restriction, including without limitation the rights to
  19. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  20. * the Software, and to permit persons to whom the Software is furnished to do so,
  21. * subject to the following conditions:
  22. *
  23. * The above copyright notice and this permission notice shall be included in all
  24. * copies or substantial portions of the Software.
  25. *
  26. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  27. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  28. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  29. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  30. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  32. */
  33. /* global jQuery */
  34. (function($) {
  35. $.fn.strengthify = function(paramOptions) {
  36. "use strict";
  37. var defaults = {
  38. zxcvbn: 'zxcvbn/zxcvbn.js',
  39. titles: [
  40. 'Weakest',
  41. 'Weak',
  42. 'So-so',
  43. 'Good',
  44. 'Perfect'
  45. ],
  46. tilesOptions:{
  47. tooltip: true,
  48. element: false
  49. },
  50. drawTitles: false,
  51. drawMessage: false,
  52. drawBars: true,
  53. $addAfter: null,
  54. nonce: null
  55. };
  56. return this.each(function() {
  57. var options = $.extend(defaults, paramOptions);
  58. if (!options.drawTitles
  59. && !options.drawMessage
  60. && !options.drawBars)
  61. console.warn("expect at least one of 'drawTitles', 'drawMessage', or 'drawBars' to be true");
  62. function getWrapperFor(id) {
  63. return $('div[data-strengthifyFor="' + id + '"]');
  64. };
  65. function drawStrengthify() {
  66. var password = $(this).val(),
  67. elemId = $(this).attr('id'),
  68. // hide strengthify if no input is provided
  69. opacity = (password === '') ? 0 : 1,
  70. // calculate result
  71. result = zxcvbn(password),
  72. // setup some vars for later
  73. css = '',
  74. bsLevel = '',
  75. message = '',
  76. // cache jQuery selections
  77. $wrapper = getWrapperFor(elemId),
  78. $container = $wrapper.find('.strengthify-container'),
  79. $message = $wrapper.find('[data-strengthifyMessage]');
  80. $wrapper.children()
  81. .css('opacity', opacity)
  82. .css('-ms-filter',
  83. '"progid:DXImageTransform.Microsoft.Alpha(Opacity=' + opacity * 100 + ')"'
  84. );
  85. if (options.onResult) {
  86. options.onResult(result);
  87. }
  88. // style strengthify bar
  89. // possible scores: 0-4
  90. switch (result.score) {
  91. case 0:
  92. case 1:
  93. css = 'password-bad';
  94. bsLevel = 'danger';
  95. message = result.feedback ? result.feedback.suggestions.join('<br/>') : "";
  96. break;
  97. case 2:
  98. bsLevel = 'warning';
  99. message = result.feedback ? result.feedback.suggestions.join('<br/>') : "";
  100. css = 'password-medium';
  101. break;
  102. case 3:
  103. css = 'password-good';
  104. bsLevel = 'info';
  105. message = "Getting better.";
  106. break;
  107. case 4:
  108. css = 'password-good';
  109. bsLevel = 'success';
  110. message = "Looks good.";
  111. break;
  112. }
  113. if ($message) {
  114. $message.removeAttr('class');
  115. $message.addClass('bg-' + bsLevel);
  116. // reset state for empty string password
  117. if (password === '') {
  118. message = '';
  119. }
  120. $message.html(message);
  121. }
  122. if ($container) {
  123. $container
  124. .attr('class', css + ' strengthify-container')
  125. // possible scores: 0-4
  126. .css(
  127. 'width',
  128. // if score is '0' it will be changed to '1' to
  129. // not hide strengthify if the password is extremely weak
  130. ((result.score === 0 ? 1 : result.score) * 25) + '%'
  131. );
  132. // reset state for empty string password
  133. if (password === '') {
  134. $container.css('width', 0);
  135. }
  136. }
  137. if (options.drawTitles) {
  138. // set a title for the wrapper
  139. if(options.tilesOptions.tooltip){
  140. $wrapper.attr(
  141. 'title',
  142. options.titles[result.score]
  143. ).tooltip({
  144. placement: 'bottom',
  145. trigger: 'manual',
  146. }).tooltip(
  147. 'fixTitle'
  148. ).tooltip(
  149. 'show'
  150. );
  151. if (opacity === 0) {
  152. $wrapper.tooltip(
  153. 'hide'
  154. );
  155. }
  156. }
  157. if(options.tilesOptions.element){
  158. $wrapper.find(".strengthify-tiles").text(options.titles[result.score]);
  159. }
  160. }
  161. };
  162. function init() {
  163. var $elem = $(this),
  164. elemId = $elem.attr('id');
  165. var drawSelf = drawStrengthify.bind(this);
  166. var $addAfter = options.$addAfter;
  167. if (!$addAfter) {
  168. $addAfter = $elem;
  169. }
  170. // add elements
  171. $addAfter.after('<div class="strengthify-wrapper" data-strengthifyFor="' + $elem.attr('id') + '"></div>');
  172. if (options.drawBars) {
  173. getWrapperFor(elemId)
  174. .append('<div class="strengthify-bg" />')
  175. .append('<div class="strengthify-container" />')
  176. .append('<div class="strengthify-separator" style="left: 25%" />')
  177. .append('<div class="strengthify-separator" style="left: 50%" />')
  178. .append('<div class="strengthify-separator" style="left: 75%" />');
  179. }
  180. if (options.drawMessage) {
  181. getWrapperFor(elemId).append('<div data-strengthifyMessage></div>');
  182. }
  183. if (options.drawTitles && options.tilesOptions) {
  184. getWrapperFor(elemId).append('<div class="strengthify-tiles"></div>');
  185. }
  186. $elem.parent().on('scroll', drawSelf);
  187. var script = document.createElement("script");
  188. script.src = options.zxcvbn;
  189. if (options.nonce !== null) {
  190. script.nonce = options.nonce;
  191. }
  192. document.head.appendChild(script);
  193. $elem.bind('keyup input change', drawSelf);
  194. };
  195. init.call(this);
  196. //return me;
  197. });
  198. };
  199. } (jQuery));