0

I am trying to create a custom javascript form validator. I am starting by creating an input validator base class, and I am extending this base class to handle more specific input types. For example, income and zipcode.

Current structure is as follows: Base Class = InputValidator, Sub Classes: Income, ZipCode

Things are working as expected when I create only one instance of Income. However, if I also create an instance of ZipCode, it appears to overwrite the base class of Income. To see this in action, I have created a JSFiddle. http://jsfiddle.net/tpdietz/wy274ymb/3/

If you type in anything other than a digit for the annual income input, you should see a warning drop down above the income input. This is what I want. However, if you uncomment line 48 in the jsfiddle, re run it, and try the same thing. You will see that typing in something incorrect for the annual income, invokes the zip code warning. As expected, typing in something other than a digit for the zip code does the same thing.

Here is how I am declaring the sub classes:

var Income = function (incomeElement, warningElement) {
    InputValidator.call(this, incomeElement, warningElement, isInteger);

    this.isValid = function() {
        return valid;
    }
}

var ZipCode = function (zipCodeElement, warningElement) {
    InputValidator.call(this, zipCodeElement, warningElement, isInteger);

    this.isValid = function() {
        return valid && ele.val().length < 6 && ele.val().length > 2;
    }
}

and here is how I declare the base class:

var InputValidator = function (element, warningElement, validatorIn) {
    this.name = name;
    ele = element;
    warning = warningElement;
    validator = validatorIn;
    valid = false;

    ele.keyup(function() {
        if(!validator($(this).val())) {
            showWarning();
            valid = false;
        } else {
            hideWarning();
            valid = true;
        }
    });

    function showWarning() {
        warning.slideDown();
    }
    function hideWarning() {
        warning.slideUp();
    }

}

Does anybody have any idea why this is happening? I thought I had a grasp on how this should work.

Thank you.

1 Answer 1

1

You need to declare all local variables with var in front of them so they are not implicit globals. When you leave off var as in this:

var InputValidator = function (element, warningElement, validatorIn) {
    this.name = name;
    ele = element;
    warning = warningElement;
    validator = validatorIn;
    valid = false;

You end up creating global variables. Thus, when you create the second instance, all your instances are sharing the same globals and they all seem to overwrite each other.

Per-instance variables should either be declared with var as local to the constructor (and thus they will be private) or they should be assigned to this.propName like you are doing with this.name.

You can change your implementation to this:

var InputValidator = function (element, warningElement, validatorIn) {
    this.name = name;
    var ele = element;
    var warning = warningElement;
    var validator = validatorIn;
    var valid = false;

    ele.keyup(function() {
        if(!validator($(this).val())) {
            showWarning();
            valid = false;
        } else {
            hideWarning();
            valid = true;
        }
    });

    function showWarning() {
        warning.slideDown();
    }
    function hideWarning() {
        warning.slideUp();
    }

}

If you want all those variables to be local to the constructor and not accessible from outside the constructor.


FYI, this is a great reason to run in Javascript's strict mode as it would flag this as an error.

var InputValidator = function (element, warningElement, validatorIn) {
    "use strict";
    this.name = name;
    ele = element;  // <== This is an error in strict mode, since ele is not declared

Note, there is no reason to take an argument from the constructor and simply assign it to a new local variable. You can just reference the named argument the same as you would a local variable.

Sign up to request clarification or add additional context in comments.

2 Comments

You are awesome. Thank you. I had no idea that would be the solution. I will accept as soon as I am allowed to (8 minutes and counting)
Thanks for the additional FYI. I feel like I just learned more about javascript in the past 5 minutes than I have in the past week.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.