1

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>
jake
  • 136
  • 1
  • 12
  • `li[i].style.display = "0px solid transparent";` that's not a valid value for [`display`](https://developer.mozilla.org/en/docs/Web/CSS/display) – Andreas Oct 13 '16 at 16:42
  • Sorry. My bad. I forgot to replace that by 'border' – jake Oct 13 '16 at 16:52

5 Answers5

2

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>
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • 1
    Thanks a Ton! I was looking for dynamic parameter values too which you did it here. Easy to understand and less lines of code too. I wanted to use display:block and display:none instead of border:1px and border:0px to show/hide items like pagination style. I Just changed in one line " li[i].style.display = i >= index && i < index + 3 ? "block" : "none"; " It worked like a charm. Thank you once again! – jake Oct 14 '16 at 03:55
  • hello, Can you help me with this one [angular $apply and javascript apply()](http://stackoverflow.com/questions/42391877/how-can-we-use-scope-apply-method-in-angular-like-javascript-apply-method-like) – jake Feb 22 '17 at 14:27
1

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>
jrarama
  • 904
  • 7
  • 8
  • @NinaScholz Apologies. The problem is not very clear to me. I updated the code to select last 2 items after 13 – jrarama Oct 13 '16 at 17:25
  • @jrarama Thank you for the help! It worked. well explained. – jake Oct 14 '16 at 03:59
  • @jrarama, I have raised a new question with some changes [here](http://stackoverflow.com/questions/40059776/specific-number-of-elements-in-loop-are-not-selecting-if-data-retrieving-from-js). can you people help me with this one. – jake Oct 15 '16 at 13:47
0

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";   
            }    
        }
}
j_quelly
  • 1,399
  • 4
  • 16
  • 37
0

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>
mariushab
  • 103
  • 1
  • 1
  • 8
  • hello, Can someone help me with this one [angular $apply and javascript apply()](http://stackoverflow.com/questions/42391877/how-can-we-use-scope-apply-method-in-angular-like-javascript-apply-method-like) – jake Feb 22 '17 at 14:28
0

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>
devellopah
  • 471
  • 2
  • 15