3

I can select any item in the list by clicking on it and apply border. Then When I click on right arrow button to select next item from where I already picked item by clicking on it is not working. It selects next item but only once. I want that to apply for every item by clicking on right arrow one by one. same thing in reverse order for leftarrow. Can someone help me with pure javascript. below is my script working only for once clicked.

<ul id="gallery">
    <li><img src="images/one.jpg" /></li>
    <li><img src="images/two.jpg" /></li>
    <li><img src="images/three.jpg" /></li>
    <li><img src="images/four.jpg" /></li>
</ul>

<div id="leftArw"></div>
<div id="rightArw"></div>


var list = document.getElementById("gallery").getElementsByTagName("LI");    
var items, currentDiv, leftArw, rightArw;    
leftArw = document.getElementById("leftArw"),
rightArw = document.getElementById("rightArw");
rightArw.addEventListener("click", right, false);

for (items = 0; items < list.length; items++) {
    list[items].style.border = "none";
    //list[items].addEventListener("click", currentItem, false);
    list[items].onclick = function () {
        currentDiv = this;
        this.style.border = "5px solid red";
    }
}

function right() {
    currentDiv.nextElementSibling.style.border = "5px solid red";
}
jake
  • 136
  • 1
  • 12

1 Answers1

2

// click handler to set the current "selected" element
document.querySelector("#gallery").addEventListener("click", function(e) {
  // list items are the only valid "click" source to work with
  if (e.target.nodeName !== "LI") {
    return;
  }

  var currentlySelectedElement = e.currentTarget // the <ul> element
                                  .querySelector(".selected");

  if (currentlySelectedElement !== null) {
    currentlySelectedElement.className = "";
  }

  e.target // the <li> element
   .className = "selected";
}, false);

// click handler for the "arrow" button
var right = (function() { // Closure to only query the DOM for the <li> elements once
  var items = document.querySelectorAll("#gallery li");

  function getSelectedItem() {
    var l = items.length,
        i = 0;

    for (; i < l; i++) {
      if (items[i].className === "selected") {
        return items[i];
      }
    }

    return null;
  }

  // actual click handler to select the next element
  return function() {
    var selectedItem = getSelectedItem(),
        nextItem;

    if (selectedItem !== null) {
      nextItem = selectedItem.nextElementSibling || items[0];

      selectedItem.className = "";
      nextItem.className = "selected";
    }
  };
}());

document.querySelector("#rightArw").addEventListener("click", right, false);
.selected {
  outline: solid 1px red
}
#rightArw {
  width: 50px;
  height: 50px;
  background-color: yellow
}
<ul id="gallery">
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

<div id="rightArw"></div>

Edit

You've mentioned in the comments, that the script won't work if you add <img /> in the <li /> elements.

<li><img src="images/one.jpg" /></li>

That's because the "click" event isn't longer triggered from the <li /> but from the <img /> element. That is, the "selected" state is now set on <img /> because of e.target. When you now click on the "arrow" the handler looks for an <li /> with the class selected (selectedItem = getSelectedItem()) which he cannot find and therefor won't go to the next <li /> element (if (selectedItem !== null)).

To get this script back to work you will have to adjust the e.target part. In this case you will have to walk one step up (.parentNode) in the DOM:

document.querySelector("#gallery").addEventListener("click", function(e) {
  // images are the only valid "click" source to work with
  if (e.target.nodeName !== "IMG") {
    return;
  }

  var currentlySelectedElement = e.currentTarget // the <ul> element
                                  .querySelector(".selected");

  if (currentlySelectedElement !== null) {
    currentlySelectedElement.className = "";
  }

  e.target  // the <img />
   .parentNode // the <li> element
   .className = "selected";
}, false);

var right = (function() {
  var items = document.querySelectorAll("#gallery li");

  function getSelectedItem() {
    var l = items.length,
        i = 0;

    for (; i < l; i++) {
      if (items[i].className === "selected") {
        return items[i];
      }
    }

    return null;
  }

  return function() {
    var selectedItem = getSelectedItem(),
        nextItem;

    if (selectedItem !== null) {
      nextItem = selectedItem.nextElementSibling || items[0];

      selectedItem.className = "";
      nextItem.className = "selected";
    }
  };
}());

document.querySelector("#rightArw").addEventListener("click", right, false);
.selected {
  outline: solid 1px red
}
#rightArw {
  width: 50px;
  height: 50px;
  background-color: yellow
}
<ul id="gallery">
  <li><img src="images/one.jpg" /></li>
  <li><img src="images/one.jpg" /></li>
  <li><img src="images/one.jpg" /></li>
  <li><img src="images/one.jpg" /></li>
</ul>

<div id="rightArw"></div>

Edit 2

I've added yet another check in the <ul /> click handler (right at the top) to prevent the handler to run on clicks which are not triggered by a <li /> (in the first example) or an <img /> in the second example.

Andreas
  • 21,535
  • 7
  • 47
  • 56
  • Its working fine with text inside li elements, but if i use images inside
  • its not working. – jake Aug 20 '16 at 16:49
  • I've edited my answer and added an example with images in the list items. Also have a look at my second edit (Edit 2). – Andreas Aug 20 '16 at 17:29
  • Andreas, sorry to bother you. can you please look into this link and suggest me if its the right way to do it or not? [here](http://stackoverflow.com/questions/39437280/how-can-i-resuse-the-window-keycode-function-using-by-closure-or-any-other-metho) – jake Sep 13 '16 at 11:11
  • with your help of closure method for this example I tried new one with little advanced but stuck in middle, can you please help me with this [link](http://stackoverflow.com/questions/40026278/how-to-select-next-specific-number-of-elements-in-loop-by-every-click-in-pure-ja) – jake Oct 13 '16 at 16:25