0

I have an Asp.Net user control that I've created. For simplicity some of the html has been removed.

<asp:Panel ID="PanelInputControl" runat="server" CssClass="input-control input-period">
    <div  ID="InputWrapperMonth" runat="server" class="input-wrapper input-month">
        <asp:TextBox ID="TextBoxMonth" runat="server"
            MaxLength="2">
        </asp:TextBox>
    </div>
    <div  ID="InputWrapperYear" runat="server" class="input-wrapper input-year">
        <asp:TextBox ID="TextBoxYear" runat="server"
            MaxLength="4">
        </asp:TextBox>
    </div>
</asp:Panel>

I also have a javascript function, that adds classes based on the validity of of the data input. Again I have removed some of the surplus code.

Here's how I build $el:

var $el = $(this).closest('.form').find('input[type="text"], input[type="checkbox"], select, textarea');

Here's the javascript function I call:

function updateInputStatus($el) {

    var controls = [];

    $el.each(function () {

        $control = $(this).closest('.input-control');

        if ($.inArray($control, controls) < 0) {
            controls.push($control);
        }
    })
}

$el is one or more input controls - textbox, dropdownlist etc. In this example lets say that TextBoxMonth and TextBoxYear are our objects, $el, and the javascript function is triggered.

What I'm trying to do is build an array of unique input-control objects. In this example PanelInputControl will be found twice, however I only want it to be added to the array once.

Whats actually happening is that the code $.inArray($control, controls) < 0 always returns -1 whatever the situation (in order words its not being found in the array), and I don't understand why.

I've also tried adding this code at the end, var cleanArray = $.unique(controls);, but again the duplicates remain in the array.

I'm confused - any advice?

9
  • $(element) === $(element) is false, because those are two different objects, even though they contain the same DOM element. Consider storing actual DOM elements in controls instead of their jQuery wrappers. Commented Aug 3, 2013 at 15:01
  • 1
    I don't understand why $el would contain same elements more than once to begin with. Commented Aug 3, 2013 at 15:02
  • 2
    Instead of putting jQuery objects into the array put the bare DOM node. Commented Aug 3, 2013 at 15:08
  • 2
    Try $(element)[0] === $(element)[0], then thinc about what DCoder said, and understand why he's right Commented Aug 3, 2013 at 15:09
  • 1
    @dotnetnoob: There's a distinction between a DOM Element and a jQuery object wrapping that DOM Element. Almost all jQuery functions return jQuery wrappers instead of raw DOM Elements. It's conceptually quite similar to the Identity Map pattern problem - without Identity Map, you can fetch the same database record (DOM Element) twice and have two separate in-memory representations (jQuery wrappers) of it. Commented Aug 3, 2013 at 15:45

1 Answer 1

2

With each loop iteration you create a new jQuery object with:

$control = $(this).closest('.input-control');

And it is these jQuery objects that you .push() into your controls array. Even though some of those jQuery objects may contain references to the same DOM elements what you are comparing with $.inArray() is the the jQuery objects, which are all distinct objects and so are not duplicates.

The .closest() method itself does not return duplicates though, so you could do this:

controls = $el.closest('input-control');

Then your controls variable would be a jQuery object that just has the unique closest input-control elements of what was in $el.

If you specifically wanted to have controls be an array of jQuery objects each of which contains only one input-control element, but with no duplicates, you could do this:

controls = $.map($el.closest('input-control'), function(v,i) { return $(v); });
Sign up to request clarification or add additional context in comments.

1 Comment

Great answer - not something I would have realised in a million years

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.