PageSourceSearch

https://members.macmh.org/js/plugins/pwstrength/pwstrength-bootstrap.js

js macmh.org collected 2026-09-24 09:52:31 UTC 26,995 bytes, 854 lines download raw bytes

1/*!
2* jQuery Password Strength plugin for Twitter Bootstrap
3* Version: 2.1.1
4*
5* Copyright (c) 2008-2013 Tane Piper
6* Copyright (c) 2013 Alejandro Blanco
7* Dual licensed under the MIT and GPL licenses.
8*/
9
10(function (jQuery) {
11// Source: src/i18n.js
12
13
14
15
16var i18n = {};
17
18(function (i18n, i18next) {
19    'use strict';
20
21    i18n.fallback = {
22        "wordMinLength": "Your password is too short",
23        "wordMaxLength": "Your password is too long",
24        "wordInvalidChar": "Your password contains an invalid character",
25        "wordNotEmail": "Do not use your email as your password",
26        "wordSimilarToUsername": "Your password cannot contain your username",
27        "wordTwoCharacterClasses": "Use different character classes",
28        "wordRepetitions": "Too many repetitions",
29        "wordSequences": "Your password contains sequences",
30        "errorList": "Errors:",
31        "veryWeak": "Very Weak",
32        "weak": "Weak",
33        "normal": "Normal",
34        "medium": "Medium",
35        "strong": "Strong",
36        "veryStrong": "Very Strong"
37    };
38
39    i18n.t = function (key) {
40        var result = '';
41
42        // Try to use i18next.com
43        if (i18next) {
44            result = i18next.t(key);
45        } else {
46            // Fallback to english
47            result = i18n.fallback[key];
48        }
49
50        return result === key ? '' : result;
51    };
52}(i18n, window.i18next));
53
54// Source: src/rules.js
55
56
57
58
59var rulesEngine = {};
60
61try {
62    if (!jQuery && module && module.exports) {
63        var jQuery = require("jquery"),
64            jsdom = require("jsdom").jsdom;
65        jQuery = jQuery(jsdom().defaultView);
66    }
67} catch (ignore) {}
68
69(function ($, rulesEngine) {
70    "use strict";
71    var validation = {};
72
73    rulesEngine.forbiddenSequences = [
74        "0123456789", "abcdefghijklmnopqrstuvwxyz", "qwertyuiop", "asdfghjkl",
75        "zxcvbnm", "!@#$%^&*()_+"
76    ];
77
78    validation.wordNotEmail = function (options, word, score) {
79        if (word.match(/^([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i)) {
80            return score;
81        }
82        return 0;
83    };
84
85    validation.wordMinLength = function (options, word, score) {
86        var wordlen = word.length,
87            lenScore = Math.pow(wordlen, options.rules.raisePower);
88        if (wordlen < options.common.minChar) {
89            lenScore = (lenScore + score);
90        }
91        return lenScore;
92    };
93
94    validation.wordMaxLength = function (options, word, score) {
95        var wordlen = word.length,
96            lenScore = Math.pow(wordlen, options.rules.raisePower);
97        if (wordlen > options.common.maxChar) {
98            return score;
99        }
100        return lenScore;
101    };
102
103    validation.wordInvalidChar = function (options, word, score) {
104        if (word.match(/[\s,',"]/)) {
105            return score;
106        }
107        return 0;
108    };
109
110    validation.wordLengthStaticScore = function (options, word, score) {
111        return word.length < options.common.minChar ? 0 : score;
112    };
113
114    validation.wordSimilarToUsername = function (options, word, score) {
115        var username = $(options.common.usernameField).val();
116        if (username && word.toLowerCase().match(username.replace(/[\-\[\]\/\{\}\(\)\*\+\=\?\:\.\\\^\$\|\!\,]/g, "\\$&").toLowerCase())) {
117            return score;
118        }
119        return 0;
120    };
121
122    validation.wordTwoCharacterClasses = function (options, word, score) {
123        if (word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) ||
124                (word.match(/([a-zA-Z])/) && word.match(/([0-9])/)) ||
125                (word.match(/(.[!,@,#,$,%,\^,&,*,?,_,~])/) && word.match(/[a-zA-Z0-9_]/))) {
126            return score;
127        }
128        return 0;
129    };
130
131    validation.wordRepetitions = function (options, word, score) {
132        if (word.match(/(.)\1\1/)) { return score; }
133        return 0;
134    };
135
136    validation.wordSequences = function (options, word, score) {
137        var found = false,
138            j;
139        if (word.length > 2) {
140            $.each(rulesEngine.forbiddenSequences, function (idx, seq) {
141                if (found) { return; }
142                var sequences = [seq, seq.split('').reverse().join('')];
143                $.each(sequences, function (idx, sequence) {
144                    for (j = 0; j < (word.length - 2); j += 1) { // iterate the word trough a sliding window of size 3:
145                        if (sequence.indexOf(word.toLowerCase().substring(j, j + 3)) > -1) {
146                            found = true;
147                        }
148                    }
149                });
150            });
151            if (found) { return score; }
152        }
153        return 0;
154    };
155
156    validation.wordLowercase = function (options, word, score) {
157        return word.match(/[a-z]/) && score;
158    };
159
160    validation.wordUppercase = function (options, word, score) {
161        return word.match(/[A-Z]/) && score;
162    };
163
164    validation.wordOneNumber = function (options, word, score) {
165        return word.match(/\d+/) && score;
166    };
167
168    validation.wordThreeNumbers = function (options, word, score) {
169        return word.match(/(.*[0-9].*[0-9].*[0-9])/) && score;
170    };
171
172    validation.wordOneSpecialChar = function (options, word, score) {
173        return word.match(/[!,@,#,$,%,\^,&,*,?,_,~]/) && score;
174    };
175
176    validation.wordTwoSpecialChar = function (options, word, score) {
177        return word.match(/(.*[!,@,#,$,%,\^,&,*,?,_,~].*[!,@,#,$,%,\^,&,*,?,_,~])/) && score;
178    };
179
180    validation.wordUpperLowerCombo = function (options, word, score) {
181        return word.match(/([a-z].*[A-Z])|([A-Z].*[a-z])/) && score;
182    };
183
184    validation.wordLetterNumberCombo = function (options, word, score) {
185        return word.match(/([a-zA-Z])/) && word.match(/([0-9])/) && score;
186    };
187
188    validation.wordLetterNumberCharCombo = function (options, word, score) {
189        return word.match(/([a-zA-Z0-9].*[!,@,#,$,%,\^,&,*,?,_,~])|([!,@,#,$,%,\^,&,*,?,_,~].*[a-zA-Z0-9])/) && score;
190    };
191
192    rulesEngine.validation = validation;
193
194    rulesEngine.executeRules = function (options, word) {
195        var totalScore = 0;
196
197        $.each(options.rules.activated, function (rule, active) {
198            if (active) {
199                var score = options.rules.scores[rule],
200                    funct = rulesEngine.validation[rule],
201                    result,
202                    errorMessage;
203
204                if (!$.isFunction(funct)) {
205                    funct = options.rules.extra[rule];
206                }
207
208                if ($.isFunction(funct)) {
209                    result = funct(options, word, score);
210                    if (result) {
211                        totalScore += result;
212                    }
213                    if (result < 0 || (!$.isNumeric(result) && !result)) {
214                        errorMessage = options.ui.spanError(options, rule);
215                        if (errorMessage.length > 0) {
216                            options.instances.errors.push(errorMessage);
217                        }
218                    }
219                }
220            }
221        });
222
223        if ($.isFunction(options.common.onScore)) {
224            totalScore = options.common.onScore(options, word, totalScore);
225        }
226
227        return totalScore;
228    };
229}(jQuery, rulesEngine));
230
231try {
232    if (module && module.exports) {
233        module.exports = rulesEngine;
234    }
235} catch (ignore) {}
236
237// Source: src/options.js
238
239
240
241
242var defaultOptions = {};
243
244defaultOptions.common = {};
245defaultOptions.common.minChar = 6;
246defaultOptions.common.maxChar = 20;
247defaultOptions.common.usernameField = "#username";
248defaultOptions.common.userInputs = [
249    // Selectors for input fields with user input
250];
251defaultOptions.common.onLoad = undefined;
252defaultOptions.common.onKeyUp = undefined;
253defaultOptions.common.onScore = undefined;
254defaultOptions.common.zxcvbn = false;
255defaultOptions.common.zxcvbnTerms = [
256    // List of disrecommended words
257];
258defaultOptions.common.events = ["keyup", "change", "paste"];
259defaultOptions.common.debug = false;
260
261defaultOptions.rules = {};
262defaultOptions.rules.extra = {};
263defaultOptions.rules.scores = {
264    wordNotEmail: -100,
265    wordMinLength: -50,
266    wordMaxLength: -50,
267    wordInvalidChar: -100,
268    wordSimilarToUsername: -100,
269    wordSequences: -20,
270    wordTwoCharacterClasses: 2,
271    wordRepetitions: -25,
272    wordLowercase: 1,
273    wordUppercase: 3,
274    wordOneNumber: 3,
275    wordThreeNumbers: 5,
276    wordOneSpecialChar: 3,
277    wordTwoSpecialChar: 5,
278    wordUpperLowerCombo: 2,
279    wordLetterNumberCombo: 2,
280    wordLetterNumberCharCombo: 2
281};
282defaultOptions.rules.activated = {
283    wordNotEmail: true,
284    wordMinLength: true,
285    wordMaxLength: false,
286    wordInvalidChar: false,
287    wordSimilarToUsername: true,
288    wordSequences: true,
289    wordTwoCharacterClasses: false,
290    wordRepetitions: false,
291    wordLowercase: true,
292    wordUppercase: true,
293    wordOneNumber: true,
294    wordThreeNumbers: true,
295    wordOneSpecialChar: true,
296    wordTwoSpecialChar: true,
297    wordUpperLowerCombo: true,
298    wordLetterNumberCombo: true,
299    wordLetterNumberCharCombo: true
300};
301defaultOptions.rules.raisePower = 1.4;
302
303defaultOptions.ui = {};
304defaultOptions.ui.bootstrap2 = false;
305defaultOptions.ui.bootstrap4 = false;
306defaultOptions.ui.colorClasses = [
307    "danger", "danger", "danger", "warning", "warning", "success"
308];
309defaultOptions.ui.showProgressBar = true;
310defaultOptions.ui.progressBarEmptyPercentage = 1;
311defaultOptions.ui.progressBarMinPercentage = 1;
312defaultOptions.ui.progressExtraCssClasses = '';
313defaultOptions.ui.progressBarExtraCssClasses = '';
314defaultOptions.ui.showPopover = false;
315defaultOptions.ui.popoverPlacement = "bottom";
316defaultOptions.ui.showStatus = false;
317defaultOptions.ui.spanError = function (options, key) {
318    "use strict";
319    var text = options.i18n.t(key);
320    if (!text) { return ''; }
321    return '<span style="color: #d52929">' + text + '</span>';
322};
323defaultOptions.ui.popoverError = function (options) {
324    "use strict";
325    var errors = options.instances.errors,
326        errorsTitle = options.i18n.t("errorList"),
327        message = "<div>" + errorsTitle + "<ul class='error-list' style='margin-bottom: 0;'>";
328
329    jQuery.each(errors, function (idx, err) {
330        message += "<li>" + err + "</li>";
331    });
332    message += "</ul></div>";
333    return message;
334};
335defaultOptions.ui.showVerdicts = true;
336defaultOptions.ui.showVerdictsInsideProgressBar = false;
337defaultOptions.ui.useVerdictCssClass = false;
338defaultOptions.ui.showErrors = false;
339defaultOptions.ui.showScore = false;
340defaultOptions.ui.container = undefined;
341defaultOptions.ui.viewports = {
342    progress: undefined,
343    verdict: undefined,
344    errors: undefined,
345    score: undefined
346};
347defaultOptions.ui.scores = [0, 14, 26, 38, 50];
348
349defaultOptions.i18n = {};
350defaultOptions.i18n.t = i18n.t;
351
352// Source: src/ui.js
353
354
355
356
357var ui = {};
358
359(function ($, ui) {
360    "use strict";
361
362    var statusClasses = ["error", "warning", "success"],
363        verdictKeys = [
364            "veryWeak", "weak", "normal", "medium", "strong", "veryStrong"
365        ];
366
367    ui.getContainer = function (options, $el) {
368        var $container;
369
370        $container = $(options.ui.container);
371        if (!($container && $container.length === 1)) {
372            $container = $el.parent();
373        }
374        return $container;
375    };
376
377    ui.findElement = function ($container, viewport, cssSelector) {
378        if (viewport) {
379            return $container.find(viewport).find(cssSelector);
380        }
381        return $container.find(cssSelector);
382    };
383
384    ui.getUIElements = function (options, $el) {
385        var $container, result;
386
387        if (options.instances.viewports) {
388            return options.instances.viewports;
389        }
390
391        $container = ui.getContainer(options, $el);
392
393        result = {};
394        result.$progressbar = ui.findElement($container, options.ui.viewports.progress, "div.progress");
395        if (options.ui.showVerdictsInsideProgressBar) {
396            result.$verdict = result.$progressbar.find("span.password-verdict");
397        }
398
399        if (!options.ui.showPopover) {
400            if (!options.ui.showVerdictsInsideProgressBar) {
401                result.$verdict = ui.findElement($container, options.ui.viewports.verdict, "span.password-verdict");
402            }
403            result.$errors = ui.findElement($container, options.ui.viewports.errors, "ul.error-list");
404        }
405        result.$score = ui.findElement($container, options.ui.viewports.score,
406                                       "span.password-score");
407
408        options.instances.viewports = result;
409        return result;
410    };
411
412    ui.initProgressBar = function (options, $el) {
413        var $container = ui.getContainer(options, $el),
414            progressbar = "<div class='progress ";
415
416        if (options.ui.bootstrap2) {
417            // Boostrap 2
418            progressbar += options.ui.progressBarExtraCssClasses +
419                "'><div class='";
420        } else {
421            // Bootstrap 3 & 4
422            progressbar += options.ui.progressExtraCssClasses + "'><div class='" +
423                options.ui.progressBarExtraCssClasses + " progress-";
424        }
425        progressbar += "bar'>";
426
427        if (options.ui.showVerdictsInsideProgressBar) {
428            progressbar += "<span class='password-verdict'></span>";
429        }
430
431        progressbar += "</div></div>";
432
433        if (options.ui.viewports.progress) {
434            $container.find(options.ui.viewports.progress).append(progressbar);
435        } else {
436            $(progressbar).insertAfter($el);
437        }
438    };
439
440    ui.initHelper = function (options, $el, html, viewport) {
441        var $container = ui.getContainer(options, $el);
442        if (viewport) {
443            $container.find(viewport).append(html);
444        } else {
445            $(html).insertAfter($el);
446        }
447    };
448
449    ui.initVerdict = function (options, $el) {
450        ui.initHelper(options, $el, "<span class='password-verdict'></span>",
451                      options.ui.viewports.verdict);
452    };
453
454    ui.initErrorList = function (options, $el) {
455        ui.initHelper(options, $el, "<ul class='error-list'></ul>",
456                      options.ui.viewports.errors);
457    };
458
459    ui.initScore = function (options, $el) {
460        ui.initHelper(options, $el, "<span class='password-score'></span>",
461                      options.ui.viewports.score);
462    };
463
464    ui.initPopover = function (options, $el) {
465        $el.popover("destroy");
466        $el.popover({
467            html: true,
468            placement: options.ui.popoverPlacement,
469            trigger: "manual",
470            content: " "
471        });
472    };
473
474    ui.initUI = function (options, $el) {
475        if (options.ui.showPopover) {
476            ui.initPopover(options, $el);
477        } else {
478            if (options.ui.showErrors) { ui.initErrorList(options, $el); }
479            if (options.ui.showVerdicts && !options.ui.showVerdictsInsideProgressBar) {
480                ui.initVerdict(options, $el);
481            }
482        }
483        if (options.ui.showProgressBar) {
484            ui.initProgressBar(options, $el);
485        }
486        if (options.ui.showScore) {
487            ui.initScore(options, $el);
488        }
489    };
490
491    ui.updateProgressBar = function (options, $el, cssClass, percentage) {
492        var $progressbar = ui.getUIElements(options, $el).$progressbar,
493            $bar = $progressbar.find(".progress-bar"),
494            cssPrefix = "progress-";
495
496        if (options.ui.bootstrap2) {
497            $bar = $progressbar.find(".bar");
498            cssPrefix = "";
499        }
500
501        $.each(options.ui.colorClasses, function (idx, value) {
502            if (options.ui.bootstrap4) {
503                $bar.removeClass("bg-" + value);
504            } else {
505                $bar.removeClass(cssPrefix + "bar-" + value);
506            }
507        });
508        if (options.ui.bootstrap4) {
509            $bar.addClass("bg-" + options.ui.colorClasses[cssClass]);
510        } else {
511            $bar.addClass(cssPrefix + "bar-" + options.ui.colorClasses[cssClass]);
512        }
513        $bar.css("width", percentage + '%');
514    };
515
516    ui.updateVerdict = function (options, $el, cssClass, text) {
517        var $verdict = ui.getUIElements(options, $el).$verdict;
518        $verdict.removeClass(options.ui.colorClasses.join(' '));
519        if (cssClass > -1) {
520            $verdict.addClass(options.ui.colorClasses[cssClass]);
521        }
522        $verdict.html(text);
523    };
524
525    ui.updateErrors = function (options, $el, remove) {
526        var $errors = ui.getUIElements(options, $el).$errors,
527            html = "";
528
529        if (!remove) {
530            $.each(options.instances.errors, function (idx, err) {
531                html += "<li>" + err + "</li>";
532            });
533        }
534        $errors.html(html);
535    };
536
537    ui.updateScore = function (options, $el, score, remove) {
538        var $score = ui.getUIElements(options, $el).$score,
539            html = "";
540
541        if (!remove) { html = score.toFixed(2); }
542        $score.html(html);
543    };
544
545    ui.updatePopover = function (options, $el, verdictText, remove) {
546        var popover = $el.data("bs.popover"),
547            html = "",
548            hide = true;
549
550        if (options.ui.showVerdicts &&
551                !options.ui.showVerdictsInsideProgressBar &&
552                verdictText.length > 0) {
553            html = "<h5><span class='password-verdict'>" + verdictText +
554                "</span></h5>";
555            hide = false;
556        }
557        if (options.ui.showErrors) {
558            if (options.instances.errors.length > 0) {
559                hide = false;
560            }
561            html += options.ui.popoverError(options);
562        }
563
564        if (hide || remove) {
565            $el.popover("hide");
566            return;
567        }
568
569        if (options.ui.bootstrap2) { popover = $el.data("popover"); }
570
571        if (popover.$arrow && popover.$arrow.parents("body").length > 0) {
572            $el.find("+ .popover .popover-content").html(html);
573        } else {
574            // It's hidden
575            popover.options.content = html;
576            $el.popover("show");
577        }
578    };
579
580    ui.updateFieldStatus = function (options, $el, cssClass, remove) {
581        var targetClass = options.ui.bootstrap2 ? ".control-group" : ".form-group",
582            $container = $el.parents(targetClass).first();
583
584        $.each(statusClasses, function (idx, css) {
585            if (!options.ui.bootstrap2) { css = "has-" + css; }
586            $container.removeClass(css);
587        });
588
589        if (remove) { return; }
590
591        cssClass = statusClasses[Math.floor(cssClass / 2)];
592        if (!options.ui.bootstrap2) { cssClass = "has-" + cssClass; }
593        $container.addClass(cssClass);
594    };
595
596    ui.percentage = function (options, score, maximun) {
597        var result = Math.floor(100 * score / maximun),
598            min = options.ui.progressBarMinPercentage;
599
600        result = result <= min ? min : result;
601        result = result > 100 ? 100 : result;
602        return result;
603    };
604
605    ui.getVerdictAndCssClass = function (options, score) {
606        var level, verdict;
607
608        if (score === undefined) { return ['', 0]; }
609
610        if (score <= options.ui.scores[0]) {
611            level = 0;
612        } else if (score < options.ui.scores[1]) {
613            level = 1;
614        } else if (score < options.ui.scores[2]) {
615            level = 2;
616        } else if (score < options.ui.scores[3]) {
617            level = 3;
618        } else if (score < options.ui.scores[4]) {
619            level = 4;
620        } else {
621            level = 5;
622        }
623
624        verdict = verdictKeys[level];
625
626        return [options.i18n.t(verdict), level];
627    };
628
629    ui.updateUI = function (options, $el, score) {
630        var cssClass, barPercentage, verdictText, verdictCssClass;
631
632        cssClass = ui.getVerdictAndCssClass(options, score);
633        verdictText = score === 0 ? '' : cssClass[0];
634        cssClass = cssClass[1];
635        verdictCssClass = options.ui.useVerdictCssClass ? cssClass : -1;
636
637        if (options.ui.showProgressBar) {
638            if (score === undefined) {
639                barPercentage = options.ui.progressBarEmptyPercentage;
640            } else {
641                barPercentage = ui.percentage(options, score, options.ui.scores[4]);
642            }
643            ui.updateProgressBar(options, $el, cssClass, barPercentage);
644            if (options.ui.showVerdictsInsideProgressBar) {
645                ui.updateVerdict(options, $el, verdictCssClass, verdictText);
646            }
647        }
648
649        if (options.ui.showStatus) {
650            ui.updateFieldStatus(options, $el, cssClass, score === undefined);
651        }
652
653        if (options.ui.showPopover) {
654            ui.updatePopover(options, $el, verdictText, score === undefined);
655        } else {
656            if (options.ui.showVerdicts && !options.ui.showVerdictsInsideProgressBar) {
657                ui.updateVerdict(options, $el, verdictCssClass, verdictText);
658            }
659            if (options.ui.showErrors) {
660                ui.updateErrors(options, $el, score === undefined);
661            }
662        }
663
664        if (options.ui.showScore) {
665            ui.updateScore(options, $el, score, score === undefined);
666        }
667    };
668}(jQuery, ui));
669
670// Source: src/methods.js
671
672
673
674
675var methods = {};
676
677(function ($, methods) {
678    "use strict";
679    var onKeyUp, onPaste, applyToAll;
680
681    onKeyUp = function (event) {
682        var $el = $(event.target),
683            options = $el.data("pwstrength-bootstrap"),
684            word = $el.val(),
685            userInputs,
686            verdictText,
687            verdictLevel,
688            score;
689
690        if (options === undefined) { return; }
691
692        options.instances.errors = [];
693        if (word.length === 0) {
694            score = undefined;
695        } else {
696            if (options.common.zxcvbn) {
697                userInputs = [];
698                $.each(options.common.userInputs.concat([options.common.usernameField]), function (idx, selector) {
699                    var value = $(selector).val();
700                    if (value) { userInputs.push(value); }
701                });
702                userInputs = userInputs.concat(options.common.zxcvbnTerms);
703                score = zxcvbn(word, userInputs).guesses;
704                score = Math.log(score) * Math.LOG2E;
705            } else {
706                score = rulesEngine.executeRules(options, word);
707            }
708        }
709        ui.updateUI(options, $el, score);
710        verdictText = ui.getVerdictAndCssClass(options, score);
711        verdictLevel = verdictText[1];
712        verdictText = verdictText[0];
713
714        if (options.common.debug) {
715            console.log(score + ' - ' + verdictText);
716        }
717
718        if ($.isFunction(options.common.onKeyUp)) {
719            options.common.onKeyUp(event, {
720                score: score,
721                verdictText: verdictText,
722                verdictLevel: verdictLevel
723            });
724        }
725    };
726
727    onPaste = function (event) {
728        // This handler is necessary because the paste event fires before the
729        // content is actually in the input, so we cannot read its value right
730        // away. Therefore, the timeouts.
731        var $el = $(event.target),
732            word = $el.val(),
733            tries = 0,
734            callback;
735
736        callback = function () {
737            var newWord = $el.val();
738
739            if (newWord !== word) {
740                onKeyUp(event);
741            } else if (tries < 3) {
742                tries += 1;
743                setTimeout(callback, 100);
744            }
745        };
746
747        setTimeout(callback, 100);
748    };
749
750    methods.init = function (settings) {
751        this.each(function (idx, el) {
752            // Make it deep extend (first param) so it extends also the
753            // rules and other inside objects
754            var clonedDefaults = $.extend(true, {}, defaultOptions),
755                localOptions = $.extend(true, clonedDefaults, settings),
756                $el = $(el);
757
758            localOptions.instances = {};
759            $el.data("pwstrength-bootstrap", localOptions);
760
761            $.each(localOptions.common.events, function (idx, eventName) {
762                var handler = eventName === "paste" ? onPaste : onKeyUp;
763                $el.on(eventName, handler);
764            });
765
766            ui.initUI(localOptions, $el);
767            $el.trigger("keyup");
768
769            if ($.isFunction(localOptions.common.onLoad)) {
770                localOptions.common.onLoad();
771            }
772        });
773
774        return this;
775    };
776
777    methods.destroy = function () {
778        this.each(function (idx, el) {
779            var $el = $(el),
780                options = $el.data("pwstrength-bootstrap"),
781                elements = ui.getUIElements(options, $el);
782            elements.$progressbar.remove();
783            elements.$verdict.remove();
784            elements.$errors.remove();
785            $el.removeData("pwstrength-bootstrap");
786        });
787    };
788
789    methods.forceUpdate = function () {
790        this.each(function (idx, el) {
791            var event = { target: el };
792            onKeyUp(event);
793        });
794    };
795
796    methods.addRule = function (name, method, score, active) {
797        this.each(function (idx, el) {
798            var options = $(el).data("pwstrength-bootstrap");
799
800            options.rules.activated[name] = active;
801            options.rules.scores[name] = score;
802            options.rules.extra[name] = method;
803        });
804    };
805
806    applyToAll = function (rule, prop, value) {
807        this.each(function (idx, el) {
808            $(el).data("pwstrength-bootstrap").rules[prop][rule] = value;
809        });
810    };
811
812    methods.changeScore = function (rule, score) {
813        applyToAll.call(this, rule, "scores", score);
814    };
815
816    methods.ruleActive = function (rule, active) {
817        applyToAll.call(this, rule, "activated", active);
818    };
819
820    methods.ruleIsMet = function (rule) {
821        if ($.isFunction(rulesEngine.validation[rule])) {
822            if (rule === "wordLength") {
823                rule = "wordLengthStaticScore";
824            }
825
826            var rulesMetCnt = 0;
827
828            this.each(function (idx, el) {
829                var options = $(el).data("pwstrength-bootstrap");
830
831                rulesMetCnt += rulesEngine.validation[rule](options, $(el).val(), 1);
832            });
833
834            return (rulesMetCnt === this.length);
835        }
836
837        $.error("Rule " + rule + " does not exist on jQuery.pwstrength-bootstrap.validation");
838    };
839
840    $.fn.pwstrength = function (method) {
841        var result;
842
843        if (methods[method]) {
844            result = methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
845        } else if (typeof method === "object" || !method) {
846            result = methods.init.apply(this, arguments);
847        } else {
848            $.error("Method " +  method + " does not exist on jQuery.pwstrength-bootstrap");
849        }
850
851        return result;
852    };
853}(jQuery, methods));
854}(jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.