There is a script that is called when a block is clicked on a block and any of its child elements:

$('.entry__item').click(function() { if(this.classList.contains('js--entry-selected')) { this.classList.remove('js--entry-selected'); } else { this.classList.add('js--entry-selected'); } }); 
  .entry__item{width:158px;padding:20px 13px 21px;margin-bottom:5px;margin-left:5px;display:inline-block;text-align:center;background:0 0;border:2px solid #a8a8a8} .entry__name{margin-bottom:5px;font-size:17px;font-weight:700;word-wrap:break-word} .entry__country{position:relative;display:block;margin-bottom:30px;font-size:14px;font-weight:300} .entry__country::after{content:"";position:absolute;bottom:-13px;left:50%;width:96px;height:1px;margin-left:-48px;display:block;background:#a8a8a8} .entry__btn, .entry__btn:focus{display:inline-block;padding:11px 20px;margin-bottom:12px;font-size:12px;font-weight:700;text-align:center;text-transform:uppercase;background:#a8a8a8;color:#fff;border-bottom:4px solid #757575;border-radius:3px; text-decoration: none;} .entry__btn:hover{background:#cc0001;border-color:#B40001; text-decoration: none; color: #fff;} .entry__btn:active{background:#B40001;border-color:#B40001; text-decoration: none; color: #fff;} .entry__info{font-size:16px;font-weight:300;color:#000;border-bottom:1px solid #000;} .js--entry-selected{background:#cc0001;color:#fff!important;border-color:#fff} .js--entry-selected .entry__country::after{background:#fff} .js--entry-selected .entry__info{color:#fff;border-color:#fff} 
 <div class="entry__item"> <span class="entry__name">НАЗВАНИЕ КОМПАНИИ</span> <span class="entry__country">Страна</span> <button class="entry__btn">Записаться на встречу</button> <a href="#id_company" role="button" data-toggle="modal" class="entry__info">Информация о компании</a> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 

And it is necessary that it worked only by clicking on the button .

It would seem, everything is simple - I hang up not on .entry__item , but on .entry__btn and instead of this I write $('.entry__item') . But for some reason this does not work. Tell me how to rewrite correctly?

  • one
    Hang an event on a button and watch .closest('.entry__item') - the closest ancestor? - vp_arth
  • @vp_arth, I had to answer - Grundy
  • @Grundy Too specific, the use of this question is highly questionable - vp_arth
  • one
    @vp_arth, why? determine when you need to hang the handler on the container, and when on the inner element, a frequent task - Grundy
  • @Grundy, persuaded) Designed an answer - vp_arth

4 answers 4

A why do you interfere with jquery and javascript ? Something already used b.

 $('.entry__btn').click(function() { let parent = $(this).closest('.entry__item'); parent.toggleClass('js--entry-selected'); }); 
 .entry__item { width: 158px; padding: 20px 13px 21px; margin-bottom: 5px; margin-left: 5px; display: inline-block; text-align: center; background: 0 0; border: 2px solid #a8a8a8 } .entry__name { margin-bottom: 5px; font-size: 17px; font-weight: 700; word-wrap: break-word } .entry__country { position: relative; display: block; margin-bottom: 30px; font-size: 14px; font-weight: 300 } .entry__country::after { content: ""; position: absolute; bottom: -13px; left: 50%; width: 96px; height: 1px; margin-left: -48px; display: block; background: #a8a8a8 } .entry__btn, .entry__btn:focus { display: inline-block; padding: 11px 20px; margin-bottom: 12px; font-size: 12px; font-weight: 700; text-align: center; text-transform: uppercase; background: #a8a8a8; color: #fff; border-bottom: 4px solid #757575; border-radius: 3px; text-decoration: none; } .entry__btn:hover { background: #cc0001; border-color: #B40001; text-decoration: none; color: #fff; } .entry__btn:active { background: #B40001; border-color: #B40001; text-decoration: none; color: #fff; } .entry__info { font-size: 16px; font-weight: 300; color: #000; border-bottom: 1px solid #000; } .js--entry-selected { background: #cc0001; color: #fff!important; border-color: #fff } .js--entry-selected .entry__country::after { background: #fff } .js--entry-selected .entry__info { color: #fff; border-color: #fff } 
 <div class="entry__item"> <span class="entry__name">НАЗВАНИЕ КОМПАНИИ</span> <span class="entry__country">Страна</span> <button class="entry__btn">Записаться на встречу</button> <a href="#id_company" role="button" data-toggle="modal" class="entry__info">Информация о компании</a> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 

    The problem is that you tried to access the classList method with a jQuery object, but it does not have this method, there is a simpler version of jQuery with 1 line:

     $('.entry__btn').click(function() { $(this).closest('.entry__item').toggleClass('js--entry-selected') }); 
    • this inside the handler is not a jQuery object, it is the home element to which the handler is attached and it has this property - Grundy

    you need it to work only by clicking on the button.

    This means you need to hang up the event handler for the click on the button .
    And there are 2 fundamentally different ways to do this:

    1) Direct handler on the button

     $('.entry__btn').click(function() { // this === button }); 

    2) Delegated handler $ .on (..., selector, ...)
    In this case, we set the event handler to the parent, but it delegates processing to the descendant, in case the initiator was a descendant.

     $('.entry__item').on('click', '.entry__btn', function() { // Здесь также this === button }); 

    Plus the second approach is that we have only one handler for all target elements. In addition, if the appropriate element is created later dynamically - the event will be processed on it.

    Parenting

    You can get the closest parent in the hierarchy that corresponds to a selector using the $ .closest method.

     $(this).closest('.entry__item').toggleClass('js--entry-selected'); 

     $('.child.ex1').click(function() { $(this).closest('.parent').toggleClass('active'); }); $('.parent.ex2').on('click', '.child', function() { $(this).closest('.parent').toggleClass('active'); }); // Добавим кнопки динамически setTimeout(function() { $('.parent.ex1').append($('<div class="child ex2">Dynamic Button</div>')) $('.parent.ex2').append($('<div class="child ex2">Dynamic Button</div>')) }, 2e3); 
     .parent {display: inline-block;width: 30vw;margin: auto;border: 1px solid silver;position: relative;text-align:center;padding: 5px;} .child {display: inline-block;border: 1px solid silver;cursor: pointer;margin: 5px;} .parent.active,.child:hover {background-color: teal} 
     <div class="parent ex1"> <div class="child ex1">Example 1</div> </div> <hr /> <div class="parent ex2"> <div class="child ex2">Example 2</div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 

      First, you use a redundant construction — instead of checking for the presence of a class and its further add-delete, you can simply use toggle .

       // это: document.querySelector('.first').onclick = function() { if (this.classList.contains('selected')) { this.classList.remove('selected'); } else { this.classList.add('selected'); } } // полностью идентично этому: document.querySelector('.second').onclick = function() { this.classList.toggle('selected'); } 
       button.selected { background-color: #000; color: #fff; } 
       <button class=first>click me</button> <button class=second>click me</button> 

      Second, notice the difference between $(this) and this , $('.first') and document.querySelector('.first') . Depending on what you will be manipulating — a jquery object or an Element instance — it depends on how you will switch the parent class.

       !$(function() { $('.first').click(function() { this.classList.toggle('selected'); // сработает, потому что мы берем экземпляр объекта Element и обращаемся к его свойству $(this).classList.toggle('selected'); // не сработает, у jquery-объекта нет свойства classList }); $('.second').click(function() { $(this).toggleClass('selected'); // сработает, поскольку вместо this используется $(this) — jquery-обертка над this и метод jquery toggleClass }); console.log( $('.first') ); // результатом будет jquery-объект со своими свойствами console.log( document.querySelector('.first') ); // результатом будет экземпляр объекта Element с базовыми свойствами и методами // собственно, переключение класса для внешнего блока $('.third').click(function() { this.closest('.outer').classList.toggle('selected'); // в формате vanilla js }); $('.fourth').click(function() { $(this).closest('.outer').toggleClass('selected'); // в формате jquery }) }); 
       button.selected { background-color: #000; color: #fff; } .outer { padding: 20px; border: 1px solid; } .outer.selected { background-color: #000; } 
       <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button class=first>click me</button> <button class=second>click me</button> <div class=outer style="margin: 2em 0 .5em"> <button class=third>click me</button> </div> <div class=outer> <button class=fourth>click me</button> </div> 

      • How does this answer relate to the question? - Grundy
      • @Grundy is a little carried away with a description of why it does not work, which he didn’t finish writing how to make it work. updated answer. - Sasha Omelchenko