views:

206

answers:

2

I am learning the prototype framework and javascript in general and am tring to refactor a bit of existing code to create some html from data inside of a class using an event listener. I am having problems getting the events to fire and getting the corresponding listener code working. Here is a small example, that I can't get working:

<html>
<head>
    <title>Event Test</title>
    <script type="text/javascript" src="prototype.js"></script>

    <script type="text/javascript">
        MyClass = Class.create({
            initialize: function(args) {
                this.div_id = $(args['div_id']);
            },
            test: function() {
                this.div_id.fire('ag:test');
            }
        });

        var myclass = new MyClass({div_id:'test'});

        $('test').observe(myclass, 'ag:test', function(evt){
            $('test').insert('<p>Test</p>');
        });


        myclass.test();
    </script>
</head>

<body>
    <div id="test">
    </div>
</body>

My intention is that I just want to add a bit of html to the div when the class is instantiated, or when some other method is called on the class. Right now this code doesn't do anything. Using firebug, it seems that my class is never being instantiated here. I've been looking at examples and the prototype docs, but can't figure out what I'm doing wrong.

Thanks!

EDIT: Changed to not fire event in the class constructor.

+1  A: 

You listen the #test div's ag:test event but fire the event on the class so it is very normal that nothing happens. You should listen to the events of the class you are creating but then you cannot catch the instantination event since you cannot attach event handlers before the class is instantinated. So you have to find another way.

BYK
Could you elaborate a bit more?
Casey
just edited my code with part of your answer.
Casey
You still do a very wrong thing. You have to listen to the newly created class for events. Something like Event.observe(myclass, 'ag:test', function(e) ...);
BYK
please look at the code, I just changed a couple of things. I am now passing the div id to the class and calling the fire method from the element. It's still not working though.
Casey
Should be $(this.div_id).fire('ag:test');
BYK
that didn't change anything. Am I do something wrong in the call to observe? Firebug doesn't seem to execute that code, and I am also getting a this.div_id = null after the class is constructed.
Casey
+1 for identifying the problem with firing the event before the class is fully instantiated.
Casey
A: 

Got it! It was a problem with deferred loading. In the original question I had all of the javascript defined in the header. It was failing because when I use $('test'), the element doesn't exist yet. The correct code would be:

<html>
<head>
    <title>Event Test</title>
    <script type="text/javascript" src="prototype.js"></script>

    <script type="text/javascript">
        MyClass = Class.create({
            initialize: function(args) {
                this.div_id = $(args['div_id']);
            },
            test: function() {
                this.div_id.fire('ag:test');
            }
        });


    </script>
</head>

<body>
    <div id="test">
    </div>

    <script type="text/javascript">
        var myclass = new MyClass({div_id:'test'});

        $('test').observe('ag:test', function(evt){
            $('test').insert('<p>Test</p>');
        });


        myclass.test();
    </script>
</body>

Casey
No the last one was due to "early" loading of your script but your main problem was using the mechanism in a completely irrelevant way. Also you did not even upvoted my answer although that was your "real" problem. So no more answers from me for you from now on. Take care...
BYK
I didn't even understand your original answer. My code also went through 3 revisions before I got here. I am not using the mechanism in a completely irrelevant way. This is a small part of what I am trying to do and that is seperating the creation of html elements form the inner workings of the class. this was a scaled down version of the problem, since I can't post the real code here. The original code was being executed in a deffered_javascript_block. The only real problem with the original code was, as you said, that I was firing the event from the initializer, which was fixed.
Casey
I think you should relax and calm down. How about a flag instead of an up vote for being a jerk? I haven't even accepted an answer yet. How do you know I wouldn't have up voted you?
Casey
I am calm and you are the one calling me as jerk =) And using my answer to update your code and then posting your own answer shows that you either did not understand what I have told in my answer or you have no respect for me. I think the second one is correct since you were able to update your code according to my answer. If you want go ahead and flag my comments or answer but the solution to your problem lies in my answer and flagging it will not change this fact. Farewell.
BYK
First, I already said I didn't understand your entire answer, but you also didn't fully answer my question. You identified one part of it that was indeed wrong, which I fixed. If you want an upvote for that no problem. You told me to 'find another way', and it was my work that got me the rest of the way. In fact your other comment about using Event.observe, didn't work for what I was trying to do.So if you want to keep whining about it go for it. I'm done with the conversation. Thank you for your time.
Casey