繁体   English   中英

如何使用 ctrl + 单击选择多个单元格

[英]How to select multiple cells using ctrl + click

我有一张数字表。 当我单击表格中的单元格时,它会切换活动状态。 我想选择一个单元格并按 crtl 并选择另一个单元格,结果第一个和第二个之间的单元格将变为活动状态。 如何实施?

代码笔https://codepen.io/geeny273/pen/GRJXBQP

<div id="grid">
  <div class="cell">1</div>
  <div class="cell">2</div>
  <div class="cell">3</div>
  <div class="cell">4</div>
  <div class="cell">5</div>
  <div class="cell">6</div>
</div>
const grid = document.getElementById("grid")

grid.onclick = (event) => {
  event.stopPropagation();
  const { className } = event.target;

  if (className.includes('cell')) {
    if (className.includes('active')) {
      event.target.className = 'cell';
    } else {
      event.target.className = 'cell active';
    }  
  }
}

它应该像轮班突出显示一样工作并且双向工作

尝试这个:

 const cells = document.querySelectorAll(".cell"); let lastClicked; function handleClick(e) { // Toggle class active if (e.target.classList.contains("active")) { e.target.classList.remove("active"); } else { e.target.classList.add("active"); } // Check if CTRL key is down and if the clicked cell has aready class active let inRange = false; if (e.ctrlKey && this.classList.contains("active")) { // loop over cells cells.forEach(cell => { // check for the first and last cell clicked if (cell === this || cell === lastClicked) { // reverse inRange inRange = !inRange; } // If we are in range, add active class if (inRange) { cell.classList.add("active"); } }); } // Mark last clicked lastClicked = this; } cells.forEach(cell => cell.addEventListener("click", handleClick));
 #grid { display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(2, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; } .active { background-color: #80aaff; }
 <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div>

代码笔

我编写的Javascript部分与您编写的完全不同 我希望你仍然可以使用它。 但它完全符合您的要求。

使用Shift + Cell 您可以选择中间的所有单元格。

 var $lastSelected = [], container = $('#grid'), collection = $('.cell'); container.on('click', '.cell', function(e) { var that = $(this), $selected, direction; if (e.shiftKey){ if ($lastSelected.length > 0) { if(that[0] == $lastSelected[0]) { return false; } direction = that.nextAll('.lastSelected').length > 0 ? 'forward' : 'back'; if ('forward' == direction) { // Last selected is after the current selection $selected = that.nextUntil($lastSelected, '.cell'); } else { // Last selected is before the current selection $selected = $lastSelected.nextUntil(that, '.cell'); } collection.removeClass('selected'); $selected.addClass('selected'); $lastSelected.addClass('selected'); that.addClass('selected'); } else { $lastSelected = that; that.addClass('lastSelected'); collection.removeClass('selected'); that.addClass('selected'); } } else { $lastSelected = that; collection.removeClass('lastSelected selected'); that.addClass('lastSelected selected'); } });
 .selected {background-color: #80aaff;} #grid{ display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(2, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div>

使用previousElementSiblingcompareDocumentPosition()

const grid = document.getElementById("grid");
const cells = [...grid.querySelectorAll(".cell")];
let recentActive;

grid.onclick = event => {
  event.stopPropagation();
  const { className } = event.target;

  if (!className.includes("cell")) {
    return;
  }

  let compareMask = recentActive && recentActive.compareDocumentPosition(event.target);
  let property = compareMask == 2 ? "nextElementSibling" : "previousElementSibling";

  let state = event.target.classList.toggle("active");
  let sibiling = event.target[property];

  while (event.ctrlKey && state && !sibiling.classList.contains("active")) {
    sibiling.classList.add("active");
    sibiling = sibiling[property];
  }
  recentActive = event.target;
};

工作演示

https://codepen.io/aswinkumar863/pen/QWbVVNG

稍加修改,您可以这样做:

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title></title>
        <style>
            #grid {
              display: grid;
              grid-template-columns: repeat(3, 50px);
              grid-template-rows: repeat(2, 50px);
            }
            
            .cell {
              display: flex;
              justify-content: center;
              align-items: center;
              border: solid 1px #ccc;
            }
            
            .active {
              background-color: #80aaff;
            }
        </style>
        <script>
            document.addEventListener('DOMContentLoaded',e=>{
                const grid = document.getElementById('grid')
                const cells= grid.querySelectorAll('div');
                
                grid.addEventListener('click',function(e){
                    e.stopPropagation();
                    
                    cells.forEach( cell=>{
                        cell.classList.remove('active')
                    });
                    event.target.classList.add('active');
                    
                    if( event.ctrlKey ) {
                        Array.from(cells).some( cell=>{
                            cell.classList.add('active')
                            if( cell==event.target )return true;
                        })
                    }
                });
            });
        </script>
    </head>
    <body>
        <div id="grid">
          <div class="cell">1</div>
          <div class="cell">2</div>
          <div class="cell">3</div>
          <div class="cell">4</div>
          <div class="cell">5</div>
          <div class="cell">6</div>
        </div>
    </body>
</html>

 document.addEventListener('DOMContentLoaded',e=>{ const grid = document.getElementById('grid') const cells= grid.querySelectorAll('div'); grid.addEventListener('click',function(e){ e.stopPropagation(); cells.forEach( cell=>{ cell.classList.remove('active') }); e.target.classList.add('active'); if( e.ctrlKey ) { Array.from(cells).some( cell=>{ cell.classList.add('active') if( cell==e.target )return true; }) } }); });
 #grid { display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(2, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; } .active { background-color: #80aaff; }
 <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div>

根据关于这不向后工作的评论,我稍微重新散列了原始内容,以便它在选择的两个方向上都有效。 编辑后的版本使用dataset属性 - 在这种情况下分配为整数。 将保留初始单元格单击的记录,如果按下ctrl键,则进行简单计算以确定用户是向前选择还是向后选择 - 这反过来影响所使用的循环,从而影响活动类的分配。 使用变量对 CSS 进行小幅调整只是为了方便......

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title></title>
        <style>
            :root{
                --rows:2;
                --cols:3;
                --size:50px;
            }
            #grid {
              display:grid;
              grid-template-columns:repeat(var(--cols),var(--size));
              grid-template-rows:repeat(var(--rows),var(--size));
              width:calc(var(--size) * var(--cols));
            }
            
            .cell {
              display: flex;
              flex:1;
              justify-content: center;
              align-items: center;
              border: solid 1px #ccc;
              margin:1px;
              cursor:pointer;
            }
            
            .active {
              background-color: #80aaff;
            }
        </style>
        <script>
            document.addEventListener('DOMContentLoaded',e=>{

                let range=[];
                
                const grid  = document.getElementById('grid')
                const cells = grid.querySelectorAll('div');
                
                const getcell=function(i){
                    return grid.querySelector('[data-index="'+i+'"]');
                }
                const clickhandler=function(e){
                    e.stopPropagation();
                    range.push( e.target );
                    
                    /* clear cells of the "active" class */
                    cells.forEach( cell=>{
                        cell.classList.remove('active')
                    });
                    /* Assign the initially selected cell as "active" */
                    e.target.classList.add('active');
                    
                    
                    if( e.ctrlKey ) {
                        /* Is the user selecting forwards or backwards? */
                        if( range[0].dataset.index < e.target.dataset.index ){
                            for( let i=range[0].dataset.index; i < e.target.dataset.index; i++ )getcell(i).classList.add('active')
                        } else if( range[0].dataset.index == e.target.dataset.index ){
                            e.target.classList.add('active')
                        } else {
                            for( let i=range[0].dataset.index; i > e.target.dataset.index; i-- )getcell(i).classList.add('active')
                        }
                        
                        range=[];
                    }
                };
                
                /* assign an integer index to each cell within parent */
                cells.forEach( ( cell, index )=>{
                    cell.dataset.index = index + 1;
                });
                
                grid.addEventListener( 'click', clickhandler );
            });
        </script>
    </head>
    <body>
        <div id="grid">
          <div class="cell">1</div>
          <div class="cell">2</div>
          <div class="cell">3</div>
          <div class="cell">4</div>
          <div class="cell">5</div>
          <div class="cell">6</div>
        </div>
    </body>
</html>

 document.addEventListener('DOMContentLoaded',e=>{ let range=[]; const grid = document.getElementById('grid') const cells = grid.querySelectorAll('div'); const getcell=function(i){ return grid.querySelector('[data-index="'+i+'"]'); } const clickhandler=function(e){ e.stopPropagation(); range.push( e.target ); /* clear cells of the "active" class */ cells.forEach( cell=>{ cell.classList.remove('active') }); /* Assign the initially selected cell as "active" */ e.target.classList.add('active'); if( e.ctrlKey ) { /* Is the user selecting forwards or backwards? */ if( range[0].dataset.index < e.target.dataset.index ){ for( let i=range[0].dataset.index; i < e.target.dataset.index; i++ )getcell(i).classList.add('active') } else if( range[0].dataset.index == e.target.dataset.index ){ e.target.classList.add('active') } else { for( let i=range[0].dataset.index; i > e.target.dataset.index; i-- )getcell(i).classList.add('active') } range=[]; } }; /* assign an integer index to each cell within parent */ cells.forEach( ( cell, index )=>{ cell.dataset.index = index + 1; }); grid.addEventListener( 'click', clickhandler ); });
 :root{ --rows:2; --cols:3; --size:50px; } #grid { display:grid; grid-template-columns:repeat(var(--cols),var(--size)); grid-template-rows:repeat(var(--rows),var(--size)); width:calc(var(--size) * var(--cols)); } .cell { display: flex; flex:1; justify-content: center; align-items: center; border: solid 1px #ccc; margin:1px; cursor:pointer; } .active { background-color: #80aaff; }
 <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div>

我通过存储所选元素的索引来创建。 它以两种方式工作 (2 -> 6) 和 (6 -> 2)

 const grid = document.getElementById("grid") var cells = [] function activate_cell(min, max) { for (var i = 0; i < grid.children.length; i++) { // Clear all selection var el = Array.from(grid.children)[i] el.classList.remove("active"); } for (var i = min; i <= max; i++) { var el = Array.from(grid.children)[i] el.classList.toggle("active"); } } grid.onclick = (event) => { event.stopPropagation(); const { className } = event.target; const index = Array.from(grid.children).indexOf(event.target) cells.push(index) if (event.ctrlKey) { activate_cell(Math.min(...cells), Math.max(...cells)) } else { cells.length = 0 // Empty selection if ctrl is not pressed cells.push(index) activate_cell(Math.min(...cells), Math.max(...cells)) } }
 #grid { display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(2, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; } .active { background-color: #80aaff; }
 <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div>

具有向前和向后功能的完整解决方案:

 const grid = document.getElementById("grid"); var lastactive = ""; grid.onclick = (event) => { event.stopPropagation(); const { className } = event.target; if (className.includes('cell')) { if (className.includes('active')) { event.target.className = 'cell'; if(lastactive != "" && event.target === lastactive) { lastactive = ""; let cells = document.querySelectorAll('.cell'); for(let i = 0; i < cells.length; i++) { if(cells[i].className.includes('active')) { lastactive = cells[i]; break; } } } } else { event.target.className = 'cell active'; if(event.ctrlKey && lastactive != "") { let current = event.target; if(event.target.compareDocumentPosition(lastactive) == 4 /*event target is before or after last active?*/) { while(current != lastactive) { current.className = 'cell active'; current = current.nextElementSibling; } } else { while(current != lastactive) { current.className = 'cell active'; current = current.previousElementSibling; } } } lastactive = event.target; } } console.log(lastactive); }
 #grid { display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(3, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; cursor: pointer; user-select: none; } .active { background-color: #80aaff; }
 <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> <div class="cell">7</div> <div class="cell">8</div> <div class="cell">9</div> </div>

选择一个或间隔,但如果您按Ctrl并单击第 3 次,则先前的选择将被重置并且新的从第一个项目开始(不那么难扩展)。

 const grid = document.getElementById("grid") var previousCell = []; function toggle(event) { event.stopPropagation(); var target = event.target; if (target.className.indexOf('cell') > -1) { var cells = target.parentElement.getElementsByClassName("cell"); if (event.ctrlKey || previousCell[0] == previousCell[1]) { if (!event.ctrlKey) previousCell = []; previousCell.push(target); prepareRange(cells, previousCell); switchRange(cells, previousCell); previousCell = [target]; prepareRange(cells, previousCell); } document.getElementById("range").innerText = previousCell[0]+1; } } function prepareRange(cells, previousCells) { for(var i=0;i<cells.length;i++) { var pos = previousCell.indexOf(cells[i]); if (pos > -1 && previousCell.length < 4) { previousCell.push(i); } } if (previousCell.length == 2) { previousCell[0] = previousCell[1]; } else { previousCell[1] = previousCell.pop(); previousCell.pop(); previousCell.sort(); } } function switchRange(cells, previousCells) { for(var i = previousCells[0];i <= previousCells[1]; i++) { target = cells[i]; if (target.className.indexOf('active') > -1) { target.className = 'cell'; } else { target.className = 'cell active'; } if (previousCell.length == 1) break; } }
 #grid { display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(2, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; } .active { background-color: #80aaff; }
 <div id="grid" onclick="toggle(event)"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div> Last cell:<div id="range"></div>

如果您对 jquery 持开放态度,这里有一个解决方案。 请注意,它在反向选择中不起作用

 $(() => { $(".cell").on("click", function(e) { $(this).toggleClass("active") if (e.ctrlKey) { $(this).prevUntil(".active").addClass("active") } }) })
 #grid { display: grid; grid-template-columns: repeat(3, 50px); grid-template-rows: repeat(2, 50px); } .cell { display: flex; justify-content: center; align-items: center; border: solid 1px #ccc; } .active { background-color: #80aaff; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="grid"> <div class="cell">1</div> <div class="cell">2</div> <div class="cell">3</div> <div class="cell">4</div> <div class="cell">5</div> <div class="cell">6</div> </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM