4
votes

bangin' my head against this and it's starting to hurt.

I'm having trouble with adding an event to an element. I'm able to add the event, and then call it immediately with element.fireEvent('click'), but once the element is attached to the DOM, it does not react to the click.

example code:

var el = new Element('strong').setStyle('cursor','pointer');
el.addEvent('click',function () { alert('hi!'); });
el.replaces(old_element); // you can assume old_element exists
el.fireEvent('click'); // alert fires

however, once I attach this to the DOM, the element is not reactive to the click. styles stick (cursor is pointer when I mouseover), but no event fires. tried mouseover as well, to no avail.

any clues here? am I missing something basic? I am doing this all over the place, but in this one instance it doesn't work.

EDIT----------------

ok here's some more code. unfortunately I can't expose the real code, as it's for a project that is still under tight wraps.

basically, the nodes all get picked up as "replaceable", then the json found in the rel="" attribute sets the stage for what it should be replaced by. In this particular instance, the replaced element is a user name that should pop up some info when clicked.

again, if I fire the event directly after attaching it, all is good, but the element does not react to the click once it's attached.

HTML-----------

<p>Example: <span class='_mootpl_' rel="{'text':'foo','tag':'strong','event':'click','action':'MyAction','params':{'var1': 'val1','var2': 'val2'}}"></span></p>

JAVASCRIPT----- assumptions: 1. below two functions are part of a larger class 2. ROOTELEMENT is set at initialize() 3. MyAction is defined before any parsing takes place (and is properly handled on the .fireEvent() test)

parseTemplate: function() {
    this.ROOTELEMENT.getElements('span._mootpl_').each(function(el) {
        var _c = JSON.decode(el.get('rel'));
        var new_el = this.get_replace_element(_c); // sets up the base element
        if (_c.hasOwnProperty('event')) {
            new_el = this.attach_event(new_el, _c);
        }
    });
},

attach_event: function(el, _c) {
    el.store(_c.event+'-action',_c.action);
    el.store('params',_c.params);
    el.addEvent(_c.event, function() {
        eval(this.retrieve('click-action') + '(this);');
    }).setStyle('cursor','pointer');
    return el;
},
2
Have you test in firebug that the element has really the dimension you've expect? Sometimes the element has no height and can't click it. - Andreas Köberle
I can see it, it has text in it. I'm attaching a click to a <strong> tag with text inside it. as stated, the mouseover change of the cursor to pointer works just fine, but the click won't fire. - kfancy

2 Answers

2
votes

debugging this is not easy when you lack content / DOM.

first - do you use event delegation or have event handlers on a parent / the parent element that do event.stop()?

if so, replace with event.preventDefault()

second thing to do. do not replace an element but put it somewhere else in the DOM - like document.body's first node and see if it works there.

if it does work elsewhere, see #1

though I realsie you said 'example code', you should write this as:

new Element('strong', {
    styles: {
        cursor: "pointer"
    },
    events: {
        click: function(event) {
            console.log("hi");
        }
    }
}).replaces(old_element);

no point in doing 3 separate statements and saving a reference if you are not going to reuse it. you really ought to show the ACTUAL code if you need advice, though. in this snippet you don't even set content text so the element won't show if it's inline. could it be a styling issue, what is the display on the element, inline? inline-block?

can you assign it a class that changes it on a :hover pseudo and see it do it? mind you, you say the cursor sticks which means you can mouseover it - hence css works. this also eliminates the possibility of having any element shims above it / transparent els that can prevent the event from bubbling.

finally. assign it an id in the making. assign the event to a parent element via:

parentEl.addEvent("click:relay(strong#idhere)", fn);

and see if it works that way (you need Element.delegate from mootools-more)

good luck, gotta love the weird problems - makes our job worth doing. it wouldn't be the worst thing to post a url or JSFIDDLE too...