0
votes

FYI, I already read the related thread Uncaught TypeError: Cannot read property 'toLowerCase' of undefined and tried to implement the idea. Still, I'm getting the classic

Uncaught TypeError: Cannot read property 'toLowerCase' of undefined

error and I don't know which line in my code it's coming from because the error points within jQuery. My code is

    ReadinessColorSetter = (function () {

        this.ColorToRange = {
            '#f65314': [0, 30],
            '#ffbb00': [31, 70],
            '#7cbb00': [70, 100]
        }

        this.SetReadiness = function (ipt) {
            // ipt: input element containing
            var val = $(this).val(),
                newcolor = "#FFF"; // default
            for (var hexcode in this.ColorToRange) {
                var range = this.ColorToRange[hexcode];
                if (val >= range[0] && val < range[1]) {
                    newcolor = hexcode;
                    break;
                }
            }
            $(ipt).parent().children().last().css('background-color', newcolor);
        }

        return this;
    })();

    // On page load, set the color of the readiness       
    $(function () {
        $('input[class="completeness"]').each(function (el) {
            ReadinessColorSetter.SetReadiness(this);
        });
    });

    // When the readiness value is changed, set the color of the readiness
    //$('input[class="completeness"]').change(function () {
        //ReadinessColorSetter.SetReadiness(this);
    //});
    $(document).on('change', $('input[class="completeness"]'), function (el) {
        ReadinessColorSetter.SetReadiness($(el.target));
    });

    $('#change-submitted').click(function () {
        alert('Change submitter clicked'); // TEST
    });

and as you see I've commented out what I thought was the problem and tried to implement the correct fix.

Any guidance on this issue?

2
Can you see what error in jQuery? When did the error occur?Keiran Tai
@KeiranTai occurs on pg loaduser5648283
Should this be $(ipt).val()? Check here: this.SetReadiness = function (ipt) {...var val = $(this).val(),Keiran Tai
I am unsure but I think the SetReadiness(this) should be SetReadiness($(this)); In one of my functions I have an "each" call and I always do "var obj = $(this);" and then just use "obj" instead because I kept forgetting when to use just "this" and when to use "$(this)". I believe that is what the "undefined" is referring to.Mark Manning
@KeiranTai Yep. My mistake. Let me check whether that fixes the problem ...user5648283

2 Answers

5
votes

This seems to be invalid:

 $(document).on('change', $('input[class="completeness"]'), function (el) {
 //-----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----it should be a string

As you can see you have passed a jquery object while in the description you should see that it requires a string of css selector like:

 $(document).on('change', 'input.completeness', function (el) {

and in the method:

var val = $(ipt).val(),

and the if condition should be:

if (val >= range[0] && val <= range[1]) {
    newcolor = hexcode;//--^^----------------should be less than equal instead
    break;
}
0
votes

Looking at :

 // On page load, set the color of the readiness       
$(function () {
    $('input[class="completeness"]').each(function (el) {
        ReadinessColorSetter.SetReadiness(this);
    });
});

The $.each() closure has the parameters of [index,elements], you are sending in unwrapped element to your SetReadiness function, you should instead do something like:

(function () {
    $('input[class="completeness"]').each(function (index, elem) {
        ReadinessColorSetter.SetReadiness(elem);
    });
})();

There is also another mistake in your code where you wrap elements within a jQuery element object multiple times, this results in two different types of objects being sent to your SetReadiness function which is a standard element object in one case and a jQuery element object in another case.

Normalise your function input to be either a standard element object or a jQuery element object, doing this you can eliminate cluttered code ie.

    this.SetReadiness = function (ipt) {
        // ipt: element pre wrapped inside of a jQuery object.

        var val = ipt.val(),
            newcolor = "#FFF"; // default
        for (var hexcode in this.ColorToRange) {
            var range = this.ColorToRange[hexcode];
            if (val >= range[0] && val < range[1]) {
                newcolor = hexcode;
                break;
            }
        }
        ipt.parent().children().last().css('background-color', newcolor);
    }

Leaving you with a function that takes a pure jQuery element object as a parameter or you could send in a standard element object and then wrap it within a jQuery element object within you SetReadiness function.

Hope this clears up some of the issues you are having, whenever you receive an undefined error always check whether you are wrapping a valid object in $(object).

Standardizing everything like this will clear up your error and will give you clean and readable code. I have not looked at the functionality of your code, and only focused on clearing up your undefined error.