How to select next specific number of elements in loop by every click in pure javascript?

I'm trying to select next 3 items(nextElementSiblings) for every click on 'next' button. Items length is 14. Its working fine till item 12. After item 12 its checking for next 3 items but there were only 2 left(thirteen 13, thirteen 14) in loop. So its unable to select last 2 items. How can I change the condition here when items left less than 3 at the end of the loop. And disable the onclick function on 'next' button as it reached till end. And enable it after clicking on 'prev' button.

var next = document.getElementById("next"),
	list = document.getElementById("list");
	
var li = list.getElementsByTagName("DIV");
	
for (var i = 0; i < li.length; i++) {
	li[i].style.display = "0px solid transparent";
}

for (var i = 0; i < 3; i++) {
	li[i].style.border = "1px solid red";
}

var nextfun = (function(){
	
	var nextitems = 4;
	var prevItems = 1;
	
	return function(){
		nextitems = nextitems + 2;
		prevItems = nextitems - 3;
		
		for (var i = 0; i < nextitems; i++) {
			
			li[i].style.border = "1px solid red";

			if(nextitems >= li.length){
				li[i].style.border = "1px solid red";
				//nextitems = 2;
				break;
				//this.pointerEvents = "none";
			}
		}
		
		for (var i = 0; i < prevItems; i++) {
			li[i].style.border = "0px solid transparent";
			
			if(prevItems <= li.length){
				prevItems = nextitems - 3;
				li[i].style.border = "1px solid transparent";
			}
			
		}
		
		return ++nextitems;
		//return --prevItems;
	}
})();
<div id="list">	
	<div> one 1</div>
	<div> two 2</div>
	<div> three 3</div>
	<div> four 4</div>
	<div> five 5</div>
	<div> six 6</div>
	<div> seven 7</div>
	<div> eight 8</div>
	<div> nine 9 </div>
	<div> ten 10</div>
	<div> eleven 11</div>
	<div> twelve 12</div>
	<div> thirteen 13</div>
	<div> fourteen 14</div>
</div>

<button id="prev" onclick="prevfun()">PREVIOUS 3</button>
<button id="next" onclick="nextfun()">NEXT 3</button>

Answers:

Answer

I suggest to use only one variable for the start of the marked items and check if the item is in the inverval for marking red or not.

var next = document.getElementById("next"),
    list = document.getElementById("list"),
    li = list.getElementsByTagName("DIV"),
    i,
    nextfun = (function () {
        var item = 3;
        return function () {
            for (var i = 0; i < li.length; i++) {
                li[i].style.border = i >= item && i < item + 3 ? "1px solid red" : "0px solid transparent";
            }
            item += 3;
        }
    })();


for (i = 0; i < li.length; i++) {
    li[i].style.border = "0px solid transparent";
}

for (var i = 0; i < 3; i++) {
    li[i].style.border = "1px solid red";
}
<div id="list"><div> one 1</div><div> two 2</div><div> three 3</div><div> four 4</div><div> five 5</div><div> six 6</div><div> seven 7</div><div> eight 8</div>	<div> nine 9 </div><div> ten 10</div><div> eleven 11</div><div> twelve 12</div><div> thirteen 13</div><div> fourteen 14</div></div>
<button id="prev" onclick="prevfun()">PREVIOUS 3</button>
<button id="next" onclick="nextfun()">NEXT 3</button>

A slightly better version with encapsulation for the buttons.

function Button(count) {
    function setBorder() {
        var i,
            li = list.getElementsByTagName("DIV"),
            l = li.length;

        document.getElementById('prev').disabled = index <= 0;
        document.getElementById('next').disabled = index + count >= l;
        for (i = 0; i < l; i++) {
            li[i].style.border = i >= index && i < index + 3 ? "1px solid red" : "0px solid transparent";
        }
    }

    var index = 0;

    this.next = function () {
        index += count;
        setBorder();
    };
    this.prev = function () {
        index -= count;
        setBorder();
    };
    setBorder();
}

var button = new Button(3);
<div id="list"><div> one 1</div><div> two 2</div><div> three 3</div><div> four 4</div><div> five 5</div><div> six 6</div><div> seven 7</div><div> eight 8</div>	<div> nine 9 </div><div> ten 10</div><div> eleven 11</div><div> twelve 12</div><div> thirteen 13</div><div> fourteen 14</div></div>
<button id="prev" onclick="button.prev()">PREVIOUS 3</button>
<button id="next" onclick="button.next()">NEXT 3</button>

Answer

Just separate a function that will render your selection and set if the buttons are disabled or not. On your nextfun and prevfun functions, just increment or decrement your currentIndex variable.

var next = document.getElementById("next"),
    prev = document.getElementById("prev"),
    list = document.getElementById("list");

var li = list.getElementsByTagName("DIV");
var currentIndex = 0, amount = 3, len = li.length;

var selectItems = function() {
    // render the borders
    for (var i=0; i < len; i++) {
        li[i].style.border = (i >= currentIndex && i < currentIndex + amount) ?
            "1px solid red": "1px solid transparent";
    }
    // set the disabled property of the buttons
    prev.disabled = currentIndex - amount < 0;
    next.disabled = currentIndex + amount > len;

    // uncomment below if you want to stop if next don't have
    // 3 items
    // next.disabled = currentIndex + (amount * 2) > len;
};

// decrement the currentIndex by amount and render
var prevfun = function() {
    currentIndex-=amount;
    selectItems();
};
// increment the currentIndex by amount and render
var nextfun = function() {
    currentIndex+=amount;
    selectItems();
};

selectItems();
<div id="list">	
	<div> one 1</div>
	<div> two 2</div>
	<div> three 3</div>
	<div> four 4</div>
	<div> five 5</div>
	<div> six 6</div>
	<div> seven 7</div>
	<div> eight 8</div>
	<div> nine 9 </div>
	<div> ten 10</div>
	<div> eleven 11</div>
	<div> twelve 12</div>
	<div> thirteen 13</div>
	<div> fourteen 14</div>
</div>

<button id="prev" onclick="prevfun()">PREVIOUS 3</button>
<button id="next" onclick="nextfun()">NEXT 3</button>

Answer

I think this is a fairly elegant solution to your problem, but it seems you have some unnecessary code in your script, I've left it just in case you omitted some functionality.

var next = document.getElementById("next"),
    list = document.getElementById("list"),
    li = list.getElementsByTagName("DIV");

// not sure why you have this?
for (var i = 0; i < li.length; i++) {
    li[i].style.display = "0px solid transparent";
}

// this can be achieved with only css
for (var i = 0; i < 3; i++) {
    li[i].style.border = "1px solid red";
}

var min = 0;
var len = li.length;

var nextfun = function() {
        min = min + 3;
        max = ((min + 3) > len ? li.length : min + 3);
        var decrement = ((min + 3) < len ? 3 : len - min);

        if (min < len) {
            // add borders
            for (var i = min; i < max; i++) {
                li[i].style.border = "1px solid red";
            }

            // remove borders 
            for (var i = min - 3; i < max - decrement; i++) {
                li[i].style.border = "0";   
            }    
        }
}
Answer

One possible solution for this problem would be the snippet below:

var listItems = document.getElementById('list').getElementsByTagName("div");
var highlightedListItemPosition = 0;
highlightListItems();

function highlightNextThreeListItems() {
  if (highlightedListItemPosition < listItems.length) {
    highlightedListItemPosition += 3;
    highlightListItems();
  }
}

function highlighPreviusThreeListItems() {
  if (highlightedListItemPosition > 0) {
    highlightedListItemPosition -= 3;
    highlightListItems();
  }
}

function unhighlightAllListItems() {
  for (var i = 0; i < listItems.length; i++) {
    listItems[i].style.border = "0px solid transparent";
  }
}

function highlightListItems() {
  unhighlightAllListItems();
  var loopLimit;
  if ((listItems.length - highlightedListItemPosition) >= 3) {
    loopLimit = highlightedListItemPosition + 3;
  } else {
    loopLimit = highlightedListItemPosition + listItems.length - highlightedListItemPosition;
  }
  for (var i = highlightedListItemPosition; i < loopLimit; i++) {
    listItems[i].style.border = "1px solid red";
  }
}
<div id="list">
  <div> one 1</div>
  <div> two 2</div>
  <div> three 3</div>
  <div> four 4</div>
  <div> five 5</div>
  <div> six 6</div>
  <div> seven 7</div>
  <div> eight 8</div>
  <div> nine 9 </div>
  <div> ten 10</div>
  <div> eleven 11</div>
  <div> twelve 12</div>
  <div> thirteen 13</div>
  <div> fourteen 14</div>
</div>

<button id="prev" onclick="highlighPreviusThreeListItems()">PREVIOUS 3</button>
<button id="next" onclick="highlightNextThreeListItems()">NEXT 3</button>

Answer

maybe something like this (though not perfect)

const buttons = document.getElementById("buttons");
const lis = Array.from(document.getElementById("list").children);
let Chunk = {
  slicingIndices: {
    start: 0,
    end: 0
  },
  current: '',
  prev: ''
};

const getNextChunk = () => {
  let {
    start, end
  } = Chunk.slicingIndices;
  [start, end] = [end, end + 3];
  const saved = Chunk.current;
  const newChunk = lis.slice(start, end);
  if (newChunk.length !== 3) return saved;
  Chunk.current = newChunk;
  Chunk.slicingIndices = {
    start, end
  };
  return Chunk.current;
};

const getPrevChunk = () => {
  let {
    start, end
  } = Chunk.slicingIndices;
  [start, end] = [start - 3, end - 3];
  const saved = Chunk.prev;
  const newChunk = lis.slice(start, end);
  if (newChunk.length !== 3) return saved;
  Chunk.prev = newChunk;
  Chunk.slicingIndices = {
    start, end
  };
  return Chunk.prev;
};

const colorChunk = chunk => (
  chunk.forEach(item => item.style.backgroundColor = 'cornflowerblue')
);

// have not implemented this stuff, sorry
const disableBtn = btn => btn.disabled = true;
const enableBtn = btn => btn.disabled = false;

const resetColorForAllItems = () => (
  lis.forEach(item => item.style.backgroundColor = '#eee')
);

buttons.addEventListener('click', (e) => {
  let chunk = e.target && e.target.id == "next" ? getNextChunk() : getPrevChunk();
  resetColorForAllItems();
  colorChunk(chunk);
});

colorChunk(getNextChunk());
.container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
ul {
  padding: 0;
  background-color: #eee;
  list-style: none;
}
<div class="container">
  <ul id="list">
    <li>one 1</li>
    <li>two 2</li>
    <li>three 3</li>
    <li>four 4</li>
    <li>five 5</li>
    <li>six 6</li>
    <li>seven 7</li>
    <li>eight 8</li>
    <li>nine 9</li>
    <li>ten 10</li>
    <li>eleven 11</li>
    <li>twelve 12</li>
    <li>thirteen 13</li>
    <li>fourteen 14</li>
  </ul>
  <div id="buttons">
    <button id="prev">PREVIOUS 3</button>
    <button id="next">NEXT 3</button>
  </div>
</div>

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.