Michelangelo
Michelangelo

Reputation: 5948

How to find next element from a certain class from click event in javascript (not in jQuery!)?

I am trying to solve a problem in javascript and I want to do it in javascript not in jQuery. I create objects in javascript, display them as elements and I bind an eventListener. For simplicity I create objects with a name, description and a price. What I basically want to do is when people click the name the corresponding price is alerted. Is there any way to do this with javascript? In my actual project I want a hover event so that people get a tooltip-like description of the product, but the idea is the same.

Thanks in advance.

Here a fiddle: fiddle

And some code:

function makeProduct (name, description, price) {
    this.name = "<p class='name'>" + name + "</p>";
    this.description = "<p class='description'>" + description + "<p>";
    this.price = "<p class='price'>" + price + "</p>";
    document.getElementById('productlist').innerHTML+=this.name;
    document.getElementById('productlist').innerHTML+=this.description;    
    document.getElementById('productlist').innerHTML+=this.price;    
}

var product1=new makeProduct("Pizza", "very Tasty", 5.00);
var product2=new makeProduct("Choclate milk", "warm for the cold winter", 3.00);


var productnames = document.getElementsByClassName('name');
for (i=0; i<productnames.length; i++){
      (function(){
    productnames[i].addEventListener('click', showPrice, false);   
    })();
}

function showPrice () {
 alert("product price");
}

Upvotes: 0

Views: 2855

Answers (2)

asdf_enel_hak
asdf_enel_hak

Reputation: 7640

First I fix your current code:

function makeProduct (name, description, price) {
    this.name = "<p class='name'>" + name + "</p>";
    this.description = "<p class='description'>" + description + "<p>"; //this line
    ...
}

//this line shoud be:

this.description = "<p class='description'>" + description + "</p>"; //</p> should be closing tag

Secondly:

function makeProduct (name, description, price) {
 //...
 document.getElementById('productlist').innerHTML+=this.price;
}

as makeProduct(..) returns nothing, there shoulding be assigment to new object to product1

var product1=new makeProduct("Pizza", "very Tasty", 5.00); 

Finally your function that returs relevant price should look line:

function showPrice(evt)
{
    var p1 = evt.target.nextSibling.nextSibling;
    alert(p1.innerHTML);    
}

DEMO

Upvotes: 1

pete
pete

Reputation: 25081

The quick fix is to write a function that returns the next matching p elem:

function getNextElement(elem, className) {
    var next = elem.nextElementSibling; // set next element to "nextElementSibling" relative to passed element.
    while (next && !next.classList.contains(className)) { // check for existence and class
        next = next.nextElementSibling; // if it exists, but the class does not, move to the next element and repeat.
    }
    return next; // return whatever was found, or null
}
function showPrice () {
    var elem = getNextElement(this, 'price'),
        price = elem ? elem.innerHTML : 'Price not found.';
    alert(price);
}

See updated fiddle: http://jsfiddle.net/zkbdy0rt/5/

A better way to do this would be to change how you are building your product list. For instance, I would put each product in a containing div (with class="product") for easier styling or finding.

In JavaScript, you can also add arbitrary properties to DOM elements which can be useful. For instance, you could store the price on the DOM element and then retrieve it in your click event handler.

div.price = product.price;

and then later...

showPrice = function (e) {
    var price = this.parentElement.price;
    alert(price.toFixed(2));
}

See this fiddle for a working example: http://jsfiddle.net/zkbdy0rt/6/

Upvotes: 2

Related Questions