2016-01-31 15 views
6

Mam kilka przycisków (generowanych przez PHP) dla aplikacji Koszyk:Jak przypisać funkcję javascript przez classname

<button class="addtocart" id="<?php echo $code; ?>"> 
    <span id="addtocartbutton">Add to cart</span> 
</button> 

Chcę zaktualizować mój wózek za pomocą funkcji:

function AddtoCart() { 
    alert("Added!"); 
} 

Później chcę znaleźć id (kod $) utworzony przez przycisk, który go nazwał (nie wiem, jak to zrobić, ale może to kolejne pytanie). I tak spróbowałem:

document.getElementsByClassName("addtocart").addEventListener("click", AddtoCart()); 

Ale to nie działa. Pracował przy użyciu onclick, ale rozumiem, że we właściwy sposób to zrobić, tworząc EventListener. Ponadto nie mogę używać funkcji on() w jQuery, ponieważ jestem zmuszony do korzystania z jQuery w wersji 1.6, która jej nie ma.

Spojrzałem na https://stackoverflow.com/a/25387857/989468 i naprawdę nie mogę przypisać tego do rodzica, który jest znacznikiem p, ponieważ oczywiście nie chcę, aby inne elementy w znaczniku p miały przypisaną tę funkcję.

+0

możemy dodać id w przycisk –

+0

znaczy atrybutu nazwa –

+1

IIRC, j Query 1.6 miał '.live', który jest w zasadzie taki sam jak' .on'. – georg

Odpowiedz

3

Podczas odpowiedzi udzielone są prawidłowe, istnieje inny sposób: Event Delegation

Attach słuchacza do jednej rzeczy, w tym przypadku dokument body a następnie sprawdzić, co element został faktycznie kliknął:

Ostrzeżenie: wpisane w locie: niesprawdzone

// Only needed *once* and items may be added or removed on the fly without 
// having to add/remove event listeners. 
document.body.addEventListener("click", addtoCart); 

function addtoCart(event) { 
    var target = event.target; 

    while(target) { 
     if (target.classList.contains('addtocart')) { 
     break; 
     } 
     // Note: May want parentElement here instead. 
     target = target.parentNode; 
    } 

    if (!target) { 
     return; 
    } 

    var id = target.dataset.id; 
    alert(id + " added!"); 
} 
+0

Wygląda to bardzo obiecująco. Gdybym tylko mógł to zrozumieć! :-) Na przykład, dlaczego potrzebujesz czasu? I dlaczego nie byłoby celu do wydarzenia (ref: if (! Target)). Dlaczego nie skorzystać z "tego"? – Chiwda

+0

Przeczytaj link zawarty w poście, ale krótka odpowiedź: ponieważ "this" nie wskazuje na element, którego się spodziewasz. IIRC, wskazuje na element, który faktycznie kliknąłeś, który może być * wewnątrz * elementem, który faktycznie sprawdzasz. Nie mogę tego teraz przetestować, ale możesz dodać 'console.log' i sprawdzić, jaka jest wartość tego" tego ". Delegacja jest nieco trudniejsza do obłaskawienia, przyznaję, ale jeśli robisz jakieś dynamiczne uaktualnianie zawartości, jest to znacznie lepsze niż dodawanie/usuwanie konkretnych procedur obsługi. –

+0

daje błąd, jeśli klikniesz w dowolnym miejscu na stronie – Gavriel

1
<html> 
<head> 
<script> 
window.onload=function{ 
    var btn = document.getElementsByName("addtocartbtn")[0]; 
    btn.addEventListener("click", AddtoCart()); 
} 

function AddtoCart() { 
    alert("Added!"); 
} 
</script> 
</head> 
<body > 
<button class="addtocart" name ="addtocartbtn" id="<?php echo $code; ?>" > <span id="addtocartbutton">Add to cart</span></button> 

</body> 
</html> 
+0

Czy to nie tylko pierwszy przedmiot? – Chiwda

2

Należy dołączyć click zdarzenia do każdego elementu z klasą addtocart, ponieważ getElementsByClassName() zwraca tablicę wszystkich obiektów o podanej nazwie klasy, więc można używać for pętli każdego z nich i skojarzyć go z funkcji, którą chcesz spust na kliknięcie (w moim przykładzie funkcja ta nazywa my_function), przykład sprawdzić poniżej:

var class_names= document.getElementsByClassName("addtocart"); 

for (var i = 0; i < class_names.length; i++) { 
    class_names[i].addEventListener('click', my_function, false); 
} 

nadzieję, że to pomaga.


function my_function() { 
 
    alert(this.id); 
 
}; 
 

 
var class_names= document.getElementsByClassName("addtocart"); 
 

 
for (var i = 0; i < class_names.length; i++) { 
 
    class_names[i].addEventListener('click', my_function, false); 
 
}
<button class="addtocart" id="id_1">button 1</button> 
 
<button class="addtocart" id="id_2">button 2</button> 
 
<button class="addtocart" id="id_3">button 3</button> 
 
<button class="addtocart" id="id_3">button 4</button>

+0

Widziałem odpowiedź podobną do tej, ale problem polega na tym, że identyfikatory są generowane po fakcie, tj. Po załadowaniu strony. Tak więc nie mogę naprawdę powiązać funkcji z każdym z góry. – Chiwda

+0

Tak, widzę, dlaczego używam nazwy "class" w mojej odpowiedzi, aby powiązać zdarzenie click, więc nie ważne, czy identyfikatory są generowane automatycznie, jeśli jest tam nazwa klasy. –

+0

Podoba mi się twoje rozwiązanie, ale wydaje mi się, że dzieli on po raz pierwszy wadę z innymi odpowiedziami poniżej. Naprawdę uważam, że jest to nieskuteczny kod, w którym pętla przechodzi przez wszystkie elementy tablicy za każdym razem, gdy ktoś kliknie element, aby dodać go do koszyka. Wyobraź sobie przypadek, w którym są setki pokazanych przedmiotów - to dużo kosztów ogólnych dla każdego kliknięcia! Wolałbym wrócić do starego i podobno złego sposobu wskazywania funkcji w html onclick dla przycisku. Podobnie jak w Chiwda

2

pokażę niektóre błędy trzeba było w kodzie, a następnie pokażę, jak można ją poprawić tak, że można osiągnąć to, co chcesz, i pokazuję również, że działa z przyciskami dodanymi dynamicznie później:

Przede wszystkim musisz przekazać referencję funkcji (jej nazwę) do addEventListener! Nazwałeś tę funkcję i przekazałeś wszystko, co powrócił. Zamiast:

document.getElementsByClassName("addtocart").addEventListener("click", AddtoCart()); 

Należy byli:

document.getElementsByClassName("addtocart").addEventListener("click", AddtoCart); 

drugie: document.getElementsByClassName("addtocart") zwraca NodeList, nie można pracować na nim, trzeba działać na jego elementach: document.getElementsByClassName("addtocart")[0], [1],....

trzecie, chciałbym zaproponować Ci użyć atrybutu data-... HTML:

<button class="addtocart" id="addtocart" data-foo="<? echo $code; ?>"> 

ten sposób można przekazać jeszcze więcej danych.Teraz można uzyskać $code jak:

document.getElementById('addtocart').dataset.foo 

// el: the button element 
 
function AddtoCart(el) { 
 
    // this is the id: 
 
    var id = el.id; 
 

 
    // and this is an example data attribute. You can have as many as you wish: 
 
    var foo = el.dataset.foo; 
 
    alert(id + " (" + foo + ") added!"); 
 
} 
 

 
// Try add a div or something around the area where all the buttons 
 
// will be placed. Even those that will be added dynamically. 
 
// This optimizes it a lib, as every click inside that div will trigger 
 
// onButtonClick() 
 
document.getElementById("buttons").addEventListener("click", onButtonClick); 
 

 
// this shows that even works when you dynamically add a button later 
 
document.getElementById('add').onclick = addButton; 
 
function addButton() { 
 
    var s = document.createElement("span"); 
 
    s.text = "Add to cart"; 
 
    var b = document.createElement("button"); 
 
    b.innerHTML = 'Third <span class="addtocartbutton">Add to cart</span>'; 
 
    b.className = "addtocart"; 
 
    b.id="third"; 
 
    b.dataset.foo="trio"; 
 
    // note the new button has the same html structure, class 
 
    // and it's added under #buttons div! 
 
    document.getElementById("buttons").appendChild(b); 
 
} 
 

 

 
// this will gett triggered on every click on #buttons 
 
function onButtonClick(event) { 
 
    var el = event.target; 
 
    if (el && el.parentNode && el.parentNode.classList.contains('addtocart')) { 
 
     // call your original handler and pass the button that has the 
 
     // id and the other datasets 
 
     AddtoCart(el.parentNode); 
 
    } 
 
}
<div id="buttons"> 
 
    <button class="addtocart" id="first" data-foo="uno">First <span class="addtocartbutton">Add to cart</span></button> 
 
    <button class="addtocart" id="second" data-foo="duo">Second <span class="addtocartbutton">Add to cart</span></button> 
 
</div> 
 

 

 
<button id="add">Add new button</button>

+0

'document.getElementsByClassName (" addtocart ")' zwraca strukturę tablicową o nazwie 'NodeList', a nie tablicę. IIRC jest to * live * 'NodeList', który jest jeszcze bardziej nieznajomy. –

+0

Dzięki @JeremyJStarcher, naprawiono NodeList – Gavriel

1

Właściwie klasy w JavaScript jest wielokrotnego wyboru należy zapewnić jak indeks tablicy.

<button class="addtocart"> <span id="addtocartbutton">Add to cart</span></button> 
     <script type="text/javascript"> 
     document.getElementsByClassName("addtocart")[0].addEventListener("click", AddtoCart);   
     function AddtoCart() { 
      alert("Added!"); 
     } 
     </script> 

Twój drugi parametr był nieprawidłowy, nie używaj nawiasów.

Stosowanie nawiasów oznacza, że ​​po wywołaniu funkcja wywoła się automatycznie i nie wywoła funkcji po tym.

+0

używając nawiasów nie jest "źle". Oznacza to, że funkcja zostanie wykonana inline. Musisz wiedzieć, kiedy ich użyć i kiedy ich nie używać. Istnieją przypadki użycia, w których potrzebne jest wywołanie liniowe. :) – AdityaParab

+0

@AdityaParab Tak, masz rację, stosowanie nawiasów nie jest błędne, ale w tym jest źle, ponieważ myślałem, że dodanie produktu do koszyka zostanie wykonane po kliknięciu na przycisk dodaj do koszyka nie automatycznie. Chociaż zaktualizowałem moje ans i dodałem więcej informacji dotyczących nawiasów. – C2486