Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Смена класса (https://javascript.ru/forum/jquery/78586-smena-klassa.html)

Байт 07.10.2019 22:06

Смена класса
 
Вот такая простенькая страничка (выжимка проблемы)
Идея - по клику мышки выделять или снимать выделение
Код:

<style type="text/css">
.unsel {
 background-color: #ffffff;
 cursor: pointer;
}
.sel {
 background-color: #9999ff;
 cursor: pointer;
}
</style>

<script>

$(document).ready(function() {
 /*
 $(".It").click( function() {  // (1) Так работает
      if ($(this).is('.sel'))
        $(this).removeClass('sel').addClass('unsel');
      else
        $(this).removeClass('unsel').addClass('sel');
 });
 */
 $(".sel").click( function() {  // (2) Так валяет дурака
        alert("sel");
        $(this).removeClass('sel').addClass('unsel');
 });
 $(".unsel").click( function() {
        alert("unsel");
        $(this).removeClass('unsel').addClass('sel');
 });
});
</script>
</head>

<body>
<span class='sel It'> Солнце </span><br>
<span class='unsel It'> Луна </span><br>
<span class='unsel It'> Меркурий</span><br>

</body> </html>

В варианте (1) все прекрасно работает.
Но почему не работает в варианте (2)??? Точнее, работает - однократно.
Клик на Солнце снимает выделение. И инспектор показывает, что класс стал unsel. Но повторный клик - и элемент ведет себя как sel. Это и alert подтверждает. Аналогично ведут себя и другие элементы.
В чем может быть дело? Чего я очень глубоко не понимаю?
ЗЫ. Есть еще вариант с toggleClass. Тоже работает на ура!
Но вопрос - чего же я не понимаю? продолжает мучить...:cray:

laimas 07.10.2019 22:15

Дурака никто не валяет, ибо после удаления класса не почему уже щелкать.

Байт 07.10.2019 22:40

Не понял. Я же добавил другой класс... Был sel. Стал unsel. На него есть реакция $(".unsel").click... В инспекторе показывает...
И почти идентичный код в варианте (1) прекрасно работает!
Может быть глаз замылился? Чего-то простейшего не вижу?

laimas 07.10.2019 22:42

Цитата:

Сообщение от Байт
почему не работает в варианте (2)??? Точнее, работает - однократно.

Потому, что обработчик установлен по классу ".sel", а в нем сразу же $(this).removeClass('sel'). Вопрос - по чему щелкать дальше будем?

Байт 07.10.2019 22:49

laimas, Но я же тут же делаю addClass('unsel'). И совершенно тоже самое делаю в рабочем варианте (1)

laimas 07.10.2019 22:52

Цитата:

Сообщение от Байт
Но я же тут же делаю addClass('unsel')

И что? С таким классом следующие две кнопки, вот для них третий обработчик и определен.

PS. Если хочется "не терять или переопределять", то нужно делегировать обработку.

Байт 07.10.2019 23:05

laimas, понимаете, мне действительно очень хочется в этом деле разобраться. Чтобы не ходить по JS, как по минному полю. Хотя для конкретного проекта все более-менее сложилось, но мне же дальше надо жить... И что меня там ждет, какие засады и западни?
То есть - понять механизмы. Вот я делаю alert. Научился смотреть инспектор (пока слабо этим смотрением владею). Что еще можно предпринять? Может быть какая-то литература есть, где рассказывается не Что, а Как? Так сказать, изнутри.
В Вебе я - зеленый новичок. Но вообще-то в программировании кой-какой опыт есть :)

Байт 07.10.2019 23:10

laimas, Ничего таки не понимаю, да и башка уже не варит, но буду думать над вашими словами...:thanks:

рони 08.10.2019 00:05

Байт,
$(".sel") это элемент/ы на момент загрузки страницы, jquery не телепат, она не следит в этом случае, какие элементы ещё возникнут с этим классом sel в дальнейшем.
если вам нужно отследить клики на любых элементах с данным классом, тогда обработчик события ставят на родителя( делегирование) , пример ниже, и в родителе проверяют класс элемента который был нажат.
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
.unsel {
 background-color: #ffffff;
 cursor: pointer;
}
.sel {
 background-color: #9999ff;
 cursor: pointer;
}
</style>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
  <script>
$(function() {
   $("body").on("click", ".unsel, .sel", function() {
   $(this).toggleClass('unsel sel');
})
});
  </script>
</head>

<body>
<span class='sel It'> Солнце </span><br>
<span class='unsel It'> Луна </span><br>
<span class='unsel It'> Меркурий</span><br>


</body>
</html>

laimas 08.10.2019 00:10

Цитата:

Сообщение от Байт
Ничего таки не понимаю

А чего тут не понятного. В комнате живут один Ваня и два Пети. Звонок, пришел курьер с доставкой: Ване квас, Петям пиво, вручил и ушел. Петям приколько, Ване обидно. А давай Ваня и ты будешь Петей - решили друзья. Появится ли после этого у Вани пиво, если курьер уже ушел?

Тоже самое и с кнопками - трем кнопкам: А и две В, по их именам установили обработчик во время Т1. Получит ли после кнопка А обработчик кнопок В если сменит имя на В во время Т2?

Malleys 08.10.2019 01:05

Цитата:

Сообщение от Байт
То есть - понять механизмы.

Такие кнопки, которые хранят в себе нажатое состояние, делаются при помощи элементов <input type="checkbox"> и <label>.

Вот ваш пример в чистом виде...
<html>
<head>
	<meta charset="utf-8">
	<style></style>
</head>
<body>
	<input type="checkbox" id="sun">
	<label for="sun">Солнце</label>

	<input type="checkbox" id="moon">
	<label for="moon">Луна</label>

	<input type="checkbox" id="mercury">
	<label for="mercury">Меркурий</label>
</body>
</html>


Или даже так...
<html>
<head>
	<meta charset="utf-8">
	<style></style>
</head>
<body>
	<label class="toggler">
		<input type="checkbox" checked>
		<span>Солнце</span>
	</label>

	<label class="toggler">
		<input type="checkbox">
		<span>Луна</span>
	</label>

	<label class="toggler">
		<input type="checkbox">
		<span>Меркурий</span>
	</label>
</body>
</html>


И уже отталкиваясь от правильной разметки, выясняется, что для достижения вашего эффекта нужно всего лишь применить стили.
<html>
<head>
	<meta charset="utf-8">
	<style>
	
.toggler {
	width: max-content;
	display: block;
} 

.toggler input {
	position: absolute;
	opacity: 0;
}

.toggler input + span {
	background-color: #ffffff;
	cursor: pointer;
	padding: 0.5em;
	margin: 0.5em;
	display: block;
}

.toggler input:focus + span {
	outline: 1px dotted;
	outline: -webkit-focus-ring-color auto 1px;
}

.toggler input:checked + span {
	background-color: #9999ff;
}
	
	</style>
</head>
<body>
	<label class="toggler">
		<input type="checkbox" checked>
		<span>Солнце</span>
	</label>

	<label class="toggler">
		<input type="checkbox">
		<span>Луна</span>
	</label>

	<label class="toggler">
		<input type="checkbox">
		<span>Меркурий</span>
	</label>
</body>
</html>
Этот пример работает даже в самых старых браузерах, а самое главное то, что он является кроссплатформенным и доступным. Также имеется уже готовое API для работы с состоянием, а также эти кнопки могут быть частью чего-то большего.

Байт 08.10.2019 11:17

Цитата:

Сообщение от рони
jquery не телепат, она не следит в этом случае, какие элементы ещё возникнут с этим классом sel в дальнейшем.

Вот оно что! Привязка-то - статическая. Теперь все понятно. Просто - луч света в темном царстве.
Огромное вам спасибо!

Байт 08.10.2019 11:22

Malleys, с чекбоксами-то все понятно. Более того, у меня так и было по началу. Но не понравилось по эстетике и объему. Там же список довольно большой.


Часовой пояс GMT +3, время: 16:16.