HTML
<body>
<div class="lol">
<a class="rightArrow" href="javascriptVoid:(0);" title"Next image">
</div>
</body>
Pseudo code
$(".rightArrow").click(function() {
rightArrowParents = this.dom(); //.dom(); is the pseudo function ... it should show the whole
alert(rightArrowParents);
});
Le message d'alerte serait:
corps div.lol a.rightArrow
Comment puis-je obtenir cela avec javascript/jquery?
En utilisant jQuery, comme ceci (suivi d'une solution qui n'utilise pas jQuery sauf pour l'événement; beaucoup moins d'appels de fonction, si c'est important):
$(".rightArrow").click(function() {
var rightArrowParents = [];
$(this).parents().addBack().not('html').each(function() {
var entry = this.tagName.toLowerCase();
if (this.className) {
entry += "." + this.className.replace(/ /g, '.');
}
rightArrowParents.Push(entry);
});
alert(rightArrowParents.join(" "));
return false;
});
Exemple en direct:
$(".rightArrow").click(function() {
var rightArrowParents = [];
$(this).parents().addBack().not('html').each(function() {
var entry = this.tagName.toLowerCase();
if (this.className) {
entry += "." + this.className.replace(/ /g, '.');
}
rightArrowParents.Push(entry);
});
alert(rightArrowParents.join(" "));
return false;
});
<div class="lol multi">
<a href="#" class="rightArrow" title="Next image">Click here</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
(Dans les exemples en direct, j'ai mis à jour l'attribut class
sur le div
pour qu'il soit lol multi
pour illustrer la gestion de plusieurs classes.)
Cela utilise parents
pour obtenir les ancêtres de l'élément sur lequel l'utilisateur a cliqué, enlève l'élément html
de celui-ci via not
= (puisque vous avez commencé à body
), puis boucle en créant des entrées pour chaque parent et en les poussant sur un tableau. Ensuite, nous utilisons addBack
pour ajouter le a
dans l'ensemble, ce qui modifie également l'ordre de l'ensemble selon ce que vous vouliez (parents
est spécial, il vous donne les parents dans l'ordre inverse de votre choix, mais ensuite addBAck
le remet dans l'ordre DOM). Ensuite, il utilise Array#join
pour créer la chaîne délimitée par des espaces.
Lors de la création de l'entrée, s'il y a quelque chose sur className
nous remplaçons les espaces par .
pour prendre en charge les éléments qui ont plus d'une classe (<p class='foo bar'>
a className
= "foo bar"
, de sorte que l'entrée finit par être p.foo.bar
).
Juste pour être complet, c'est l'un de ces endroits où jQuery peut être excessif, vous pouvez facilement le faire simplement en remontant le DOM:
$(".rightArrow").click(function() {
var rightArrowParents = [],
Elm,
entry;
for (Elm = this; Elm; Elm = Elm.parentNode) {
entry = Elm.tagName.toLowerCase();
if (entry === "html") {
break;
}
if (Elm.className) {
entry += "." + Elm.className.replace(/ /g, '.');
}
rightArrowParents.Push(entry);
}
rightArrowParents.reverse();
alert(rightArrowParents.join(" "));
return false;
});
Exemple en direct:
$(".rightArrow").click(function() {
var rightArrowParents = [],
Elm,
entry;
for (Elm = this; Elm; Elm = Elm.parentNode) {
entry = Elm.tagName.toLowerCase();
if (entry === "html") {
break;
}
if (Elm.className) {
entry += "." + Elm.className.replace(/ /g, '.');
}
rightArrowParents.Push(entry);
}
rightArrowParents.reverse();
alert(rightArrowParents.join(" "));
return false;
});
<div class="lol multi">
<a href="#" class="rightArrow" title="Next image">Click here</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Là, nous utilisons simplement la propriété standard parentNode
de l'élément à plusieurs reprises pour remonter l'arborescence jusqu'à ce que nous manquions de parents ou que nous voyions l'élément html
. Ensuite, nous inversons notre tableau (car il est en arrière vers la sortie que vous vouliez), et le rejoignons, et nous sommes prêts à partir.
Voici une version native de JS qui renvoie un chemin jQuery. J'ajoute également des identifiants pour les éléments s'ils en ont. Cela vous donnerait la possibilité de faire le chemin le plus court si vous voyez un identifiant dans le tableau.
var path = getDomPath(element);
console.log(path.join(' > '));
Les sorties
body > section:eq(0) > div:eq(3) > section#content > section#firehose > div#firehoselist > article#firehose-46813651 > header > h2 > span#title-46813651
Voici la fonction.
function getDomPath(el) {
var stack = [];
while ( el.parentNode != null ) {
console.log(el.nodeName);
var sibCount = 0;
var sibIndex = 0;
for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
var sib = el.parentNode.childNodes[i];
if ( sib.nodeName == el.nodeName ) {
if ( sib === el ) {
sibIndex = sibCount;
}
sibCount++;
}
}
if ( el.hasAttribute('id') && el.id != '' ) {
stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
} else if ( sibCount > 1 ) {
stack.unshift(el.nodeName.toLowerCase() + ':eq(' + sibIndex + ')');
} else {
stack.unshift(el.nodeName.toLowerCase());
}
el = el.parentNode;
}
return stack.slice(1); // removes the html element
}
J'avais besoin d'une version native de JS, qui renvoie le chemin d'accès standard CSS (pas jQuery) et traite de ShadowDOM. Ce code est une mise à jour mineure de la réponse de Michael Connor, juste au cas où quelqu'un d'autre en aurait besoin:
function getDomPath(el) {
if (!el) {
return;
}
var stack = [];
var isShadow = false;
while (el.parentNode != null) {
// console.log(el.nodeName);
var sibCount = 0;
var sibIndex = 0;
// get sibling indexes
for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
var sib = el.parentNode.childNodes[i];
if ( sib.nodeName == el.nodeName ) {
if ( sib === el ) {
sibIndex = sibCount;
}
sibCount++;
}
}
// if ( el.hasAttribute('id') && el.id != '' ) { no id shortcuts, ids are not unique in shadowDom
// stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
// } else
var nodeName = el.nodeName.toLowerCase();
if (isShadow) {
nodeName += "::shadow";
isShadow = false;
}
if ( sibCount > 1 ) {
stack.unshift(nodeName + ':nth-of-type(' + (sibIndex + 1) + ')');
} else {
stack.unshift(nodeName);
}
el = el.parentNode;
if (el.nodeType === 11) { // for shadow dom, we
isShadow = true;
el = el.Host;
}
}
stack.splice(0,1); // removes the html element
return stack.join(' > ');
}
Voici une solution pour la correspondance exacte d'un élément.
Il est important de comprendre que le sélecteur ( ce n'est pas un vrai ) que les outils chrome affichent n'identifient pas de façon unique un élément dans le DOM. ( par exemple, il ne fera pas la distinction entre une liste de span
éléments. il n'y a pas d'informations de positionnement/d'indexation )
Une adaptation d'une similaire ( à propos de xpath ) réponse
$.fn.fullSelector = function () {
var path = this.parents().addBack();
var quickCss = path.get().map(function (item) {
var self = $(item),
id = item.id ? '#' + item.id : '',
clss = item.classList.length ? item.classList.toString().split(' ').map(function (c) {
return '.' + c;
}).join('') : '',
name = item.nodeName.toLowerCase(),
index = self.siblings(name).length ? ':nth-child(' + (self.index() + 1) + ')' : '';
if (name === 'html' || name === 'body') {
return name;
}
return name + index + id + clss;
}).join(' > ');
return quickCss;
};
Et tu peux l'utiliser comme ça
console.log( $('some-selector').fullSelector() );
Démo sur http://jsfiddle.net/gaby/zhnr198y/
J'ai déplacé l'extrait de T.J. Crowder à un petit plugin jQuery. J'ai utilisé la version jQuery de lui même s'il a raison de dire que c'est une surcharge totalement inutile, mais je ne l'utilise qu'à des fins de débogage, donc je m'en fiche.
Usage:
Html
<html>
<body>
<!-- Two spans, the first will be chosen -->
<div>
<span>Nested span</span>
</div>
<span>Simple span</span>
<!-- Pre element -->
<pre>Pre</pre>
</body>
</html>
Javascript
// result (array): ["body", "div.sampleClass"]
$('span').getDomPath(false)
// result (string): body > div.sampleClass
$('span').getDomPath()
// result (array): ["body", "div#test"]
$('pre').getDomPath(false)
// result (string): body > div#test
$('pre').getDomPath()
Référentiel
$(".rightArrow")
.parents()
.map(function () {
var value = this.tagName.toLowerCase();
if (this.className) {
value += '.' + this.className.replace(' ', '.', 'g');
}
return value;
})
.get().reverse().join(", ");
bonjour cette fonction résout le bogue lié à l'élément courant qui n'apparaît pas dans le chemin
vérifie ça maintenant
$j(".wrapper").click(function(event) {
selectedElement=$j(event.target);
var rightArrowParents = [];
$j(event.target).parents().not('html,body').each(function() {
var entry = this.tagName.toLowerCase();
if (this.className) {
entry += "." + this.className.replace(/ /g, '.');
}else if(this.id){
entry += "#" + this.id;
}
entry=replaceAll(entry,'..','.');
rightArrowParents.Push(entry);
});
rightArrowParents.reverse();
//if(event.target.nodeName.toLowerCase()=="a" || event.target.nodeName.toLowerCase()=="h1"){
var entry = event.target.nodeName.toLowerCase();
if (event.target.className) {
entry += "." + event.target.className.replace(/ /g, '.');
}else if(event.target.id){
entry += "#" + event.target.id;
}
rightArrowParents.Push(entry);
// }
où $j
= variable jQuery
résolvez également le problème avec .. dans le nom de la classe
voici la fonction de remplacement:
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Merci
var obj = $('#show-editor-button'),
path = '';
while (typeof obj.prop('tagName') != "undefined"){
if (obj.attr('class')){
path = '.'+obj.attr('class').replace(/\s/g , ".") + path;
}
if (obj.attr('id')){
path = '#'+obj.attr('id') + path;
}
path = ' ' +obj.prop('tagName').toLowerCase() + path;
obj = obj.parent();
}
console.log(path);