Forum Moderators: open

Message Too Old, No Replies

Unobtrusive Javascript Rollover class

Changing references in a script from "id"s to "class"s

         

pinheadj

6:52 pm on Sep 14, 2005 (gmt 0)

10+ Year Member



I am trying to use a javascript that lets you create a rollover effect on images with a particular id, however I want it to use classes instead of ids (basically to create a series of images that all have rollovers but that all change to the same over image.

Unfortunately I'm fairly new at working with Javascript and my initial attempt at simply searching and replacing "id" with "class" in the javascript file didn't work out.

The following is the script in question ( "rollovers.js" ):


function Rollovers_swap(id){ // id to swap in an image, null to swap out
if (id!= null)
{
var image = document.images[id]
if (image == null) return


var newimage = this.images[id]
if (newimage == null) return


this.temp_img = image
this.temp_src = image.src


image.src = newimage.src
}
else
{
if ((this.temp_img!= null) && (this.temp_src!= null))
this.temp_img.src = this.temp_src


this.temp_img = null
this.temp_src = null
}
}


function Rollovers(image_list){
this.images = new Object()// Storage for swap-in images
this.Install = Rollovers_Install
this.swap = Rollovers_swap


// Storage for the current swap-out image
this.temp_img = null
this.temp_src = null


for (var i=0; i < image_list.length; i++) {
var id = image_list[i][0]
var src = image_list[i][1]


var image = new Image()
image.src = src
this.images[id] = image
}
}


function Rollovers_Install() {// Should be called after page is loaded
var _this = this
var swap_out = function(){_this.swap(null);}


var set = function (id){
var image = document.images[id]
if (image == null) return
image.onmouseover = function(){_this.swap(id);}
image.onmouseout = swap_out
}


for(var id in this.images) set(id);
}

This goes in the head of the page:


<script src="rollovers.js"></script>
<script language="JavaScript" type="text/JavaScript">
// Note, no "var" keyword, so "rollovers" is global
rollovers = new Rollovers([
["imagename", "image_1_over.gif"],
["anotherimagename", "image_2_over.gif"]
]);
</script>

...and lastly, the body:


<body onload="rollovers.Install();">
<img src="image_1.gif" id="imagename" />
<img src="image_2.gif" id="anotherimagename" />
</body>

What I would want in the body would be more like this:


<body onload="rollovers.Install();">
<img src="image_1.gif" class="imagename" />
<img src="image_2.gif" class="imagename" />
<img src="image_3.gif" class="imagename" />
<img src="image_4.gif" class="imagename" />
</body>

Any ideas on how I would need the change the javascript file to make this work?

Many thanks.

Bernard Marx

10:07 pm on Sep 14, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If you want a really "unobtrusive" roller set-up you can use CSS rollovers.
Meanwhile, if you don't feel like it (using links in IE etc). Then I have a far less obtrusive scripting option. The script is short, but technical, yet it's just a "plugin".

1) Wack in the script.
2) Give the required images a the className, "roll" (or "aclass roll" etc).
3) Use the suffix, "-roll" for the rollover image ("imageName-roll.gif").
- the exact extension can be configured in the script.


<img class="roll" src="somePath/animage.gif">
<img class="anyclass roll" src="someOtherPath/images/nuther.gif">

There is no onload initiation involved, as it relies on event bubbling instead.

Note that WebmasterWorld corrupts the ¦ symbol, which will need to be replaced in this code.
Hence...

/*--------------------------------------
Adds suffix to image name, deoending
on event type, and according to
config of doRoll.suffixSwitch.
(Can include mouseup¦down definitions)
---------------------------------------*/
function doRoll(image, eType)
{
image.src = image.src.replace(
doRoll.regExp,
'$1'+doRoll.suffixSwitch[eType]+'$2'
);
}

doRoll.regExp = /^(.*\/[^-]*)-?.*(\.[^\.]*$)/;
doRoll.suffixSwitch =
{
mouseover:'-over',
mouseout :''
}

document.onmouseover =
document.onmouseout = function(e)
{
/* XBrowser normalise */
e = e¦¦event;
elm = e.srcElement¦¦e.target;
/* reject elms with classNames not including 'roll' */
if (! /\broll\b/.test(elm.className) )
return;
doRoll(elm, e.type);
}

[edited by: jatar_k at 3:48 pm (utc) on Oct. 5, 2005]

Rambo Tribble

3:05 am on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I don't know, Bernard, there's a lot of overhead there just to get away with using bubbling to identify classes. How about something less taxing on the interpreter, like:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Untitled</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<style type="text/css">
.inOne{position:absolute;height:200px;width:400px;background:#edd;}
.inTwo{position:absolute;height:200px;width:400px;background:#dde;visibility:hidden;}
</style>
<script type="text/javascript">
window.onload=function(){
var divs=document.getElementsByTagName('div');
var divs_ln=divs.length;
for(var i=0;i<divs_ln;i++){
if(divs[i].className.indexOf('out')!=-1){
divs[i].onmouseover=swapOne;
divs[i].onmouseout=swapTwo;
}
}
}
function swapOne(){
var divs=this.getElementsByTagName('div');
divs[0].style.visibility="hidden";
divs[1].style.visibility="visible";
}
function swapTwo(){
var divs=this.getElementsByTagName('div');
divs[0].style.visibility="visible";
divs[1].style.visibility="hidden";
}
</script>
</head>
<body>
<br />
<div class="out">
<div class="inOne"></div>
<div class="inTwo"></div>
</div>
</body>
</html>

?

Bernard Marx

12:22 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nice to hear from you, Tribble, but are you daring to question my judgement?

Our current context involves images, which would add a little complication.
I was also trying to avoid all that

onload = function(){ grab all the elements and push event handlers on them }

..malarky. I'm starting to think of it as "brute force".

pinheadj was going admirably overboard with the object wrappers and closures, but it was a little sledgehammer to crack a nut. Your code certainly pairs down some unnecessaries, but you have to admit it will have to be developed to accomodate more than just 2 elements.

Pistols at dawn on the heath?

Rambo Tribble

12:59 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Judgement? My word! What possessed you to take on that impediment? I'll have none of it.

Images shouldn't require any more effort; either put them on the divs or collect and toggle them instead of the divs. The only trick is putting them in the "out" container. From the great container flows all.

My concern is the overhead you engender by having to run the script on every element in the document, on every move of the mouse.

Brute force? Simply think of as giving the interpreter something to do in those first moments while the user sits awestruck at the resplendence of your design.

I'd prefer Heath bars, noonish, on the Pistol (River. I'm a canoeist, remember.)

Rambo Tribble

1:39 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



By the by, I'd vote for the CSS approach, with a note declaring, "Best when not viewed with Microcruft products."

If, however, one has a client enthralled by that "market share" nonsense, there are "behaviors", (sorry, I forgot, better call it "behaviours" for you, Bernard) or simply placing the relevant code in conditional comments (a bit less arcane and opaque, in my estimation).

Leosghost

2:12 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I wanna know if you two can be booked for barmitzvahs..;)
Elegant solutions ..but CSS would be everso much easier if the siths would just co-operate.

Bernard Marx

2:55 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The CSS background shift has the potential to be the hands down winner.

- Can be applied without ref to image dimensions
- Easy to script a layer on top to effect mouse ups & downs.
+ No preload, of course

But those siths do bother me..

- Need to use a link. I don't know what accessibility experts say about using links on elements that may just be GUI buttons.
- The dreaded "flicker". It's only in "every visit" mode, but when it's on it's seriously bothersome (both for the user, and for the sanity of your server logs). The fixes I've seen recently are a) too fussy for me, and b) don't actually work properly (at least in my IE6).

I should mention that I have twice now lost an hour or so bug-tracing around:

#boo{ behaviour: url( colonialSpelling.htc )}

I gave up on behaviors in the end - something to do with asynchronicity.

Brute force? Simply think of as giving the interpreter something to do in those first moments while the user sits awestruck at the resplendence of your design.

I wish!

Sometimes, if there are enough elements requiring treatment, this process can leave enough time to become subliminally jaded. I'm looking for a happy medium here. A complicated onload enhancement process can be perceptible, yet so far, I have found that the bubbling approach, although it may be making the browser work harder, doesn't acually produce any noticeable unwanted effects. (Event capture is possibly better, and more widely applicable in Mozilla).

If you still hate the thought of it all this bullying of interpreter, I have some code that will get you going. I'll just have to dig it out and re-heat it for you.

Rambo Tribble

3:02 pm on Sep 16, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The bubbling approach probably won't be a problem, unless you have something else going on at the same time. Perhaps an animation, or such. Older, slower processors may be a bugaboo, as well, however. It would be so much easier if there were a getElementsByClassName(). Oh, well.

Please don't blame the spelling on the colonies, per se, but on the self-important jerk who decided to deprive the American people of the roots of their language (or is that Spanish, now?), Noah Webster.

visibility:hidden; also obviates the need for a separate preload, though everything must be loaded (or as Bob Dylan said, "Everybody must get stoned." Or, is that something different? You humans are so hard to keep up with.)

Rambo Tribble

1:45 am on Sep 17, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I can't speak for Bernard, but I happily do bars, though am not big on mitzvahs.

Siths, like Klingons, are both objectionable in demeanor and, often, distasteful in appearance (though Klingons, at least, are pleasantly hirsute). I tend to avoid both their bars and their mitzvahs.

If, Bernard, you are becoming jaded, it is probably because onload waits for every rutting little pixel of every rutting little image to be loaded before firing. Let me suggest including a final script tag, at the bottom of the body to initiate the handler assignments. That way the document's primary structure will be complete before the assignments occur. If you are concerned with derision from the herd of developers who mindlessly chant, "No script tags in the body!", simply that was once suggested as a best practice to them, allow me to assist:

Rambo Tribble

2:09 am on Sep 17, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Harrumph! Got cut off before I could finish editing that last bit. Here it is in its entirety:

If, Bernard, you are becoming jaded, it is probably because onload waits for every rutting little pixel of every rutting little image to be loaded before firing. Let me suggest including a final script tag, at the bottom of the body to call a function in the head, initiating the handler assignments. That way the document's primary structure will be complete before the assignments occur. If you are concerned with derision from the herd of developers who mindlessly chant, "No script tags in the body!", simply because that was once suggested as a best practice to them, allow me to assist:

Snoop Dogg be say, "Dat scrip' tag at da bottom o' da body be way fly, fo' shizzle, fo' shizzle!"

In two or three days the crawlers will have indexed that, it will spread across the net and in a week all your clients will be demanding that "fly scrip' tag".

No thanks are necessary.