How to select all "empty" elements"

Is there any way to select all the empty elements of a page?

For some reason I don't know how to explain, the code below doesn't select the inputs without text on my page:

$("input[value=''], select[value=''], textarea[value='']");

I know I can get all the input's, select's and textarea's empty with a loop, if I first get all the elements with something like $("input, select, textarea") and then check the return of the val method for each of them. However, I would like to know if there is any special selector only for empty controls, which has a better performance than brute force filtering.

Author: Garoto de Programa, 2014-02-25

6 answers

The simplest form is input:not([value]),input[value='']:

Http://jsfiddle.net/4rB65 /

<input type="text">
<input type="text" value>
<input type="text" value="">
<input type="text" value="foo">

$(function() {
    $('input:not([value]),input[value=""]').css('border', 'solid 1px red');
});
 2
Author: Ricardo Souza, 2014-02-25 19:17:45

Apparently, when using [value=""] it only observes the attribute value, not the property value. That is, the value that was in the markup, not the current value. Example:

<input type="text" />
<input type="text" value="" />

The first the selector will never catch. The second, always will (even if you edit and put a value in it).

Looking at the selectors available by jQuery, I'm afraid there aren't any that satisfy your requirement. The answer of @Gustavo Rodrigues (preserved by @bfavaretto) would therefore be one of the only workarounds available (i.e. filter results by property valuevalue).

 5
Author: mgibsonbr, 2017-04-13 12:59:43

However, I would like to know if there is any special selector just for empty controls, which has better performance than brute force filtering.

Answer: No, it does not exist.

Even your alternative using value="" is not 100% satisfactory in filtering elements with empty value.

Using the selector:

$('input[value=""]') //...

You would receive from the following elements:

<input type="text">              <!-- não retornaria (mas deveria retornar) -->
<input type="text" value>        <!-- retornaria -->
<input type="text" value="">     <!-- retornaria -->
<input type="text" value="foo">  <!-- não retornaria -->

As you may notice, the first example item, even without having the "value" attribute and being empty, is not returned as an object by the selector.

The best solution would still be to loop through all the elements you want to check using the jQuery function .val() for example to filter the empty elements.


Solution example using loop:

var s = $('input');
s.each(function(){
    var t = $(this);
    if(t.val()){
        t.addClass('exclua-me');
    }
});
var vazios = s.not('.exclua-me'); //aqui você tem os inputs vazios
EXEMPLO NO FIDDLE
 4
Author: Kazzkiq, 2014-02-25 18:58:07

There is no selector for this.

To treat everything at once, I suggest the approach @Gustavo Rodrigues had posted (but deleted):

$('input, select, textarea').filter(function () {
    return !this.value.trim();
});
 3
Author: bfavaretto, 2014-02-25 18:46:04

For what you posted to work, the values must be explicitly set to value="", and then it will be possible to select the elements input, select and textarea you want with the following expression:

$("input[value=''], select:has(option[value='']:selected), textarea:empty")

EDIT

I improved the expression to also select those that do not have the value attribute:

$("input[value=''], input:not([value]), select:has(option[value='']:selected), select:has(option:not([value]):selected), textarea:empty")

Poxa, unfortunately, it seems that these selectors can only see the original values printed in HTML, and not the values current... with the exception of the selector for select.

EDIT 2

You can, however, create your own selector, as described in the code of this SOEN answer: https://stackoverflow.com/a/15031698/195417

jQuery.extend(
  jQuery.expr[':'],
  {
    /// check that a field's value property has a particular value
    'field-value': function (el, indx, args) {
      var a, v = $(el).val();
      if ( (a = args[3]) ) {
        switch ( a.charAt(0) ) {
          /// begins with
          case '^':
            return v.substring(0,a.length-1) == a.substring(1,a.length);
          break;
          /// ends with
          case '$':
            return v.substr(v.length-a.length-1,v.length) == 
              a.substring(1,a.length);
          break;
          /// contains
          case '*': return v.indexOf(a.substring(1,a.length)) != -1; break;
          /// equals
          case '=': return v == a.substring(1,a.length); break;
          /// not equals
          case '!': return v != a.substring(1,a.length); break;
          /// equals
          default: return v == a; break;
        }
      }
      else {
        return !!v;
      }
    }
  }
);

And then use like this:

  • for values starting with "Test": $('input:field-value(^teste)');
  • for values containing "Test": $('input:field-value(*teste)');
  • for values ending with "test": $('input:field-value($teste)');
  • for values that are not equal to "test": $('input:field-value(!teste)');
  • for values that are equal to "test": $('input:field-value(=teste)');

Do not forget to give an upvote there to Soen guy if you find this a good solution... the credit is not mine. =)

 2
Author: Miguel Angelo, 2017-05-23 12:37:31

In this fiddle we count the collection of the elements that has no value but it is only possible to obtain the initial state of the fields.

Basically

$('input:not([value])') 

Takes all input that do not have the attribute value filled, and

$('input[value=""]')

Takes all elements that have the attribute value with no value or empty. the joining of the two in a form with the treatment for whether there are select and textarea empty would be:

$('form input:not([value]), input[value=""], textarea:empty, select:empty');

But only that does not resolves, because the first three selectors take the fields whose initial state is empty, that is, if the user changes or fills them, these fields will still continue to be selected by the query.

Particularly to solve the problem, I prefer to use the code of this fiddle that prevents a field that is filled from the server from being selected and at the same time, it is still limited to the input that by default comes with no value from the server.

 1
Author: Filipe, 2014-02-28 16:18:47