Black
Black

Reputation: 20222

prototypejs - create click event for button with class

I tried it like this:

Event.observe('.add_select_row', 'click', function() {
    console.log("KLICK!");
});

But I get "Uncaught TypeError: Cannot read property 'get' of undefined"

I also tried:

Event.observe('add_select_row', 'click', function() {
    console.log("KLICK!");
});

... and ...

Event.observe($('.add_select_row'), 'click', function() {
    console.log("KLICK!");
});

enter image description here

http://api.prototypejs.org/dom/Event/observe/

Upvotes: 0

Views: 709

Answers (1)

Walter
Walter

Reputation: 1150

Event.observe requires a DOM element or an id of a DOM element in order to work. If you want to bind a click event listener to a collection of one or more elements sharing the same classname, then you need to construct your listener differently, or bind a unique listener to each element sharing that classname.

The simplest way to do what you're describing here would be to add an ID to the element you want to listen to. If you can't do that, then you could rewrite your listener so that it responds at a different level:

$(document).observe('click', '.add_select_row', function(evt, elm){
  // evt is now bound to the click event, so you could keep it from bubbling:
  evt.stop();
  // elm is now bound to the element with the classname add_select_row
  // that triggered the click, so you can do something with that
  elm.addClassName('clicked');
  console.log('CLICK');
});

This pattern is known as a "lazy observer", which takes advantage of the fact that click events bubble up and are eventually caught by the document itself. You're not limited to using the document for this, either. You could also set this sort of observer on any parent element of the button, for example:

$('foo').on('click', '.add_select_row', function(evt, elm){});

if you had a div#foo at some ancestor level to that button.

The benefit to this pattern is that you don't end up with a separate observer bound to each element in your page that shares that classname. One observer will work for any number of observable elements, as long as you want each one to do the same thing.

If you really wanted to have a separate observer for each button, you could give each one an unique ID. If that wasn't practical, you could do this (but don't -- it's wasteful to create observers for multiple elements when you're only interested in one):

$$('.add_select_row').each(function(elm){
  elm.observe('click', function(evt){
    console.log('CLICK');
  });
});

The "double-dollar" method in Prototype allows you to use classnames or any other CSS selector to identify a collection of elements on the page. Even if there is only one returned matching element on the page, it always returns an array containing that element. This is similar to how jQuery sees the DOM, and in Prototype 1.7 and up, uses the same Sizzle CSS selector library to select elements.

Upvotes: 3

Related Questions