Comment utiliser du javascript pur pour sélectionner toutes les .dummy classes mais PAS THIS? J'ai cherché un moment mais je ne trouve pas la réponse que je veux.

Par exemple. si je clique sur le premier .dummy div, je veux sélectionner tous les .dummy div mais pas celui sur lequel j'ai cliqué.

JQuery moyen de réaliser est comme ci-dessous,

var $dummy = $('.dummy');
$dummy.on('click', function(){
    $dummy.not(this).......
});

Mais j'aimerais savoir comment y parvenir en utilisant du javascript pur

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    console.log(document.querySelectorAll('.dummy').not(this)); 
    // WRONG not working, also querySelectorAll('.dummy:not(this)'));
  });
});
<div class="dummy">One</div>
<div class="dummy">Two</div>
<div class="dummy">Three</div>
<div class="dummy">Four</div>
2
olo 16 avril 2018 à 03:32

4 réponses

Étend l'objet intégré "NodeList" comme suit:

//Extends NodeList
NodeList.prototype.not = function ( cssSelectorOrNodeOrNodeList ) {
    //Change object name(constructor.name) to "NodeList" from "Array" in console window
    let list = ( () => { class NodeList extends Array {} return new NodeList(); } )(), excludes;

    if ( typeof cssSelectorOrNodeOrNodeList === "string" ) excludes = document.querySelectorAll( cssSelectorOrNodeOrNodeList );
    else if ( cssSelectorOrNodeOrNodeList instanceof NodeList ) excludes = cssSelectorOrNodeOrNodeList;
    else if ( cssSelectorOrNodeOrNodeList instanceof Node ) excludes = [ cssSelectorOrNodeOrNodeList ];
    
    if ( excludes === undefined || !excludes.length ) return this;

    for ( const node of this ) {
        let flag = true;
        for ( const compare of excludes ) {
            if ( node === compare ) {
                flag = false;
                break;
            }
        }
        if ( flag ) list.push( node );
    }
    Object.setPrototypeOf( list, NodeList.prototype );

    return list;
};

//Object information
{
    let test = document.childNodes.not( document.body );
    console.log( test.constructor.name ); //NodeList
    console.log( test.constructor === NodeList ); //true
    console.log( test instanceof NodeList ); //true
    console.log( test instanceof Array ); //false
    console.dir( test ); //NodeList .... not Array ....;
}

//Your test code

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    console.log(document.querySelectorAll('.dummy').not(this)); 
    // WRONG not working, also querySelectorAll('.dummy:not(this)'));
  });
});
<div class="dummy">One</div>
<div class="dummy">Two</div>
<div class="dummy">Three</div>
<div class="dummy">Four</div>

Vous pouvez l'utiliser comme vous l'avez écrit.

1
Isitea 16 avril 2018 à 06:59

Chaque élément a ses frères et sœurs dans une LinkedList attachée à this.previousSibling et this.nextSibling. Bien que vous puissiez filtrer après avoir appelé à nouveau querySelectorAll, je voulais montrer une option où vous n'avez pas besoin d'appeler à nouveau les recherches. De plus, vous pouvez être sûr qu'il s'agit bien de frères et sœurs et non d'autres .dummy sur la page (vous pouvez également le faire en définissant le contexte approprié pour querySelectorAll)

/**
 * @param acc  {Array}  An array to push onto
 * @param el   {Node}   The element to cycle over
 */
function getPrevSiblings(acc, el) {
  if(el.previousSibling) {
  	// Ignores #text elements
  	if(el.previousSibling.nodeName !== "#text" ) {
    	acc.push(el.previousSibling);
    }

    return getPrevSiblings(acc, el.previousSibling)
  }
  return acc;
}

/**
 * @param acc  {Array}  An array to push onto
 * @param el   {Node}   The element to cycle over
 */
function getNextSiblings(acc, el) {
  if(el.nextSibling) {
  	// Ignores #text elements
  	if(el.previousSibling.nodeName !== "#text" ) {
    	acc.push(el.nextSibling);
    }
    return getNextSiblings(acc, el.nextSibling)
  }
  return acc;
}

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    var prev = getPrevSiblings([], this)
    var next = getNextSiblings([], this)
    var allElsForLogging = [].concat(prev, next);
    console.log(allElsForLogging); 
  });
});
<div>
  <div class="dummy">One</div>
  <div class="dummy">Two</div>
  <div class="dummy">Three</div>
  <div class="dummy">Four</div>
</div>
1
Kevin Peno 16 avril 2018 à 01:14

Vous pouvez simplement faire une boucle sur les éléments et utiliser un if

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    console.log(document.querySelectorAll('.dummy').forEach((e) => {
      if (e !== this) {
        e.style.color = 'red';
      }
    }));
  });
});
<div class="dummy">One</div>
<div class="dummy">Two</div>
<div class="dummy">Three</div>
<div class="dummy">Four</div>
0
CodingWithSpike 16 avril 2018 à 00:48

Alternativement aux réponses déjà données (qui sont tout à fait utilisables mais pas nécessairement équivalentes), si les éléments ont un autre attribut d'identification, vous pouvez l'utiliser comme ceci:

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(event){
    console.log(document.querySelectorAll('.dummy:not([myattr="' + event.target.getAttribute("myattr") + '"])'));
  });
});
<div class="dummy" myattr="1">One</div>
<div class="dummy" myattr="2">Two</div>
<div class="dummy" myattr="3">Three</div>
<div class="dummy" myattr="4">Four</div>
1
Anonymous 16 avril 2018 à 01:08