jquery-strength.es.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /**
  2. * jQuery strength v0.2.5
  3. * https://github.com/amazingSurge/jquery-strength
  4. *
  5. * Copyright (c) amazingSurge
  6. * Released under the LGPL-3.0 license
  7. */
  8. import $ from 'jquery';
  9. import PasswordStrength from 'password_strength';
  10. var DEFAULTS = {
  11. namespace: 'strength',
  12. skin: null,
  13. showMeter: true,
  14. showToggle: true,
  15. usernameField: '',
  16. templates: {
  17. toggle: '<span class="input-group-addon"><input type="checkbox" class="{toggleClass}" title="Show/Hide Password" /></span>',
  18. meter: '<div class="{meterClass}">{score}</div>',
  19. score: '<span class="label {scoreClass}"></span>',
  20. main: '<div class="{containerClass}"><div class="input-group">{input}{toggle}</div>{meter}</div>'
  21. },
  22. classes: {
  23. container: 'strength-container',
  24. status: 'strength-{status}',
  25. input: 'strength-input',
  26. toggle: 'strength-toggle',
  27. meter: 'strength-meter',
  28. score: 'strength-score',
  29. shown: 'strength-shown'
  30. },
  31. scoreLables: {
  32. empty: 'Empty',
  33. invalid: 'Invalid',
  34. weak: 'Weak',
  35. good: 'Good',
  36. strong: 'Strong'
  37. },
  38. scoreClasses: {
  39. empty: '',
  40. invalid: 'label-danger',
  41. weak: 'label-warning',
  42. good: 'label-info',
  43. strong: 'label-success'
  44. },
  45. emptyStatus: true,
  46. scoreCallback: null,
  47. statusCallback: null
  48. };
  49. const NAMESPACE$1 = 'strength';
  50. /**
  51. * Plugin constructor
  52. **/
  53. class Strength {
  54. constructor(element, options = {}) {
  55. this.element = element;
  56. this.$element = $(element);
  57. this.options = $.extend(true, {}, DEFAULTS, options, this.$element.data());
  58. this.classes = this.options.classes;
  59. this.$username = $(this.options.usernameField);
  60. this.score = 0;
  61. this.status = null;
  62. this.shown = false;
  63. this.trigger('init');
  64. this.init();
  65. }
  66. init() {
  67. this.createHtml();
  68. this.$element.addClass(this.classes.input);
  69. this.$toggle = this.$container.find(`.${this.classes.toggle}`);
  70. this.$meter = this.$container.find(`.${this.classes.meter}`);
  71. this.$score = this.$container.find(`.${this.classes.score}`);
  72. this.$input = this.$container.find(`.${this.classes.input}`);
  73. this.bindEvents();
  74. this.initialized = true;
  75. this.trigger('ready');
  76. }
  77. bindEvents() {
  78. if(this.$toggle.is(':checkbox')){
  79. this.$toggle.on('change', () => {
  80. this.toggle();
  81. });
  82. } else {
  83. this.$toggle.on('click', () => {
  84. this.toggle();
  85. });
  86. }
  87. this.$input.bind('keyup.strength keydown.strength', () => {
  88. this.check();
  89. });
  90. this.$element.on(`${NAMESPACE$1}::check`, (e, api, score, status) => {
  91. this.$score.html(this.options.scoreLables[status]);
  92. if (status !== this.status) {
  93. const newClass = this.options.scoreClasses[status];
  94. const oldClass = this.options.scoreClasses[this.status];
  95. this.$score.removeClass(oldClass).addClass(newClass);
  96. this.trigger('statusChange', status, this.status);
  97. }
  98. this.status = status;
  99. this.score = score;
  100. });
  101. this.$element.on(`${NAMESPACE$1}::statusChange`, (e, api, current, old) => {
  102. this.$container.removeClass(this.getStatusClass(old)).addClass(this.getStatusClass(current));
  103. });
  104. }
  105. getStatusClass(status) {
  106. return this.options.classes.status.replace('{status}', status);
  107. }
  108. createHtml() {
  109. let output = this.options.templates.main;
  110. output = output.replace('{containerClass}', this.classes.container);
  111. output = output.replace('{toggle}', this.generateToggle());
  112. output = output.replace('{meter}', this.generateMeter());
  113. output = output.replace('{score}', this.generateScore());
  114. output = output.replace('{input}', `<div class="${this.classes.input}"></div>`);
  115. this.$container = $(output);
  116. if (this.options.skin) {
  117. this.$container.addClass(this.options.skin);
  118. }
  119. this.$element.before(this.$container);
  120. const $holder = this.$container.find(`.${this.classes.input}`);
  121. const el = this.$element.detach();
  122. $holder.before(el);
  123. $holder.remove();
  124. }
  125. generateToggle() {
  126. if (this.options.showToggle) {
  127. let output = this.options.templates.toggle;
  128. output = output.replace('{toggleClass}', this.classes.toggle);
  129. return output;
  130. }
  131. return '';
  132. }
  133. generateMeter() {
  134. if (this.options.showMeter) {
  135. let output = this.options.templates.meter;
  136. output = output.replace('{meterClass}', this.classes.meter);
  137. return output;
  138. }
  139. return '';
  140. }
  141. generateScore() {
  142. let output = this.options.templates.score;
  143. output = output.replace('{scoreClass}', this.classes.score);
  144. return output;
  145. }
  146. check() {
  147. let score = 0;
  148. let status = null;
  149. if ($.isFunction(this.options.scoreCallback)) {
  150. score = this.options.scoreCallback.call(this);
  151. if ($.isFunction(this.options.statusCallback)) {
  152. status = this.options.statusCallback.call(this, score);
  153. }
  154. } else {
  155. const check = new PasswordStrength();
  156. check.username = this.$username.val() || null;
  157. check.password = this.$input.val();
  158. score = check.test();
  159. status = check.status;
  160. }
  161. if (this.options.emptyStatus && status !== 'invalid' && this.$input.val() === '') {
  162. status = 'empty';
  163. }
  164. this.trigger('check', score, status);
  165. }
  166. getScore() {
  167. if (!this.score) {
  168. this.check();
  169. }
  170. return this.score;
  171. }
  172. getStatus() {
  173. if (!this.status) {
  174. this.check();
  175. }
  176. return this.status;
  177. }
  178. toggle() {
  179. let type;
  180. if(this.$toggle.is(':checkbox')) {
  181. type = this.$toggle.is(":checked")? "text" : "password";
  182. } else {
  183. type = this.shown === false?"text" : "password";
  184. }
  185. this.shown = type === "text";
  186. if(this.shown) {
  187. this.$container.addClass(this.classes.shown);
  188. } else {
  189. this.$container.removeClass(this.classes.shown);
  190. }
  191. this.$input.attr('type', type);
  192. this.trigger('toggle', type);
  193. }
  194. trigger(eventType, ...params) {
  195. let data = [this].concat(params);
  196. // event
  197. this.$element.trigger(`${NAMESPACE$1}::${eventType}`, data);
  198. // callback
  199. eventType = eventType.replace(/\b\w+\b/g, (word) => {
  200. return word.substring(0, 1).toUpperCase() + word.substring(1);
  201. });
  202. let onFunction = `on${eventType}`;
  203. if (typeof this.options[onFunction] === 'function') {
  204. this.options[onFunction].apply(this, params);
  205. }
  206. }
  207. destroy() {
  208. this.$element.data(NAMESPACE$1, null);
  209. this.trigger('destroy');
  210. }
  211. static setDefaults(options) {
  212. $.extend(true, DEFAULTS, $.isPlainObject(options) && options);
  213. }
  214. }
  215. var info = {
  216. version:'0.2.5'
  217. };
  218. const NAMESPACE = 'strength';
  219. const OtherStrength = $.fn.strength;
  220. const jQueryStrength = function(options, ...args) {
  221. if (typeof options === 'string') {
  222. const method = options;
  223. if (/^_/.test(method)) {
  224. return false;
  225. } else if ((/^(get)/.test(method))) {
  226. const instance = this.first().data(NAMESPACE);
  227. if (instance && typeof instance[method] === 'function') {
  228. return instance[method](...args);
  229. }
  230. } else {
  231. return this.each(function() {
  232. const instance = $.data(this, NAMESPACE);
  233. if (instance && typeof instance[method] === 'function') {
  234. instance[method](...args);
  235. }
  236. });
  237. }
  238. }
  239. return this.each(function() {
  240. if (!$(this).data(NAMESPACE)) {
  241. $(this).data(NAMESPACE, new Strength(this, options));
  242. }
  243. });
  244. };
  245. $.fn.strength = jQueryStrength;
  246. $.strength = $.extend({
  247. setDefaults: Strength.setDefaults,
  248. noConflict: function() {
  249. $.fn.strength = OtherStrength;
  250. return jQueryStrength;
  251. }
  252. }, info);