Выбор элементов от и до jQuery

416
26 июля 2017, 22:37

В общем, есть div с произвольным количеством дочерних div-ов. Нужно реализовать выбор/мультивыбор дочерних div (на подобии выбора файлов в проводнике).

Если зажата клавиша CTRL, то добавляем div к выбранным. Если клавиша не зажата, то снимаем выбор у всех и добавляем к текущему. Если зажата клавиша SHIFT, то нужно выбрать n элементов, от и до.

Код:

   $(document).ready(function() {
      // отслеживание зажатий ctrl и shift
      var ctrl = false;
      var shift = false;
      $(window).keydown(function(e) {
        if (e.keyCode == 17) {
          ctrl = true;
          $('.key').text('Зажат "CTRL"');
        } else if (e.keyCode == 16) {
          shift = true;
          $('.key').text('Зажат "SHIFT"');
        }
      });
      $(window).keyup(function(e) {
        if (e.keyCode == 17) {
          ctrl = false;
        } else if (e.keyCode == 16) {
          shift = false;
        }
        $('.key').text('');
      });
      // выбор элементов
      $('.images').on('click', 'div', function() {
        // ctrl зажат - добавим к текущему элементу класс "active"
        if (ctrl) {
          $(this).toggleClass('active');
        }
        // Shift зажат
        else if (shift) {
          // нужно выбрать элементы от и до ( тут нужна помощь )
        }
        // ctrl и shift НЕзажаты - снимим у всех эл. класс "active" и добавим к текущему эл. класс "active"
        else {
          $('.images > div').removeClass('active');
          $(this).toggleClass('active');
        }
      });
    });

В этом примере я все реализовал, кроме выбора при зажатой клавише SHIFT. Дальше застрял...

Answer 1

Элементы выделяются и сверху и снизу, а если нет выделеных, то с первого элемента:

$(document).ready(function() { 
  // отслеживание зажатий ctrl и shift 
  var ctrl = false; 
  var shift = false; 
  $(window).keydown(function(e) { 
    if (e.keyCode == 17) { 
      ctrl = true; 
      $('.key').text('Зажат "CTRL"'); 
    } else if (e.keyCode == 16) { 
      shift = true; 
      $('.key').text('Зажат "SHIFT"'); 
    } 
  }); 
  $(window).keyup(function(e) { 
    if (e.keyCode == 17) { 
      ctrl = false; 
    } else if (e.keyCode == 16) { 
      shift = false; 
    } 
    $('.key').text(''); 
  }); 
 
  // выбор элементов 
  $('.images').on('click', 'div', function() { 
 
    // ctrl зажат - добавим к текущему элементу класс "active" 
    if (ctrl) { 
      $(this).toggleClass('active'); 
    } 
 
    // Shift зажат 
    else if (shift) { 
 
      let images = $('.images'); 
      let fromElement = images.children().index($('.active')); 
 
      let currentElement = images.children().index($(this)) + 1; 
      fromElement = fromElement == -1 ? 0 : fromElement; 
 
      if (fromElement < currentElement) { 
       $('.active').removeClass('active'); 
        images.children().each( 
          function(index, element) { 
            if (index >= fromElement && index < currentElement) { 
              if (!$(element).hasClass('active')) 
                $(element).toggleClass('active'); 
            } 
          }); 
 
      } else { 
        images.children().each( 
          function(index, element) { 
            if (index <= fromElement && index > currentElement - 2) { 
              if (!$(element).hasClass('active')) 
                $(element).toggleClass('active'); 
            } 
          }); 
      } 
    } 
 
    // ctrl и shift НЕзажаты - снимим у всех эл. класс "active" и добавим к текущему эл. класс "active" 
    else { 
      $('.images > div').removeClass('active'); 
      $(this).toggleClass('active'); 
    } 
  }); 
 
});
.images { 
  height: 400px; 
  width: 400px; 
  border: 1px solid red; 
} 
 
.images div { 
  height: 40px; 
  width: 40px; 
  border: 1px solid blue; 
  margin: 10px; 
  float: left; 
  cursor: pointer; 
} 
 
.active { 
  background: green; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<div class="images"> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
</div> 
 
<div class="key"> 
  <div>

Answer 2

Выделение происходит как сверху вниз, так и снизу вверх. Основываясь на работу проводника, с зажатым SHIFT можно убирать выделение у уже выбранных элементах.

$(document).ready(function() { 
 
  // отслеживание зажатий ctrl и shift 
  var ctrl = false; 
  var shift = false; 
  var last = 0; 
  var current = 0; 
  $(window).keydown(function(e) { 
    if (e.keyCode == 17) { 
      ctrl = true; 
      $('.key').text('Зажат "CTRL"'); 
    } else if (e.keyCode == 16) { 
      shift = true; 
      $('.key').text('Зажат "SHIFT"'); 
    } 
  }); 
  $(window).keyup(function(e) { 
    if (e.keyCode == 17) { 
      ctrl = false; 
    } else if (e.keyCode == 16) { 
      shift = false; 
    } 
    $('.key').text(''); 
  }); 
 
 
 
 
  // выбор элементов 
  $('.images').on('click', 'div', function() { 
 
    // ctrl зажат - добавим к текущему элементу класс "active" 
    if (ctrl) { 
      $(this).toggleClass('active'); 
      last = $(this).index() + 1; 
    } 
 
    // Shift зажат 
    else if (shift) { 
      $('.images > div').removeClass('active'); 
      current = $(this).index() + 1; 
      // нужно выбрать элементы от и до ( тут нужна помощь ) 
      if (current > last) { 
        for (var i = last; i <= current; i++) { 
          $('.images > div:nth-child(' + i + ')').addClass('active'); 
        } 
      } else { 
        for (var i = last; i >= current; i--) { 
          $('.images > div:nth-child(' + i + ')').addClass('active'); 
        } 
      } 
 
    } 
 
    // ctrl и shift НЕзажаты - снимим у всех эл. класс "active" и добавим к текущему эл. класс "active" 
    else { 
      $('.images > div').removeClass('active'); 
      $(this).toggleClass('active'); 
      last = $(this).index() + 1; 
    } 
 
  }); 
 
});
.images { 
  height: 400px; 
  width: 400px; 
  border: 1px solid red; 
} 
 
.images div { 
  height: 40px; 
  width: 40px; 
  border: 1px solid blue; 
  margin: 10px; 
  float: left; 
  cursor: pointer; 
} 
 
.active { 
  background: green; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
<div class="images"> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
  <div></div> 
</div> 
 
<div class="key"></div>

READ ALSO
Не срабатывает onclick на тачскрине некоторых мобильных устройствах

Не срабатывает onclick на тачскрине некоторых мобильных устройствах

Здравствуйте, для реализации кнопки с выпадающим меню для мобильных устройств написал простую функцию:

243
С помощью ng-if вызвать функцию

С помощью ng-if вызвать функцию

Возможно ли это сделать? У меня есть такая разметка:

250
Поиск через ajax в django

Поиск через ajax в django

Причина, по которой задаю данный вопрос: Я полный ноль в javascript вообще, и jquery в частностиНо стоит задача сделать живой поиск по модели Book, выдавать...

291