Datsik
Datsik

Reputation: 14824

How come I cannot call Array.prototype.map on an empty array?

I am trying to just make a little validator for form inputs (mainly for practice and trying different things)

I have the code:

var Validator = function() {
    this.elements = {};
    this.alerts = [];
}

Validator.prototype = {
hookElement: function() {
var that = this;
$('#'+elementid).on('keyup', function(e) {
    if (that.elements[name].val().length > that.elements[name].options.maxLength) {
        that.alerts.map(function(x) {
            if (x.name === name && x.option === 'maxLength') {
                return true;
            } else {
                that.alerts.push({
                'alert': name + ' Cannot Be Greater Than ' + that.elements[name].options.maxLength,
                'name': name,
                'option': 'maxLength',
                'visible': true
            });
            }
        });
    } else {
       // Yet to add remover function
    }
});
}

When I press keys in the input field, the array never maps (determined with some console.log debugging) Why does it not go through it, I know it's supposed to perform a function on each element in the array but if there are no elements does it really just do nothing? How can I make this work.

The idea is so that it will not add to the array if the object already exists inside the array.

edit: Pasting full code here but I don't think it will be relevant: Sorry for the indentation, it isn't that bad on Sublime Text

var Validator = function() {
    this.elements = {};
    this.alerts = new Array();
}

Validator.prototype =  {
    hookElement: function(elementid, name, options) {
        if (options === "object" || options === undefined) {
            if (typeof options === "object" || options === undefined) {
                if (elementid != undefined || name != undefined) {
                     this.elements[name] = $('#'+elementid);
                     this.elements[name].name = name;
                     this.elements[name].options  = options || {
                                                                                        maxLength: 5,
                                                                                        smallLength: 5,
                                                                                        partner: undefined,
                                                                                        regex: undefined,
                                                                                        uppercase: undefined,
                                                                                        lowercase: undefined
                                                                                      };
                    var that = this;                                                                
                    $('#'+elementid).on('keyup', function(e) {
                        if (that.elements[name].val().length > that.elements[name].options.maxLength) {
                            that.alerts.map(function(x) {
                                if (x.name === name && x.option === 'maxLength') {
                                    return true;
                                } else {
                                    that.alerts.push({
                                    'alert': name + ' Cannot Be Greater Than ' + that.elements[name].options.maxLength,
                                    'name': name,
                                    'option': 'maxLength',
                                    'visible': true
                                });
                                }
                            });
                        } else {

                        }
                    });

                } else {
                    return console.log('Missing Arguments');
                }
            } else {
                return console.log('Options argument must be an object please visit the API page.');
            };
        };
    },

    hookForm: function(elementid, alertid, options) {
        var li = document.createElement('li');
        var ul = document.createElement('ul');
        ul.id = 'alertsList';
        if (document.getElementById(ul.id) === null) {
            document.getElementById(alertid).appendChild(ul);
        }

        var alertsExist = [];
        var that = this;
        if (elementid != undefined) {
            $('#'+elementid).on('keyup', function() {
                console.log(that.alerts);
                for (var i = 0; i < that.alerts.length; i++ ) {
                    if (alertsExist.indexOf(that.alerts[i].name + ' ' + that.alerts[i].alert) === -1) {
                        li.id = that.alerts[i].name + that.alerts[i].option;
                        li.innerHTML = that.alerts[i].alert;
                        document.getElementById('alertsList').appendChild(li);
                        alertsExist.push(that.alerts[i].name + ' ' + that.alerts[i].alert);
                    }
                }
            });
        }
    }
}

var test = new Validator();
test.hookElement('userEmail', 'Email');
test.hookElement('userPassword', 'Password');
test.hookForm('createForm', 'alerts');

Upvotes: 4

Views: 5588

Answers (1)

Hans Roerdinkholder
Hans Roerdinkholder

Reputation: 3000

You are using the Array.prototype.map function in a way that isn't intended. The callback will only be applied on array items, so indeed it won't trigger on an empty array. Besides that, you manipulate the array you are mapping from inside your callback, which is a bad idea.

You should use Array.prototype.find (more info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) to see if the item is already in the array, and if not, do your that.alerts.push logic.

Edit: code: (untested)

$('#'+elementid).on('keyup', function(e) {
    if (that.elements[name].val().length > that.elements[name].options.maxLength) {
        if (!that.alerts.find(function (x) {
             return x.name === name && x.option === 'maxLength';
        })) {
             // Item not yet in the array, so push it
             that.alerts.push({
                 'alert': name + ' Cannot Be Greater Than ' + that.elements[name].options.maxLength,
                 'name': name,
                 'option': 'maxLength',
                 'visible': true
             });
         }
     }
 });

Upvotes: 4

Related Questions