Katia
Katia

Reputation: 729

Dynamically check for SELECT duplicate value

the goal I'm aiming for is to check all the SELECT element for duplicated values (can't select the same value in 2 SELECTs)
I've done lots of searching but all of it 2 SELECTs not fixable for more

the logic I tried:

check function(){
declare values array, errorElement array
foreach(select element){ if the selected value exist in the value array(duplicate), add the element to the error element array
else add the value to the value array
}
if no error elements (no duplicated values), remove the error class from all selects
else foreach(select elemnt){
if the select exists in the error element array, set error class
else remove error class
}
}

on any select change, call check function

and here the demo

function checkSelects() 
{ 
    var errorElements = []; var values = [];

    $("select").each(function () {
        if ($.inArray($(this).val(), values) !== -1) {
            errorElements.push($(this).attr('id'));
        } else {
            values.push($(this).val());
        }
    });
    if (errorElements.length === 0) {
        $("select").each(function () {
            $(this).removeClass('error');
        });
    } else {
        $("select").each(function () {
            if ($.inArray($(this).attr('id'), errorElements) !== -1) {
                $(this).addClass('error');
            } else {
                $(this).removeClass('error');
            }
        });
    }
}

$(function () {
     $("select").change(function () {
        checkSelects();
     }); 
});

as for functionality it works perfect, setting the error class for one side of the duplicate conflict. but I'd like to make it even more clear and set the error class for both sides

is that going over-board? any pointer how to achieve that?
here's a screen-cap of it
enter image description here

selecting text1 in 2 SELECTs only sets the error class for the later element.
I'd like for both text1s to be shown in red

Upvotes: 1

Views: 3056

Answers (2)

Ja͢ck
Ja͢ck

Reputation: 173622

Simply filter all select boxes with the same value and mark all of them at once.

I've also simplified the code a fair bit by clearing all errors when the check starts.

function checkSelects() 
{
    var $elements = $('select');

    $elements
        .removeClass('error')
        .each(function () {
            var selectedValue = this.value;

            $elements
                .not(this)
                .filter(function() {
                    return this.value == selectedValue;
                })
                .addClass('error');
        });
}

Demo

Upvotes: 3

Anoop Joshi P
Anoop Joshi P

Reputation: 25537

Use like this

function checkSelects() {
    var errorElements = [];
    var values = [];

    $("select").each(function () {
        if ($.inArray($(this).val(), values) !== -1) {
            errorElements.push($(this).attr('id'));
        } else {
            values.push($(this).val());
        }
    });
    if (errorElements.length === 0) {
        $("select").each(function () {
            $(this).removeClass('error');
        });
    } else {
        $("select").each(function () {
            if ($.inArray($(this).attr('id'), errorElements) !== -1) {
                $(this).addClass('error');
                $("select[value="+$(this).val()+"]").addClass('error'); <---- here
            } else {
                $(this).removeClass('error');
            }
        });
    }

}

Fiddle

Eidt

I've simplified your code, you can use like this way too

function checkSelects() {
    $(".error").removeClass("error");
    $("select").each(function () {
        if ($("select[value=" + $(this).val() + "]").length > 1) {
            $("select[value=" + $(this).val() + "]").addClass('error');
        }
    });
}

$(function () {
    $("select").change(function () {
        checkSelects();
    });
});

Updated Fiddle

Upvotes: 4

Related Questions