Выбор предыдущего элемента, по которому был клик

98
20 мая 2021, 09:00

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

Вопрос: Возможно ли каким-то образом определять этот предыдущий выбранный элемент списка?

function categories() { 
  var categoriesItem = $('.list li a'); 
       
  categoriesItem.on('click', function(e) { 
    e.preventDefault(); 
     
    var currentCategoriesItem = $(this); 
     
    // Определение выбранных эл-тов 
    if (currentCategoriesItem.hasClass('active')) { 
      currentCategoriesItem.removeClass('active'); 
    } else { 
      currentCategoriesItem.addClass('active'); 
    } 
  }); 
} 
 
categories();
.list li a.active { 
  color: red; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<ul class="list"> 
  <li><a href="#close">Яблоки</a></li> 
  <li><a href="#close">Бананы</a></li> 
  <li><a href="#close">Груши</a></li> 
  <li><a href="#close">Апельсины</a></li> 
</ul>

Answer 1

История выбранных фильтров хранится в связанном списке объектов:

    function categories() { 
        var categoriesItem = $('.list li a'); 
        var state = {cur: [], prev: undefined}; 
        categoriesItem.on('click', function(e) { 
        e.preventDefault(); 
        if ($(this).hasClass('active')) {                             
          var e = $(this).data('c');  
          var c = state.cur.slice(); 
          if (state.cur[0] == $(this).data('c')) {      
            state = state.prev; 
            state.cur = c.filter(function (n) { 
                return state.cur.indexOf(n) !== -1 && n != e; 
            }); 
          } else { 
            var c = state.cur.filter(function (v) { 
              return v != e; 
            }); 
            state = { 
              cur : c.filter(function (v) { 
                return v != e; 
              }), 
              prev : state.prev 
            };  
          } 
          if (state.cur.length === 0) { 
            state = {cur: [], prev: undefined}; 
          } 
        } else { 
          var c = state.cur.slice(); 
          c.unshift($(this).data('c')); 
          state = {cur : c, prev : state};      
        } 
        $(".-result").remove(); 
        $('.list li a.active').removeClass('active'); 
        var result = 0; 
        $.each(state.cur, function (k, v) { 
          var e = $("a[data-c=" + v + "]"); 
          result = result + $(e).data('res'); 
          $(e).addClass('active'); 
        }); 
         if (!!state.cur[0]) $("a[data-c=" + state.cur[0] + "]").parent().append('<button class="-result">Результат: ' + result + '</button>');  
      }); 
    } 
 
    categories();
.list li a.active { 
  color: red; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
<ul class="list"> 
  <li><a href="#close" data-c="1" data-res="3">Яблоки</a></li> 
  <li><a href="#close" data-c="2" data-res="8">Бананы</a></li> 
  <li><a href="#close" data-c="3" data-res="5">Груши</a></li> 
  <li><a href="#close" data-c="4" data-res="1">Апельсины</a></li> 
</ul>

Answer 2

Может вам нужно что-то около такого?

var items = []; // Массив для хранения последовательности всего кликнутого 
 
$('.list li a').on('click', function(e) { 
  e.preventDefault(); 
     
  var bubu = $(this); 
  if( bubu.hasClass('active') ){ 
    bubu.removeClass('active'); 
     
    var length = bubu.parent().siblings().length;  
    // у вас класс, а не id, поэтому не рискнул $('.list li a').length 
    items.push( bubu.text() );  
    // Для демо в массив сохраняется текст элемента, но можно хоть весь элемент 
    // или его номер, что разумнее 
    items = items.slice( -length-1 ); //Каждый раз массив обрезается с конца. 
  } else { 
    bubu.addClass('active'); 
  } 
 
  console.clear(); console.log( items ); 
});
.list li a.active { 
  color: red; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
 
<ul class="list"> 
  <li><a href="#close">Яблоки</a></li> 
  <li><a href="#close">Бананы</a></li> 
  <li><a href="#close">Груши</a></li> 
  <li><a href="#close">Апельсины</a></li> 
</ul>

P.s. не было бы необходимости хранить кликнутое - сам класс можно было переключать

$(this).toggleClass('active');

И всё) Без всяких условий.

P.s.-2 про номер кликнутого элемента...

$('.list li a').index( $(this) ); это дело выдаст номер кликнутого this среди всех найденных list li a... ( ну или this-parent-siblings-блабла ) А потом можно достать этот же номер и получить нужный элемент по номеру, $('.list li a').eq( номер )

Answer 3

Т.к. в метках стоит jQuery, то напишу весь код на нём.

// т.к. при клике мы добавляем класс, то по классу и будет использовать все проверки. 
 
// создадим переменную с названием класса, чтобы немного упростить себе жизнь :D 
let active = 'active'; 
 
$('.list').on('click', 'li', function(){ 
  // по клику на `li` выполняем следующее: 
  // проверяем, у дочернего `a`, нажатого `li`, недолжно быть класса `active` 
  if(!$(this).find('a').hasClass(active)) { 
    // убираем класс у `li a.active` 
    $('.list').find('li a.'+active).removeClass(active); 
    // добавляем класс дочернему `a`, нажатого `li` 
    $(this).find('a').addClass(active); 
  } 
});
.list li a.active { 
  color: red; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 
 
<ul class="list"> 
  <li><a href="#close">Яблоки</a></li> 
  <li><a href="#close">Бананы</a></li> 
  <li><a href="#close">Груши</a></li> 
  <li><a href="#close">Апельсины</a></li> 
</ul>

READ ALSO
Зачем этот алгоритм и что он делает?

Зачем этот алгоритм и что он делает?

Есть кусок кода, я не понимаю, зачем он и как работаетПо идее функция getComponentTypeID() возвращает какой-то ID (зависящий от количества вызовов) на 1 больше...

117
как определить inline функцию?

как определить inline функцию?

Как определить встроилась ли функция или у нее свой адрес и реализация, как у не встраимовой функции? Компилятор может игнорировать инструкцию,...

85
Constexpr значение как non-type template parameter

Constexpr значение как non-type template parameter

Я пробовал сделать static_assert для одного конструктора сразу в std::enable_if, используя msvc

87