2010-11-18 28 views
3

J'écris un script GreaseMonkey avec JQuery.
Parfois, le site que je veux modifier affiche des informations dans un TD, ainsi:Jquery: manière idiomatique de sélectionner l'élément A s'il est présent, élément B sinon?

<center><table><tr><td> 
Something interesting here.</td></tr>....</table></center> 

alors que parfois il affiche les choses dans une balise P (ou plusieurs) au sein de la même structure de table, ainsi:

<center><table><tr><td> 
<p>Other text about the same interesting thing. 
<p>and maybe some more stuff too.</td></tr>...</table></center> 

En ce moment je fais deux sélecteurs différents pour sélectionner le <p> par rapport au <td>, mais je me demande s'il y a un bon moyen de sélectionner seulement la balise P si elle est présente et la TD sinon dans un seul sélecteur Jquery, puisque ce que je veux ajouter est identique dans les deux cas.

(Si je viens ajouter à la TD quelle que soit l'emplacement de mes changements d'addition en fonction de la présence/absence de l'étiquette P, donc je vais la cohérence de placement.)

+1

Ce que vous avez posté n'est pas un balisage valide, pouvez-vous donner un exemple complet? –

+0

les éléments 'td' contiennent-ils seulement des éléments' p' ou pas d'éléments? –

+0

@Nick Craver: Il peut ne pas être valide, mais il pourrait être exactement ce qui est sur la page. Malgré les balises 'p' non fermées, l'intention est suffisamment claire. –

Répondre

1

Oui, vous pouvez le faire par l'extension jQuery.

Mettre ce en haut de votre fichier GM:

$.fn.substituteIfPresent = function (tagName) 
{ 
    return this.map (function() 
    { 
     var childArray = $(this).children (tagName); 

     if (childArray.length) 
      return childArray[0]; 
     else 
      return this; 
    }); 
} 


Ensuite, vous pouvez obtenir l'élément désiré avec:

X = $("center > table > tbody > tr > td").substituteIfPresent ('p'); 

//-- Note that X is a standard jQuery object, the following works: 
X.css ('border', '1px solid green'); 


Cette version de substituteIfPresent() ne retourne que le premier p tag, si présent.

+0

Tandis que toutes les solutions proposées utilisent essentiellement la même chose que je fais déjà avec 'if $ ('p'). length', celle-ci me donne le plus de JQuery-ish. :-) – Hellion

1

Pas possible en simple jQuery déclaration, mais vous pouvez faire quelque chose comme ceci:

var $elem = $('p').length > 0 ? $('p') : $('table'); 

$elem.append(...); 
+0

var $ elem = $ ('p'). Longueur? $ ('p'): $ ('table'); – mkoryak

0

une belle façon avec une seule opération de sélection est la suivante:

var $el = (function(){ 
    var $td = $('td'), // you probably want a more precise selector here 
     $p = $td.find('p:last'); 

    return $p.length ? $p : $td; 
})(); 

Ceci définit $el au dernier p élément s'il en existe et sinon à l'élément td. Notez que cela aura des résultats inattendus si vous avez plus d'un élément td sur votre page, vous devez donc utiliser un sélecteur plus précis que $('td').

La raison de la fonction auto-exécutable est d'éviter de polluer votre oscilloscope avec des variables supplémentaires.

1

J'utiliser .map (ou .each) pour cela:

$("center > table > tbody > tr > td").map(function() { 
    if($(this).find("p").length) { 
     $(this).find("p").css("border", "1px solid red"); 
    } else { 
     $(this).css("border", "1px solid green"); 
    } 
}); 

Démo: http://jsfiddle.net/tBWhH/3/

+1

Puisque vous ne renvoyez pas de valeur, il est probablement plus logique d'utiliser '.each()'. : 0) – user113716

+0

@patrick - bon point, mais je pense que l'effet est le même dans les deux sens. Je jouais d'abord avec le retour d'une collection - mais ensuite je me suis un peu embrouillé. – karim79

+0

Ou utilisez la valeur de retour puisque OP semble vouloir l'un ou l'autre. http://jsfiddle.net/tBWhH/4/ – user113716