Ctrl + क्लिक का उपयोग करके कई कोशिकाओं का चयन कैसे करें


16

मेरे पास संख्याओं के साथ एक तालिका है। जब मैं तालिका में एक कक्ष पर क्लिक करता हूं, तो यह सक्रिय अवस्था को जन्म देता है। मैं एक सेल का चयन करना चाहता हूं और crtl को दबाकर दूसरे सेल का चयन करना चाहता हूं, और परिणामस्वरूप सेल पहले और दूसरे के बीच सक्रिय हो जाएंगे। इसे कैसे लागू किया जाए?

codepen 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';
    }  
  }
}

इसे शिफ्ट हाइलाइटिंग की तरह काम करना चाहिए और दोनों दिशाओं में काम करना चाहिए


10
क्या यह कार्यक्षमता सामान्य रूप से शिफ्ट कुंजी के साथ नहीं है?
विमनसिर

पाश से सक्रिय, से lastclickकरने के लिए thisclickहै और यह भी के लिए जाँच ctrlक्लिक
एंटनी जैक

बहुत सी अस्पष्ट स्थितियां हैं - क्या आप किसी विशेष या श्रेणी की कोशिकाओं को फिर भी टॉगल करना चाहते हैं, क्या आप रेंज की शिफ्ट जैसी हाइलाइटिंग (/ टॉगल) बनाना चाहते हैं या एकल सेल का चयन करना चाहते हैं, आदि कई tescases आपके प्रश्न को स्पष्ट कर सकते हैं। ..
टॉम

1
@Wimanicesir Shift आमतौर पर प्रारंभ और वर्तमान के बीच की सीमा का चयन करता है, जबकि ctrl चयन में जोड़ता है
Emanuel Vintilă

1
@ EmanuelVintilă लेकिन सवाल "पहले एक और दूसरे के बीच की कोशिकाओं" के लिए पूछता है, जो वास्तव में Shift कुंजी का अपेक्षित व्यवहार है।
जॉन मोंटगोमरी

जवाबों:


11

इसे इस्तेमाल करे:

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>

codepen


6

मैंने जावास्क्रिप्ट भाग c को आपके द्वारा किए गए से बहुत भिन्न रूप से क्रमादेशित किया। मुझे उम्मीद है कि आप अभी भी इसका इस्तेमाल कर सकते हैं। लेकिन यह वही करता है जो आपने मांगा था।

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>

सौभाग्य ;)


हालांकि इसकी नहीं ओपी चाहता था लेकिन एक कोशिश के लिए अच्छा है! +1
मै'मून ओथमैन

@ Ma'mounothman ... लेकिन वह पहली और दूसरी क्लिक के बीच की सभी कोशिकाओं को चिह्नित करना चाहते हैं जब आप शिफ्ट कुंजी दबाते हैं ... और यह मेरे समाधान के साथ काम करता है। या वह क्या चाहता है ??
स्विसकोडेन

माफ करना इसका मतलब यह नहीं है, बात यह है कि आपके समाधान व्यक्तिगत चयनित कोशिकाओं को डी-सेलेक्ट किया जाएगा, लेकिन निश्चित नहीं कि यदि ठीक है, तो यह केवल एक चीज है जिसे जांचने की आवश्यकता है, इसके अलावा आपका समाधान वैसे भी काम करता है!
मैमून ओथमैन

5

का उपयोग कर previousElementSiblingऔरcompareDocumentPosition()

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


रिवर्स में काम नहीं करता है, उदाहरण के लिए 6 का चयन करें और ctrl + 2 का चयन करें
अनुराग श्रीवास्तव

@ अनुराग श्रीवास्तव ने तय किया
User863

4

आगे और पीछे की कार्यक्षमता के साथ पूर्ण समाधान:

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>


4

मैंने चयनित तत्व के संचय सूचकांक द्वारा बनाया है। यह दोनों तरीकों से काम करता है (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>


4

एक या अंतराल का चयन करें, लेकिन यदि आप Ctrl दबाते हैं और 3 बार क्लिक करते हैं तो पिछला चयन रीसेट हो जाता है और 1 आइटम से नया शुरू होता है (विस्तार के लिए इतना कठिन नहीं)।

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>


4

एक मामूली संशोधन के साथ आप इसे इस तरह कर सकते हैं:

<!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>

इस संबंध में टिप्पणी करने के बाद कि मैं पीछे की ओर काम नहीं कर रहा हूं, मैंने मूल को थोड़ा-सा फिर से जोड़ा है ताकि यह चयन की दोनों दिशाओं में काम करे। संपादित संस्करण datasetविशेषताओं का उपयोग करता है - इस मामले में पूर्णांक के रूप में सौंपा गया है। एक रिकॉर्ड प्रारंभिक सेल क्लिक पर रखा जाता है और, यदि ctrlकुंजी को दबाया जाता है , तो यह निर्धारित करने के लिए एक साधारण गणना की जाती है कि क्या उपयोगकर्ता आगे या पीछे का चयन कर रहा है - जो बदले में उपयोग किए गए लूप को प्रभावित करता है और इस प्रकार सक्रिय वर्ग के असाइनमेंट को प्रभावित करता है। चर का उपयोग करके सीएसएस के लिए एक मामूली मोड़ सिर्फ सुविधा के लिए था ...

<!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>


रिवर्स में काम नहीं करता है, उदाहरण के लिए 6 का चयन करें और ctrl + 2 का चयन करें
अनुराग श्रीवास्तव

पता नहीं था कि यह करने की जरूरत है कि
रामरादर

ठीक है, जो वैसे भी एक संपूर्ण समाधान की जरूरत है? :)
अनुराग श्रीवास्तव

1
यह आपकी चिंता क्यों करता है यह मेरे नियंत्रण से परे है कि मैं कुछ पोस्ट करने के बाद क्या होता है और पूरी तरह से अन्य उपयोगकर्ताओं के लिए चाहे वह ऊपर या नीचे जाता है ... जब तक कि आप मेरी ओर से कुछ गुड़ की पकौड़ी का सुझाव नहीं दे रहे हैं जो अलग है।
रामरेडर

3

यदि आप 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>


यह वास्तव में या तो रिवर्स में काम नहीं करता है
रामरेडर

मेरा उत्तर स्पष्ट रूप से बताता है कि
अनुराग श्रीवास्तव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.