Jquery: как переделать скрипт?

248
08 марта 2017, 19:52

Есть скрипт, который вызывается при клике по блоку и любым его дочерним элементам:

$('.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>

А нужно, чтобы он срабатывал только по клику на button.

Казалось бы, всё просто - вешаю клик не на .entry__item, а на .entry__btn и вместо this пишу $('.entry__item'). Но почему-то так не работает. Подскажите, как переписать правильно?

Answer 1

A зачем вы мешаете jquery и javascript? Чтото одно уже б использовали.

$('.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>

Answer 2

Проблема в том что вы пытались обратиться к методу classList с jQuery объекта, а у него этого метода нет, есть более простой вариант на jQuery в 1 строку:

$('.entry__btn').click(function() {
    $(this).closest('.entry__item').toggleClass('js--entry-selected')
});
Answer 3

нужно, чтобы он срабатывал только по клику на button.

Значит и нужно навешивать обработчик события клика на button.
Причём есть 2 принципиально разных способа сделать это:

1) Непосредственный обработчик на кнопке

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

2) Делегированный обработчик $.on(..., selector, ...)
В этом случае мы устанавливаем обработчик события на родителя, но он делегирует обработку потомку, в случае, если инициатором был потомок.

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

Плюс второго подхода в том, что у нас всего один обработчик на все целевые элементы. К тому же, если подходящий элемент будет создан позже динамически - событие будет обработано и на нём.

Манипуляции с родителем

Можно получить ближайшего родителя в иерархии, соответсвующего некоторому селектору c помощью метода $.closest.

$(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>

Answer 4

Во-первых, вы используете избыточную конструкцию — вместо проверки на наличие класса и его дальнейшего добавления-удаления можно просто использовать 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>

Во-вторых, обратите внимание на разницу между $(this) и this, $('.first') и document.querySelector('.first'). В зависимости от того, над чем вы будете производить манипуляции — jquery-объектом или экземпляром Element — зависит то, как именно придется переключать класс родителя.

!$(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>

READ ALSO
Как получить массив цветов

Как получить массив цветов

Привет, мне нужна функция, в которую мы передаем цвет и получаем массив, этого же цвета, но допустим каждый элемент массива чуть чуть светлее

294
Как достучаться до сервера?

Как достучаться до сервера?

Познакомился с нодой совсем недавно и после php всё кругом идет, так что не ругайте

316
(CSS) user-modify. Редактирование по нажатию на кнопку

(CSS) user-modify. Редактирование по нажатию на кнопку

В шаблоне используется свойство user-modify для всех тегов span

280
Дубли транзакций в Google Tag Manager

Дубли транзакций в Google Tag Manager

Есть магазин, сделан Data Layer на странице успешной покупки, при обновлении страницы он уже не выводится (хранится один раз в сессии)Стали появляться...

262