Разделить список jQuery на две части в алфавитном порядке по классам - PullRequest
2 голосов
/ 11 июня 2019

Я бы хотел, чтобы элементы списка с классом 'active' располагались в алфавитном порядке вверху списка, а остальная часть списка внизу заказывалась отдельно. Другими словами,

<li><label><span>zz</span></label></li>
<li class='active'><label><span>rr</span></label></li>
<li class='active'><label><span>bb</span></label></li>
<li><label><span>hh</span></label></li>
<li><label><span>ii</span></label></li>
<li class='active'><label><span>yy</span></label></li>
<li><label><span>kk</span></label></li>
<li><label><span>mm</span></label></li>

результаты в ..

bb
rr
yy
hh
ii
kk
mm
zz

Я думаю, что у меня правильный подход, но я не могу заставить это работать. Я думаю, что-то связанное с дополнением. Может ли кто-нибудь помочь мне преодолеть последнее препятствие? https://jsfiddle.net/Lcz47b9y/

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul id="rootUl">
    <li><label><span>zz</span></label></li>
    <li class='active'><label><span>rr</span></label></li>
    <li class='active'><label><span>bb</span></label></li>
    <li><label><span>hh</span></label></li>
    <li><label><span>ii</span></label></li>
    <li class='active'><label><span>yy</span></label></li>
    <li><label><span>kk</span></label></li>
    <li><label><span>mm</span></label></li>
</ul>

.

var myli = $('#rootUl li.active label').children('span').detach().sort(sortByText);

$('#rootUl').append($(myli))

function sortByText(a, b) {
    var first = $.trim($(a).text());
    var second = $.trim($(b).text());
    return first.localeCompare(second);
}

Ответы [ 2 ]

1 голос
/ 11 июня 2019

Для этого вы можете изменить логику sort(), чтобы сначала сравнивать классы элементов, а затем, если они совпадают, сравнивать их по тексту. Попробуйте это:

$('#rootUl li').sort(function(a, b) {
  var $a = $(a), $b = $(b);
  if ($a.hasClass('active') && !$b.hasClass('active')) {
    return -1;
  } else if (!$a.hasClass('active') && $b.hasClass('active')) {
    return 1;
  }
  
  return $a.text().toUpperCase().localeCompare($b.text().toUpperCase());
}).appendTo('#rootUl');
.active { color: #C00; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="rootUl">
  <li><label><span>zz</span></label></li>
  <li class='active'><label><span>rr</span></label></li>
  <li class='active'><label><span>bb</span></label></li>
  <li><label><span>hh</span></label></li>
  <li><label><span>ii</span></label></li>
  <li class='active'><label><span>yy</span></label></li>
  <li><label><span>kk</span></label></li>
  <li><label><span>mm</span></label></li>
</ul>
1 голос
/ 11 июня 2019

Отсоедините li s, а не их внутренние <span> s - затем в функции .sort получите доступ к тексту диапазона, а затем используйте prependTo для вставки вверху.

Похоже, вы хотите отсортировать и .active s, и не .active s, поэтому добавьте эту логику и в свою функцию сравнения, вычитая вызовы hasClass:

const getSpanText = elm => $(elm).find('span').text();

$('#rootUl li')
  .detach()
  .sort(sortByText)
  .prependTo('#rootUl');

function sortByText(a, b) {
  return $(b).hasClass('active') - $(a).hasClass('active')
    || getSpanText(a).localeCompare(getSpanText(b));
}
.active {
  background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul id="rootUl">
  <li><label><span>zz</span></label></li>
  <li class='active'><label><span>rr</span></label></li>
  <li class='active'><label><span>bb</span></label></li>
  <li><label><span>hh</span></label></li>
  <li><label><span>ii</span></label></li>
  <li class='active'><label><span>yy</span></label></li>
  <li><label><span>kk</span></label></li>
  <li><label><span>mm</span></label></li>
</ul>
...