PDA

View Full Version : Prototype and Event.observe



brentnicholas
01-22-2008, 05:11 PM
Anyone here familiar with how Prototype's "Event.observe" works and rules that might need to be followed to use it?

Here's what I'm getting at:
1) the page loads
2) window.onLoad fires, and uses Ajax.Updater to pull in the menu (an HTML file), with the anchors I want to Event.observe
3) My problem... where do I put the "Event.observe" scripts to observe the anchors? What I'm doing doesn't work.

Examples:

http://www.cflhd.gov/testingajax/index.htm
does not work. The functions are structured in a way that make sense to me, but does not work.

http://www.cflhd.gov/testingajax/test.htm
(Ajax in Practice example) works, but not the way I want it to. I want to 'observe' an element that is pulled in on 'window.onLoad'.

Any help would be greaty appreciated.

Thanks,

BN

jscheuer1
01-22-2008, 07:01 PM
As you've found out, you cannot observe for an element until it is a part of the document.

This:


Event.observe('menuTrainingProvided','click', addTrainingProvided, false);

Basically means that this:


<div id="menuTrainingProvidedDIV">
<a href="#" id="menuProfessionalOutreach">
<img src="" title="Training Provided Image">
Training Provided
</a>
</div>

shall behave like so:


<div id="menuTrainingProvidedDIV"
onclick="addTrainingProvided();">
<a href="#" id="menuProfessionalOutreach">
<img src="" title="Training Provided Image">
Training Provided
</a>
</div>

If you write it like that, you won't even need to 'observe' it. Further, it would probably be better like so:


<div id="menuTrainingProvidedDIV">
<a href="#" id="menuProfessionalOutreach"
onclick="addTrainingProvided();return false;">
<img src="" title="Training Provided Image">
Training Provided
</a>
</div>

or like:


<div id="menuTrainingProvidedDIV"
onclick="addTrainingProvided();">
<a href="#" id="menuProfessionalOutreach"
onclick="return false;">
<img src="" title="Training Provided Image">
Training Provided
</a>
</div>

brentnicholas
01-22-2008, 08:57 PM
Thanks for your reply. I agree to all your points.
What I'm trying to accomplish is to keep all my javascript in an included *.js file included at the top of the page.

So as a result I need to figure out how to register events for objects that are currently in the DOM. Though may not have been at page load.

I've outlined the problem a little better in a google forum as well, here it is:
------------------------------------------------

So i'm trying to keep from littering my HTML with <script> tags. I'd
like all my javascript to be in an included file at the top of the
page.


Anway, I understand the following and how it works:



<h2 id="mydiv">Click me!</h2>
<script type="text/javascript" language="javascript">
Event.observe('mydiv', 'click', function(e){ alert('clicked
me!') });
</script>


Ok, fine. It follows the rule that an 'Event.observe', must be placed
after the element being observed. See: http://wiki.script.aculo.us/scriptaculous/show/Event.observe


However, this litters my HTML with js and tightly couples the UI to
the behaviour. Bad...

So I've beek mucking around with this, and it does not work.

Before I show the code I'll out line it.

1) The page is called and window.onload calls a function that uses
Ajax.updater to load the menu into a DIV on the page.

2) Right below the Ajax.updater in showMainMenu, I try to hold off
registering the event until the DOM is done loading (just grasping at
straws here), and attempt to register the event that watches for what
link you clicked on the menu that was loaded in dspMainMenu.cfm.



/* init section */
window.onload = function() {
showMainMenu();
};

function showMainMenu()
{
new Ajax.Updater('workingDIV','dspMainMenu.cfm?#session.UrlToken#',
{
method: 'get'
}
);
Event.observe(window, 'load', function() {
Event.observe('menuProfessionalOutreach', 'click',
addProfessionalOutreach);
});
}


/* actions */
function addProfessionalOutreach(event) {
new Ajax.Updater('workingDIV','dsp_addProfessionalOutreach.cfm?
#session.UrlToken#',
{
method: 'get'
}
);
}

cotents of dspMainMenu.cfm


<div id="menuProfessionalOutreachDIV">
<a href="#" id="menuProfessionalOutreach">
<img src="" title="Professional Outreach Image">
Professional Outreach
</a>
</div>


So what am I not doing right here?

I have a sneaky suspicion that it's something to do with the
dspMainMenu.cfm not being 'read into' the DOM?? Or evaluated into the
DOM?

Should I be using Ajax.Request instead? Ajax.Updater seemed cleaner
since the call to dspMainMenu.cfm was just being dumped into a DIV and
didn't need to do much.

Though maybe my events should be registered in the 'onSuccess'
function call of Ajax.Request...??

brentnicholas
01-22-2008, 10:19 PM
[QUOTE=brentnicholas;127460]

I was just messing around with seeing what runs and does not run in the scripts and found that if I add the 'alert()' below, the page works fine with no errors.

Intially I was getting an error at line 3818 - Object Required in the Prototype.js file. I assumed I was just defining my Event.observe incorrectly. Maybe this is a bug in Prototype? I'm still leaning towards me doing something wrong.

But this observation is interesting...



function showMainMenu()
{
new Ajax.Updater('workingDIV','dspMainMenu.cfm?#session.UrlToken#',
{
method: 'get'
}
);
Event.observe(window, 'load', function() {
alert('in here'); // adding this caused the page to start running fine
Event.observe('menuProfessionalOutreach', 'click',
addProfessionalOutreach);
});
}



cotents of dspMainMenu.cfm


<div id="menuProfessionalOutreachDIV">
<a href="#" id="menuProfessionalOutreach">
<img src="" title="Professional Outreach Image">
Professional Outreach
</a>
</div>

jscheuer1
01-22-2008, 10:41 PM
There are various ways to deal with this. You could have a document.onclick function that evaluates the id of the element clicked, walking up the DOM tree to the body tag. If it encounters certain id's along the way, certain actions could be performed. This approach bypasses 'observe'.

Another approach would be to start polling for the added elements with the id's in question at the same time that the imported content is requested, once they are a part of the DOM, 'observe' them.

I like my previous approach, it is simplest and cleanest, and requires no script tags in the external content. It does however add code to the markup that you apparently want to keep separate. However, the modularity isn't compromised. If, in the future, you want the division with the id:

menuTrainingProvidedDIV

to do something different, you need only edit the addTrainingProvided() function. You don't have to touch the markup ever again.