সিটিআরএল + ক্লিক ব্যবহার করে একাধিক ঘর কীভাবে নির্বাচন করবেন


16

আমার কাছে সংখ্যা সহ একটি টেবিল আছে। আমি যখন টেবিলের কোনও ঘরে ক্লিক করি তখন এটি সক্রিয় স্থানে টগল করে। আমি একটি ঘর নির্বাচন করতে এবং 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';
    }  
  }
}

এটি শিফট হাইলাইট করার মতো কাজ করা উচিত এবং উভয় দিকেই কাজ করে


10
এই কার্যকারিতাটি সাধারণত শিফট কী দিয়ে করা হয় না?
Wimanicesir

লুপ দ্বারা সক্রিয়, থেকে lastclickথেকে thisclickএবং জন্য চেক ctrlক্লিক
অ্যান্টনি জ্যাক

অনেকগুলি অস্পষ্ট শর্ত রয়েছে - আপনি কি এখনও নির্দিষ্ট বা কক্ষের পরিসর টগল করতে চান, আপনি কি একটি স্থানের মতো শিফ্টের মতো হাইলাইটিং (/ টগল) করতে চান বা একক ঘর নির্বাচন করতে চান Several বেশ কয়েকটি টেস্কসেস আপনার প্রশ্ন সাফ করতে পারে। ..
টম

1
@ উইম্যানিসির শিফট সাধারণত শুরু এবং বর্তমানের মধ্যে ব্যাপ্তি নির্বাচন করে, যখন সিটিআরএল নির্বাচনের সাথে যোগ করে
ইমানুয়েল ভিন্টিলি

1
@ ইমানুয়েলভিন্টিল - তবে প্রশ্নটি "প্রথম থেকে দ্বিতীয় মধ্যে কোষগুলির" জন্য জিজ্ঞাসা করে, যা সত্যই শিফট কী এর প্রত্যাশিত আচরণ।
জন মন্টগোমেরি

উত্তর:


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

আমি জাভাস্ক্রিপ্ট অংশ সি প্রোগ্রাম করেছিলাম আপনার চেয়ে সম্পূর্ণ আলাদা । আমি আশা করি আপনি এটি এখনও ব্যবহার করতে পারবেন। তবে এটি আপনি যা চেয়েছিলেন ঠিক তাই করে।

শিফট + সেল দিয়ে আপনি এর মধ্যে থাকা সমস্ত ঘর নির্বাচন করতে পারেন।

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
মামুন অটম্যান

@ মা'মুনোথম্যান ... তবে আপনি শিফট কী টিপলে প্রথম এবং দ্বিতীয় ক্লিকের মধ্যে থাকা সমস্ত ঘর চিহ্নিত করতে চান ... এবং এটি আমার সমাধানের সাথে এটিই কাজ করে। বা সে কি চায় ??
সুইসকোডেমেন

দুঃখিত, এটি সেভাবে বোঝানো হয়নি, জিনিসটি হ'ল আপনার সমাধানটি পৃথক কোষকে নির্বাচিত করবে কিন্তু নিশ্চিত নয় যে এটি ঠিক আছে, এটিই কেবল যাচাই করা দরকার যা আপনার সমাধান যেভাবেই কাজ করে!
মা'মুন অটম্যান

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 এবং সিটিআরএল + নির্বাচন 2 নির্বাচন করুন
অনুরাগ শ্রীবাস্তব

@ আনুরাগস্রীবাস্তব স্থির করেছেন
ব্যবহারকারী 863

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

একটি বা অন্তর নির্বাচন করুন, তবে আপনি যদি সিটিআরএল টিপুন এবং তৃতীয়বারের মতো ক্লিক করুন পূর্ববর্তী নির্বাচনটি পুনরায় সেট করা হয় এবং প্রথম আইটেম থেকে নতুন শুরু হয় (প্রসারিত করার পক্ষে তেমন কঠিন নয়)।

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 এবং সিটিআরএল + নির্বাচন 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>


এটি সত্যিই কোনও বিপরীতে কাজ করে না
রামরাইডার

আমার উত্তরটি পরিষ্কারভাবে জানিয়েছে
অনুরাগ শ্রীবাস্তব
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.