Member Avatar for diafol

Hi all, I'm a bit of a jobber with JS, so please excuse me.

I'm use prototype quite a lot for ajax calls, but have always used inline onclicks. I'm trying to be less obtrusive by creating event handlers/listeners.

I used to do this with the aid of pHp to place arguments into the function (usually via 'while loop'):

<li><a href="#" onclick="dofunction(arg1,arg2);">item 1</a></li>
<li><a href="#" onclick="dofunction(arg1,arg2);">item 2</a></li>
<li><a href="#" onclick="dofunction(arg1,arg2);">item 3</a></li>

At the moment I have this function:

Event.observe(window, 'load', function() {
  Event.observe('myid', 'click', runme);
});

to react to

<li id="myid">Click Me </li>

This is all well and good and it works - when I click the item the 'runme' function runs.

Can anyone tell me how I can get any list item in a particular list to run 'runme' (I don't want to use a unique id for each item). Also, and more importantly, where can I place the arguments (arg1, arg2) in the HTML so that they can be passed to a function? I will be creating the list dynamically from DB entries.

Thanks in advance.

Hi Ardav,

I'm not massively experienced in Prototype but I think I've worked something out. It may not be exactly what you want but it's a start.

Event.observe(window, 'load', function(){
  Event.observe(document.body, 'click', function(e){
    if( Event.element(e).args ){
      var args = Event.element(e).args.split('|');
	  var fn = args.shift();
	  window[fn](args.join('|'));
    }
  });
  Event.observe(document.body, 'mouseover', function(e){
    if( Event.element(e).args ){
      Event.element(e).style.cursor = 'hand';
    }
  });
});
function f1(args){
	args = args.split('|');
	alert("Function f1\narguments (" + args.join() + ')');
}
function f2(args){
	args = args.split('|');
	alert("Function f2\narguments (" + args.join() + ')');
}
function f3(args){
	args = args.split('|');
	alert("Function f3\narguments (" + args.join() + ')');
}
<ul>
<li args="f1|Item 1|a|b|c">List item 1</li>
<li args="f2|Item 2|d|e|f">List item 2</li>
<li args="f3|Item 3|g|h|i">List item 3</li>
</ul>

You'll see that I've put all the arguments for each <li> in the custom HTML attribute args with | as a separator. The observer fn checks for the presence of a non-null args attribute in the target <li> without checking the tagName or the <ul>'s className or anything. This means that the observer will work for elements other than <li> just by adding an args attribute in the HTML (or progammatically I suppose).

In the handler, the args string is split into an array of values. The first element is separated out and used as a function name (f1, f2 or f3) which is called with the remaining, re-joined values passed as a single argument. Functions f1, f2 and f3 are all near-identical. I've just done this to demonstrate that, if you wish, you can specify an eventual handler, rather than hard-coding runme , or whatever, in the anonymous observer.

Oh yes, there's also a mouseover handler to set the cursor to hand. Strangely it returns to arrow on its own in IE6 but I'm not sure this will happen in other browsers. Worth checking.

I think that's about it.

Airshow

commented: You've saved me a load of work (again!) - cheers +3
Member Avatar for diafol

That's fantastic Airshow. Really appreciate it - diolch yn fawr.

Member Avatar for diafol

Unfortunately, I can't get args to work. For some reason js won't recognize it. I'll try and use some other tag - perhaps the class tag can hold some data.

//EDIT
Yup, that worked! The cursor mouseover wasn't too fussed about it, but that's small potatoes. Thanks again.

Ardav, which browser are you using? I tested in IE6 (a daft choice I know).

Member Avatar for diafol

I used Chrome, FF, Opera, Safari and IE7. IE7 worked, but not the others. So for once, IE fared better than the rest. I bet I could get the others to work if I worked at it, but like I said, I don't really need this functionality as I will be trying to keep my clickable lists semantic by placing them within <a> tags, so hand cursor automatic.

I can now write unobtrusive code - no more onclick this and onclick that. Absolutely great. The only this is that my class attribute looks as though somebody with tourettes has had a go at it.

Ardav,

I'm sure I posted a further thought earlier but it seems to have disappeared - (or maybe a oz-mod has been in and messed things up). There's certainly something odd going on.

Anyways, the thought was to use Event.element(e).getAttribute('args') instead of Event.element(e).args (in three places) to pick up the custom tag. If it works in FF, then you can keep class "pollution free".

Airshow

Member Avatar for diafol

Awesome. The class tag is pretty trivial in the current list as all the CSS is controlled by ul id, but being able to use the args attribute would certainly be better. BTW, will XHTML fail validation due to custom attributes? Not that it's a major concern since in developing an admin area, not a public site.

Ardav,

Yes I think most validators generate a warning for custom attributes.

I've never tried it but I suppose you must be able to create your own XHTML schema (in the same way you can for XML) and invoke it in the doctype or thereabouts. Thus, you may be able to make your custom attributes "legal". So, if validation is an issue, this might worth exploring.

I'm sure some clever soul out there in Daniland will be able to advise - maybe the subject of a new topic.

Airshow

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.