Comment puis-je détecter si un sélecteur renvoie null?

271

Quelle est la meilleure façon de détecter si un sélecteur jQuery renvoie un objet vide. Si tu fais:

alert($('#notAnElement'));

vous obtenez [object Object], donc la façon dont je le fais maintenant est la suivante:

alert($('#notAnElement').get(0));

qui écrira "indéfini", et vous pouvez donc vérifier cela. Mais cela semble très mauvais. De quelle autre manière existe-t-il?

peirix
la source

Réponses:

494

Mon préféré est d'étendre jQuery avec cette petite commodité:

$.fn.exists = function () {
    return this.length !== 0;
}

Utilisé comme:

$("#notAnElement").exists();

Plus explicite que l'utilisation de la longueur.

Magnar
la source
2
Pourquoi avez-vous enveloppé «ceci» dans un $ ()? «ceci» dans ce contexte ne pointe-t-il pas réellement vers un objet jQuery?
Adham Atta
1
Je trouve que le retour thisest beaucoup plus utile que true. Voir ma réponse portant la presenceméthode de Rails .
Marc-André Lafortune
5
Si vous souhaitez conserver la capacité de chaîner, si la fonction retourne true, ou si vous souhaitez utiliser cette méthode pour l'attribuer thisà une variable, je recommanderais de changer l'instruction return en ce que CSharp a.
Hanna
1
Magnar, pouvez-vous expliquer comment fonctionne cette fonction "extension"? Je suppose que c'est un concept Javascript et non un concept strictement JQuery. J'ai étudié le prototypage mais je ne sais pas si cela s'applique ici et pourquoi la syntaxe serait "$ .fn".
KyleM
3
@Adam Oui. Mais dans ce cas, vous devez simplement supprimer le exist-check, compte tenu du fonctionnement de jQuery. Il ne fera simplement rien si aucun élément ne correspond au sélecteur.
Magnar
197
if ( $("#anid").length ) {
  alert("element(s) found")
} 
else {
  alert("nothing found")
}
duckyflip
la source
67

Le sélecteur renvoie un tableau d'objets jQuery. Si aucun élément correspondant n'est trouvé, il renvoie un tableau vide. Vous pouvez vérifier la .lengthcollection retournée par le sélecteur ou vérifier si le premier élément du tableau n'est pas défini.

Vous pouvez utiliser l' un des exemples suivants dans une instruction IF et ils produisent tous le même résultat. Vrai, si le sélecteur a trouvé un élément correspondant, faux sinon.

$('#notAnElement').length > 0
$('#notAnElement').get(0) !== undefined
$('#notAnElement')[0] !== undefined
Jose Basilio
la source
1
J'utilise à .lengthmoins que le code ne soit chaud. C'est certainement le plus clair avec intention. En outre, il .size()est obsolète et l'est depuis des années (depuis le 1.8). Je vais juste modifier votre réponse et la supprimer, n'hésitez pas à la rajouter avec une note mais elle est tellement ancienne, je pense que c'est mieux.
Evan Carroll
1
Techniquement, il renvoie un objet jQuery qui ne contient aucun noeud DOM. Dire qu'il renvoie un tableau vide n'est pas correct.
Vigrant
39

J'aime faire quelque chose comme ça:

$.fn.exists = function(){
    return this.length > 0 ? this : false;
}

Alors vous pouvez faire quelque chose comme ça:

var firstExistingElement = 
    $('#iDontExist').exists() ||      //<-returns false;
    $('#iExist').exists() ||          //<-gets assigned to the variable 
    $('#iExistAsWell').exists();      //<-never runs

firstExistingElement.doSomething();   //<-executes on #iExist

http://jsfiddle.net/vhbSG/

CSharp
la source
6
@Ehsan En fait, ce n'est pas un doublon de la réponse acceptée ... notez que la réponse acceptée ne renvoie que vrai / faux tandis que cette réponse renvoie soit l'objet d'origine ("ceci") soit faux. Cette réponse vous permet de faire des choses supplémentaires avec la valeur de retour (comme le chaînage de fonctions supplémentaires) si elle n'est pas fausse.
RSW
1
J'ai exactement le même code dans ma boîte à outils standard. Ce formulaire est équivalent à object.presence dans Rails et super utile dans la construction de substitution décrite par @CSharp.
inopinatus
C'est une bonne réponse, mais il serait utile que vous expliquiez ce qui se passe si AUCUN des éléments testés n'existe. Réponse courte: TypeError: firstExistingElement.doSomething is not a function. Vous pouvez encapsuler l'intégralité de la variable affectation / test dans un if () et ne faire quelque chose que si un élément est trouvé ....
Stephen R
9

J'aime utiliser presence, inspiré de Ruby on Rails :

$.fn.presence = function () {
    return this.length !== 0 && this;
}

Votre exemple devient:

alert($('#notAnElement').presence() || "No object found");

Je le trouve supérieur à celui proposé $.fn.existscar vous pouvez toujours utiliser des opérateurs booléens ou if, mais le résultat véridique est plus utile. Un autre exemple:

$ul = $elem.find('ul').presence() || $('<ul class="foo">').appendTo($elem)
$ul.append('...')
Marc-André Lafortune
la source
7

Ma préférence, et je n'ai aucune idée pourquoi ce n'est pas déjà dans jQuery:

$.fn.orElse = function(elseFunction) {
  if (!this.length) {
    elseFunction();
  }
};

Utilisé comme ceci:

$('#notAnElement').each(function () {
  alert("Wrong, it is an element")
}).orElse(function() {
  alert("Yup, it's not an element")
});

Ou, comme il semble dans CoffeeScript:

$('#notAnElement').each ->
  alert "Wrong, it is an element"; return
.orElse ->
  alert "Yup, it's not an element"
nilskp
la source
0

Vous voudrez peut-être faire cela tout le temps par défaut. J'ai eu du mal à encapsuler la fonction jquery ou la méthode jquery.fn.init pour le faire sans erreur, mais vous pouvez apporter une modification simple à la source jquery pour ce faire. Vous y trouverez quelques lignes environnantes que vous pouvez rechercher. Je recommande de rechercher la source jquery pourThe jQuery object is actually just the init constructor 'enhanced'

var
  version = "3.3.1",

  // Define a local copy of jQuery
  jQuery = function( selector, context ) {

    // The jQuery object is actually just the init constructor 'enhanced'
    // Need init if jQuery is called (just allow error to be thrown if not included)
    var result = new jQuery.fn.init( selector, context );
    if ( result.length === 0 ) {
      if (window.console && console.warn && context !== 'failsafe') {
        if (selector != null) {
          console.warn(
            new Error('$(\''+selector+'\') selected nothing. Do $(sel, "failsafe") to silence warning. Context:'+context)
          );
        }
      }
    }
    return result;
  },

  // Support: Android <=4.0 only
  // Make sure we trim BOM and NBSP
  rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;

jQuery.fn = jQuery.prototype = {

Enfin, vous pouvez obtenir le code source jquery non compressé ici: http://code.jquery.com/

Devin G Rhode
la source