0

I'm working on this simple "Book List" task and I'm almost done with it, except that I would like to add a text under each book such as: text1, text2, text3, etc. I have an array that stores each text. As of right now I'm looping through my array but I keep getting "text12" for all the pictures. Basically I want to add a functionality that when the user clicks on a link for example "Murach's HTML5 and CSS3" I should get the picture as well as text1 and so on right below the picture. Can anyone tell me what I'm doing wrong please. Thank you so much in advanced.

CodePen: http://codepen.io/HenryGranados/pen/dMNpBV

Here's my javascript code:

var $ = function (id) {
return document.getElementById(id);
}
window.onload = function () {
// set up the list display
var categories = $("categories");
var h2Elements = categories.getElementsByTagName("h2");

var h2Node;
for (var i = 0; i < h2Elements.length; i++ ) {
h2Node = h2Elements[i];

    // Attach event handler
    h2Node.onclick = function () {
        
        var h2 = this;         // h2 is the current headingNode object

        if (h2.getAttribute("class") == "plus") {
            h2.setAttribute("class", "minus");  
        }
        else {
            h2.setAttribute("class", "plus");
        }
        if (h2.nextElementSibling.getAttribute("class") == "closed") {
            h2.nextElementSibling.setAttribute("class", "open");
        }
        else {
            h2.nextElementSibling.setAttribute("class", "closed");
            var linkElements = h2.nextElementSibling.firstChild.childNodes;
    }
    $("image").setAttribute("src", "");
        // needed for IE so a placeholder isn't displayed for the image
        $("image").setAttribute("style", "display:none;");
   }
 }

 // set up the image display
 var listNode = $("categories");
 var imageNode = $("image");
 var texto = $("texto");

 var imageLinks = listNode.getElementsByTagName("a");
 var array = ["text1", "text2", "text3", "text4", "text5", "text6", "text7", "text8", "text9", "text10", "text11", "text12"];

 // Process image links
 var i, linkNode, image;
 for ( i = 0; i < imageLinks.length; i++ ) {
  linkNode = imageLinks[i];
    for(var j = 0 ; j < array.length; j++){
      linkNodeArray = array[j];

    // Attach event handler
    linkNode.onclick = function (evt) {
        var link = this;          // link is the linkNode
        var mitexto = this;

        imageNode.src = link.getAttribute("href");
        texto.innerHTML = linkNodeArray;

        // needed for IE to display the image
        imageNode.setAttribute("style", "display:block;");

        // Cancel the default action of the event
        if (!evt) { evt = window.event; }
    if ( evt.preventDefault ) {
            evt.preventDefault();          // DOM compliant code
      }
      else {
        evt.returnValue = false;
      }
    }
    // Preload image
    image = new Image();
    image.src = linkNode.getAttribute("href");
  }   
 } 
}
2
  • What is wrong with the current output? It's a little unclear. Commented Mar 17, 2016 at 2:30
  • @Scott my program runs just fine, but I want to add a functionality that when the user clicks on a link for example "Murach's HTML5 and CSS3" I should get the picture as well as the text1 right below the picture and so on Commented Mar 17, 2016 at 2:32

2 Answers 2

1

You looping through "imageLinks" and for each item in imageLinks you also loop to end of array (text array). So, the event "onclick" will be override to the last one (use last text array element).

One more, you should set the text for each image to link attribute. It'll help to separate with each other

Fixed code should like :

var $ = function (id) {
    return document.getElementById(id);
}
window.onload = function () {
    // set up the list display
    var categories = $("categories");
  var h2Elements = categories.getElementsByTagName("h2");

  var h2Node;
  for (var i = 0; i < h2Elements.length; i++ ) {
   h2Node = h2Elements[i];

        // Attach event handler
        h2Node.onclick = function () {

            var h2 = this;         // h2 is the current headingNode object

            if (h2.getAttribute("class") == "plus") {
                h2.setAttribute("class", "minus");  
            }
            else {
                h2.setAttribute("class", "plus");
            }
            if (h2.nextElementSibling.getAttribute("class") == "closed") {
                h2.nextElementSibling.setAttribute("class", "open");
            }
            else {
                h2.nextElementSibling.setAttribute("class", "closed");
                var linkElements = h2.nextElementSibling.firstChild.childNodes;
        }
        $("image").setAttribute("src", "");
            // needed for IE so a placeholder isn't displayed for the image
            $("image").setAttribute("style", "display:none;");
   }
 }

    // set up the image display
    var listNode = $("categories");
    var imageNode = $("image");
    var texto = $("texto");

    var imageLinks = listNode.getElementsByTagName("a");
    var array = ["text1", "text2", "text3", "text4", "text5", "text6", "text7", "text8", "text9", "text10", "text11", "text12"];

    // Process image links
 var i, linkNode, image;
 for ( i = 0,j=0; i < imageLinks.length; i++,j++ ) {
  linkNode = imageLinks[i];
      if(j>=array.length) j=0; //Back to begin if array text not enough for link elements
      linkNodeArray = array[j];
    linkNode.setAttribute('title',linkNodeArray);
    // Attach event handler
    linkNode.onclick = function (evt) {
        var link = this;          // link is the linkNode
        var mitexto = this;

        imageNode.src = link.getAttribute("href");
        texto.innerHTML = link.getAttribute('title');

        // needed for IE to display the image
        imageNode.setAttribute("style", "display:block;");

        // Cancel the default action of the event
        if (!evt) { evt = window.event; }
    if ( evt.preventDefault ) {
            evt.preventDefault();          // DOM compliant code
      }
      else {
        evt.returnValue = false;
      }
    }
    // Preload image
    image = new Image();
    image.src = linkNode.getAttribute("href");

 }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Your code is 99% perfect!!! there are just one little issue. For example when you click on "Murach's MySQL" (which gives you text4) and then click on "Books for Java developers" the text "text4" is still showing. Is there any way that when you click on "Books for Java developers" the text4 can go away? Thanks a lot!
Hi. Because that's "h2 tag" so above code not process. Simply, just modify code on "Attach event handler" section (your comment) like: var h2 = this; $("texto").innerHTML='';
Thanks a lot, I'm marking your answer as the correct one!!
@xpng I still suggest you to read the link I provided, I am sure you will feel it useful.
@Reddy Thanks Reddy!
0

This is called the Infamous Loop Problem (Please read this document to get better understanding of this problem. Navigate to the section The Infamous Loop Problem), The values inside the loop are passed by reference, So only the last loops value will be assigned to all the other loops too as all the loop still points to the same referenced variable and the last set value is the one every loop points to. The issue will be resolved if you wrap all your stuff inside the onclick into a return function. See the below code.

for (var i = 0; i < h2Elements.length; i++ ) {
 ....
 ....
 h2Node.onclick = function () {
  return function(){
    //put all your existing stuff here.
  };    
 }();
 ....

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.