jQuery 1.9.1 property selector
Asked Answered
N

3

16

Background

As of jQuery 1.9 the .attr(..) method no longer returns property values, instead we now have to use .prop(..). Unfortunately this also applies to attributes specified via an attributes selector i.e. $("input[value=]")

See http://jquery.com/upgrade-guide/1.9/#attr-versus-prop-

and a good SO discussion on the differences between .attr and .prop :

.prop() vs .attr()

My Situation

I'm currently using selectors like $("input[value=]") and $("select[value=]") to select input elements that have no value set. However, this no longer works with jQuery 1.9, instead I'm now doing something like this:

var hasValue = function () { return !!($(this).val().length); };
var hasNoValue = function () { return !($(this).val().length); };
$("input").filter(hasValue);
$("select").filter(hasValue);

My actual selectors are a little larger, checking multiple elements with or without values so now I'm having to split my 1 selector string into multiple selectors with .filter(..) method calls in between.

Question

Is there an equivalent to $("[value=]"), $("[value!=]"), $("[value='abc']") which uses the property instead of the attribute? And if not, is there a cleaner way than using the .filter(hasValue) and .filter(hasNoValue) methods?

Thanks

Neodymium answered 20/3, 2013 at 0:46 Comment(7)
Looks pretty clean to me - and probably better than your previous solution (as your previous solution would only be working from the value set when the DOM was initialized, and your current solution takes into account whether or not there has been user input)Monteiro
Shouldn't it be [value] instead of [value=]? Or do both work?Georginageorgine
Works just fine for me -> FIDDLE, and it should be [value=""] as just [value] would select any element with a value attribute.Glutamate
$('input, select, textearea').filter(function(){ return !!this.value; })Oidea
@Glutamate The point is to use the currently entered value. Your fiddle works with the initial values only.Mesdames
@HaralanDobrev - okay, guess I misunderstood then, as the "attributes starts with" selector never worked with anything other than the initial value as far as I know, so nothing has changed for years regarding that ?Glutamate
@Glutamate From the upgrade guide: "As of jQuery 1.9, this behaves correctly and consistently.". It sounds like it didn't behave like that until 1.9.Mesdames
V
12

Using .filter seems to be the only way, but it's not too bad and you can actually make it a little more accurate by using .val:

$(":input").filter(function () { return $(this).val() === ""; });

If this really is that reprehensible to you, you could create a custom selector.

$.expr[':'].emptyInput = function (elem) {
    return $(elem).is(":input") && $(elem).val() === "";
};

http://jsfiddle.net/ExplosionPIlls/zaZPp/

EDIT: You may also be able to get away with using this.value instead of $(elem).val().

Vitebsk answered 20/3, 2013 at 1:0 Comment(1)
Yes, the custom expression is exactly what I'm after. It's just a preference but I think a single expression like $("input:emptyInput") is a tad easier to understand for the next coder. Thanks.Neodymium
M
1

According to the upgrade guide:

However, when a selector like "input[value=abc]" is used, it should always select by the value attribute and not any change made to the property by the user, for example from them typing into a text input. As of jQuery 1.9, this behaves correctly and consistently. Earlier versions of jQuery would sometimes use the property when they should have used the attribute.

So this answers your first question - there is not a direct equivalent, the point is to use the attribute instead of the property.

Your code seems fine, but if you want to be more standardized and re-usable you could create an additional filter. Like so:

(function($) {
    $.expr[':'].hasValue = function(element) {
        var $element = $(element);
        return element.is(':input') && element.val();
    };
}(window.jQuery));

This will allow you to select stuff like that:

// Select input elements with value and select elements without value.
$('input:hasValue,select:not(:hasValue)');

And other various combinations you need.

Mesdames answered 20/3, 2013 at 1:6 Comment(1)
I read that paragraph in the upgrade guide but it frustrated me because it didn't offer an alternative for that exact situation. I was hoping for some equivalent property syntax like $("input{value=abc}"). But defining my own expression is just as good. +1 for the same answer I was after.Neodymium
S
0

I came across this and just wanted to post another solution I found that works in some situations where some of the other suggested solutions are not appropriate.

Simply add this event handler to your code

    $('input').on('keyup', function(){  
        var value = $(this).val();
        $(this).attr('value', value);
    });
Siena answered 21/11, 2013 at 0:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.