Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Приём отбора элементов на основе .siblings() (https://javascript.ru/forum/events/74682-prijom-otbora-ehlementov-na-osnove-siblings.html)

kvizor34 31.07.2018 13:27

Приём отбора элементов на основе .siblings()
 
Здравствуйте уважаемые форумчане!
К примеру, есть вот такой зоопарк:
<ul>
    <li class="slonik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
    <li class="slonik"></li>
    <li class="slonik"></li>
    <li class="slonik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
</ul>

Как при клике на одного из li class="begemotik" получить всех, самых ближайших соседей? Т.е. не всех бегемотиков в списке, а только тех кто рядом с тем, на кого кликнули.

p.s. Для тех кому "пояснить задачу подробнее", "объяснить зачем это нужно" или "просто оберни бегемотов в тег" скажу лишь что текущую DOM структуру менять нельзя, и задача именно такая, и реализовать её нужно именно так.

Dilettante_Pro 31.07.2018 14:02

Цитата:

Сообщение от kvizor34
текущую DOM структуру менять нельзя

Цифры - только для наглядности, на процесс не влияют
Цитата:

Сообщение от kvizor34
Как при клике на одного из li class="begemotik" получить всех, самых ближайших соседей?

<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<script>
$('li.begemotik').click(function(){
  $('li').css( "color", "black" );
  $(this).next().css( "color", "red" );
  $(this).prev().css( "color", "red" );
});
</script>


Цитата:

Сообщение от kvizor34
пояснить задачу подробнее

Или только бегемотиков?
<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<script>
$('li.begemotik').click(function(){
  $('li').css( "color", "black" );
  $(this).next('.begemotik').css( "color", "red" );
  $(this).prev('.begemotik').css( "color", "red" );
});
</script>

kvizor34 31.07.2018 14:23

Методы next() и prev() выбирают одного следующего/предыдущего соседа, пожалуйста прочтите первый пост внимательно.
На вашем примере, должно работать так:
клик на 2 - выбираются 3 и 4
клик на 3 - выбираются 2 и 4
клик на 9 - выбирается 8

Dilettante_Pro 31.07.2018 14:23

самых ближайших соседей на основе .siblings()
<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<script>
$('li.begemotik').click(function(){
  var i=$(this).index();
  $('li').css( "color", "black" );
  $(this).siblings().eq(i - 1).css( "color", "red" );
  $(this).siblings().eq(i).css( "color", "red" );
});
</script>

Dilettante_Pro 31.07.2018 14:25

kvizor34,
Цитата:

Сообщение от kvizor34
пожалуйста прочтите условие внимательно

У вас условия очень расплывчатые.
Уточнять нельзя, но что такое самые ближайшие? Если, как работает siblings(), все дети родителя, то в чем вопрос?

kvizor34 31.07.2018 14:29

Цитата:

Сообщение от Dilettante_Pro (Сообщение 491387)
kvizor34,
У вас условия очень расплывчатые.
Уточнять нельзя, но что такое самые ближайшие? Если, как работает siblings(), все дети родителя, то в чем вопрос?

самые ближайшие - все, что идут подряд

kvizor34 31.07.2018 14:31

Цитата:

Сообщение от kvizor34 (Сообщение 491380)
Т.е. не всех бегемотиков в списке, а только тех кто рядом с тем на кого кликнули

Неужели я так сложно объяснил?

kvizor34 31.07.2018 15:07

Решено, рекурсия
 
В итоге чтобы решить задачу, я написал две рекурсивных функции, одну для поиска себеподобных после, вторую до себя.
<ul>
    <li class="slonik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
    <li class="slonik"></li>
    <li class="slonik"></li>
    <li class="slonik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
</ul>

$('.begemotik').click(function(){
  subrowsGroup = [];
  function findnext(row) {
    if(row.next().hasClass('begemotik')){
      subrowsGroup.push(row.next());
      findnext(row.next());
    }else{
      return false;
    }
  }
  function findprev(row) {
    if(row.prev().hasClass('begemotik')){
      subrowsGroup.push(row.prev());
      findprev(row.prev());
    }else{
      return false;
    }
  }
	findnext($(this));
	findprev($(this));
  console.log(subrowsGroup);
})


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

Aetae 31.07.2018 15:15

Кажется я понял (но не уверен :) ):
<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<script>
$('li').click(function(){
  $('li').css( "color", "black" );
  var $this = $(this);
  var cls = $this.attr('class');
  $this.nextUntil(':not(.' + cls + ')').css( "color", "red" );
  $this.prevUntil(':not(.' + cls + ')').css( "color", "red" );
});
</script>

Dilettante_Pro 31.07.2018 15:18

Аналогичный принцип - другая реализация
<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<script>
$('li.begemotik').click(function(){
  $('li').css( "color", "black" );
   var sb = $(this).prev('li.begemotik');
   while (sb.index() >= 0){
        sb.css( "color", "red" );
        sb = sb.prev('li.begemotik');
   }
   sb = $(this).next('li.begemotik');
   while (sb.index() >= 0){
        sb.css( "color", "red" );
        sb = sb.next('li.begemotik');
   }
});
</script>

рони 31.07.2018 15:27

kvizor34,
<!DOCTYPE HTML>

<html>

<head>
  <title>Untitled</title>
  <style type="text/css">
  li{
      width: 100px;
      height: 20px;
      border: 1px dashed Gray;
      padding: 5px;
  }
  .red{
      background-color: Red;
  }

  </style>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
   <script>
      $(function() {
    $("ul").on("click", "li", addCls);
    function addCls()
    {
       var el = $(this), cls = ":not(." + this.className +")";
       el.nextUntil(cls).add(el.prevUntil(cls)).addClass("red")
    }


     })
   </script>
</head>

<body>
<ul>
    <li class="slonik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
    <li class="slonik"></li>
    <li class="slonik"></li>
    <li class="slonik"></li>
    <li class="begemotik"></li>
    <li class="begemotik"></li>
</ul>

</body>

</html>

рони 31.07.2018 15:28

Aetae,
:)

kvizor34 31.07.2018 15:35

Цитата:

Сообщение от Aetae (Сообщение 491391)
Кажется я понял (но не уверен :) ):
<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<script>
$('li').click(function(){
  $('li').css( "color", "black" );
  var $this = $(this);
  var cls = $this.attr('class');
  $this.nextUntil(':not(.' + cls + ')').css( "color", "red" );
  $this.prevUntil(':not(.' + cls + ')').css( "color", "red" );
});
</script>

Совершенно верно! :)
я про эти методы (next/prevUntil) вообще никогда не слышал) спасибо большое! :dance:

j0hnik 31.07.2018 15:48

<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>

<script>
var li = document.querySelectorAll('li');
li.forEach(el=>el.onclick=e=>{
	var cls = el.className, th = el;
while (el = el.previousElementSibling) {
	if (el.className !== cls) break;
	else  el.style.color = 'red';
}
while (th = th.nextElementSibling) {
	if (th.className !== cls) break;
	else  th.style.color = 'red';
}
});
</script>

Белый шум 31.07.2018 16:04

<ul>
    <li class="slonik">1</li>
    <li class="begemotik">2</li>
    <li class="begemotik">3</li>
    <li class="begemotik">4</li>
    <li class="slonik">5</li>
    <li class="slonik">6</li>
    <li class="slonik">7</li>
    <li class="begemotik">8</li>
    <li class="begemotik">9</li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>
$('ul').on('click', 'li', function(){
  $this = $(this);
  var cls = $this.attr('class');
  if($this.data('select')=='yes'){
    $this.css('color','').data('select', '');
    $this.nextUntil(':not(.'+cls+')').css('color','').each(function(){$(this).data('select', '');});
    $this.prevUntil(':not(.'+cls+')').css('color','').each(function(){$(this).data('select', '');});
  } else {
    $this.data('select', 'yes');
    $this.nextUntil(':not(.'+cls+')').css('color','red').each(function(){$(this).data('select', 'yes');});
    $this.prevUntil(':not(.'+cls+')').css('color','red').each(function(){$(this).data('select', 'yes');});
  }
});
</script>

Первое нажатие выделяет, второе - снимает выделение.

Aetae 31.07.2018 17:32

Белый шум
.each(function(){$(this).data('select', 'yes');});
==
.data('select', 'yes')

JQuery всегда работает с массивами.

SuperZen 31.07.2018 20:53

<ul>
  <li class="slonik">slonik 1</li>
  <li class="begemotik">begemotik 2</li>
  <li class="begemotik">begemotik 3</li>
  <li class="begemotik">begemotik 4</li>
  <li class="slonik">slonik 5</li>
  <li class="slonik">slonik 6</li>
  <li class="slonik">slonik 7</li>
  <li class="begemotik">begemotik 8</li>
  <li class="begemotik">begemotik 9</li>
</ul>

<script type="text/javascript">
  document.querySelector('ul').addEventListener('click', this)
  handleEvent = (e) => {
    var sibling = e.target
    while (true) {
      if (!sibling.previousElementSibling || !sibling.previousElementSibling.classList.contains(e.target.className)) break
      sibling = sibling.previousElementSibling
    }
    while (sibling) {
      if (!sibling.classList.contains(e.target.className)) break
      else sibling.style.color = 'red'
      sibling = sibling.nextElementSibling
    }
  }
</script>


мои 5 копеек %)

Белый шум 01.08.2018 00:54

Цитата:

Сообщение от Aetae (Сообщение 491407)
JQuery всегда работает с массивами.

Да, перемудрил :(


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