PDA

View Full Version : [DHTML] Rainbow link on mouseOver



temp304
11-23-2007, 03:34 PM
1) CODE TITLE: Rainbow link on mouseOver

2) AUTHOR NAME/NOTES: Thái Cao Phong

3) DESCRIPTION: Implement this script into your web pages to make all links change color by themself on mouse over event. Colors defined by an array with hexadecimal value, clrArray, you can change and add colors easily. All you need to do is cope all JavaScript code and paste into your web pages, you should save them into a file for using this effect on many pages.

4) URL TO CODE: http://javascriptbank.com/javascript/run-script-rainbow-link-on-mouseover.html

or, ATTACHED BELOW (see #3 in guidelines below):

jscheuer1
11-23-2007, 05:09 PM
I think DD already has a script like this, not sure*. Anyways:



<script language=javascript>

has been deprecated in favor of the type attribute:


<script type="text/javascript">

Your code intentionally skips Opera, but could easily work in it, and uses browser sniffing rather than feature detection to decide its execution pathway.


* http://www.dynamicdrive.com/dynamicindex5/rainbow.htm
Which also has some problems, but does work in Opera, IE, FF, Safari (win).

Twey
11-23-2007, 06:06 PM
Blarg, I rewrote this whole thing and then closed my browser tab by accident. The code is horribly written (probably in the DD version as well). Here's v1v2:
<script type="text/javascript">
Array.prototype.filter = function(f) {
f = f || function(a) { return a; };

for(var i = 0, n = this.length, r = []; i < n; ++i)
if(f(this[i]))
r.push(this[i]);

return r;
};

var RainbowElements = {
classRegex: /rainbow\(([^\)]+)\)/,
init: function(elms) {
for(var i = 0, a = elms, m, n = a.length; i < n; ++i)
if(m = a[i].className.match(RainbowElements.classRegex))
RainbowElements.setup(a[i], m[1].split(/\s*,\s*/));
},
setup: function(el, colours) {
var
cptr = 0,
rh,
nextColour = function(el) {
el.style.color = colours[++cptr] || colours[cptr = 0];
},
resetColour = function(el) {
el.style.color = colours[cptr = 0];
};

el.onmouseover = function() {
rh = setInterval(function() { nextColour(this); }, 200);
};

el.onmouseout = function() {
resetColour(this);
clearInterval(rh);
};

resetColour(el);

el = null;
}
};

onload = function() { RainbowElements.init(document.links) };
</script>
<!-- ... -->
<a href="foo" class="rainbow(red, #ffa500, yellow, #0f0, blue, #4b0082, #ee82ee)">Bar</a>Untested.

jscheuer1
11-23-2007, 08:22 PM
Untested.

Unworking:


Error: RainbowLinks is not defined
Source File: file://localhost/C:/webwork2/test/twey_rainbow.htm
Line: 24


if(m = a[i].className.match(RainbowLinks.classRegex))

Twey
11-23-2007, 08:39 PM
Whoops! I generalised it and forgot to change the references. Edited.

jscheuer1
11-23-2007, 08:53 PM
I noticed that and fixed it myself, but then I got:


Error: el.style has no properties
Source File: file://localhost/C:/webwork2/test/twey_rainbow.htm
Line: 32


el.style.color = colours[++cptr] || colours[cptr = 0];

Which I am also now getting with your edited version (which, BTW you changed exactly as I had to fix the first error). Why not just debug the whole thing?

Twey
11-23-2007, 11:24 PM
I noticed that and fixed it myself, but then I got:Yep, I made another daft mistake: should look like this:
el.onmouseover = function() {
var me = this;
rh = setInterval(function() { nextColour(me); }, 100);
};After this modification it works, but I added some more features too.
Why not just debug the whole thing?Generally my code works first-time, and I've developed a habit of not actually testing it :p Nevertheless, I added some features and tested them fully this time:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Rainbow Text Demo Page</title>
<script type="text/javascript">
Array.prototype.filter = function(f) {
f = f || function(a) { return a; };

for(var i = 0, n = this.length, r = []; i < n; ++i)
if(f(this[i]))
r.push(this[i]);

return r;
};

var RainbowElements = {
classRegex: /rainbow\(([^\)]+)\)/,
init: function(elms) {
for(var i = arguments.length - 1; i >= 0; --i)
for(var a = arguments[i], j = a.length - 1, m; j >= 0; --j)
if(m = a[i].className.match(RainbowElements.classRegex))
RainbowElements.setup(a[j], m[1].split(/\s*,\s*/));
},
getNamedArg: function(lst, prop, def) {
for(var i = lst.length - 1; i >= 0; --i)
if(lst[i].indexOf(prop + ":") === 0)
return lst.splice(i, 1)[0].substr((prop + ":").length);

return def;
},
setup: function(el, colours) {
var
prop = RainbowElements.getNamedArg(colours, "property", "color"),
delay = RainbowElements.getNamedArg(colours, "delay", 100),
cptr = 0,
rh,
nextColour = function(el) {
el.style[prop] = colours[++cptr] || colours[cptr = 0];
},
resetColour = function(el) {
el.style[prop] = colours[cptr = 0];
};

el.onmouseover = function() {
var me = this;
rh = setInterval(function() { nextColour(me); }, delay);
};

el.onmouseout = function() {
resetColour(this);
clearInterval(rh);
};

resetColour(el);

el = null;
}
};

onload = function() { RainbowElements.init(document.links) };
</script>
</head>
<body>
<p>
<a
href="foo"
class="rainbow(delay:50, red, #ffa500, yellow, #0f0, blue, #4b0082, #ee82ee)">
Bar
</a>
</body>
</html>A class now contains a sequence of colours, but may also contain anywhere an argument:value pair. Two exist: delay and property. E.G., to have the background colour change colour instead of the foreground colour, we could write:
class="rainbow(red, lime, property:backgroundColor, blue)"Or, for a smooth fading effect:
class="rainbow(#00f, #20d, #40c, #60a, #808, #a06, #c04, #e02, #f00, #e02, #c40, #a60, #880, #6a0, #4c0, #2e0, #0f0, #0e2, #0c4, #0a6, #088, #06a, #04c, #02e, delay:50)"

ddadmin
11-24-2007, 01:20 AM
Yep, there is a script on DD similar to this (http://www.dynamicdrive.com/dynamicindex5/rainbow.htm) already. One of those 90's scripts that to be honest, I would have promptly dismissed if we met today. :)

jscheuer1
11-24-2007, 05:31 AM
Generally my code works first-time, and I've developed a habit of not actually testing it :p Nevertheless, I added some features and tested them fully this time

Something akin to working the NYT Sunday crossword in pen, eh? Anyways, adding features that require verbose inline code isn't generally the best way to go, and doesn't really make up for not proofreading the original effort. I'll give you a pass though because you did say that it wasn't tested.

But don't throw away your pencil just yet.


Yep, there is a script on DD similar to this (http://www.dynamicdrive.com/dynamicindex5/rainbow.htm) already. One of those 90's scripts that to be honest, I would have promptly dismissed if we met today. :)

At least that one, as I noted in my first post in this thread, works pretty well cross browser. It is (as I also noted) fairly atrociously coded, though somewhat understandably so, given when and for which browsers it was written.

Twey
11-24-2007, 09:23 AM
Anyways, adding features that require verbose inline code isn't generally the best way to goIt doesn't require verbose inline code at all. It uses classes to allow options to be set per element. This is by far preferable to having a global options set elsewhere, or even something like an ID/options hash, since it's easier to read all round. I suppose it could save some time to have a class/options hash, so I've implemented (http://www.twey.co.uk/files/rainbow.html) one of those (as well as giving some more subtle examples than an actual rainbow).
But don't throw away your pencil just yet.I also don't test because the majority of my code is just to demonstrate a technique, and could as easily be pseudo-code. You're right that I should test more than I do, though.

jscheuer1
11-24-2007, 04:04 PM
If you fix the error on line 23:


2e, delay:50, property:backgroundColor",

by getting rid of that extra comma, now you really have something! Just as a note, I didn't really inspect the code enough to see why that is an error, but it is something like the fact that one should never have a comma after the last property in an object, and almost always never, item in an array. FF (Konq perhaps as well, I have no idea), by the way forgives this, others do not.

Hey DD, how about upgrading the one in the library with (once fixed) Twey's?

Twey
11-24-2007, 04:56 PM
Whoops! It seems Konq does forgive the extra comma. I'd thought it wouldn't since Safari apparently doesn't. Oh well, fixed anyway. Opera is the only browser I know for sure doesn't tolerate extra commas in objects, but I hear Safari and IE don't either.
Just as a note, I didn't really inspect the code enough to see why that is an error, but it is something like the fact that one should never have a comma after the last property in an object, and almost always never, item in an array.Only the former. Extra commas in arrays have a special meaning: the omitted values are undefined (e.g. [1, 2, , 4] is equivalent to [1, 2, undefined, 4]). As such, the trailing comma in an array is, whilst completely useless (unspecified elements are undefined anyway), perfectly valid.

jscheuer1
11-24-2007, 05:17 PM
More 'problems' - Because the classes are being rewritten to suit your nomenclature without preserving the class name for styling purposes, the classes cannot be styled in a stylesheet, that could probably be easily changed by introducing a space after the actual class name and before all that other stuff you are appending to it, with appropriate adjustments to the processing code, if needed.

What's puzzling me is that if I change the page's background color, the bluish bg one seems to stop working. I made up a primary bg one, and that seemed unaffected. :confused:

Now about extra commas in arrays, yes its just undefined, but for all practical purposes, depending upon the rest of the code, that should never be done, as it makes the length property grow by one, often causing scripts to break. You are correct though, in and of itself, it doesn't make the parser barf in the same way that just reading an object with an extra comma does.

Twey
11-24-2007, 07:15 PM
More 'problems' - Because the classes are being rewritten to suit your nomenclature without preserving the class name for styling purposes, the classes cannot be styled in a stylesheet, that could probably be easily changed by introducing a space after the actual class name and before all that other stuff you are appending to it, with appropriate adjustments to the processing code, if needed.Whoops -- I did fix this earlier but it seems to have made its way back in. Mistaken undo, perhaps.
What's puzzling me is that if I change the page's background color, the bluish bg one seems to stop working. I made up a primary bg one, and that seemed unaffected.I think it's just hard to see. The effect is very faint, because blue contrasts with black quite a bit so it's not necessary to make it very heavy. Make it a little lighter:
'bluish-bg' : "property:backgroundColor, #000, #001, #002, #003, #004, #005, #006, #007, #008, #009, #00a, #009, #008, #007, #006, #005, #004, #003, #002, #001",
Now about extra commas in arrays, yes its just undefined, but for all practical purposes, depending upon the rest of the code, that should never be done, as it makes the length property grow by one, often causing scripts to break.It doesn't (at least in SpiderMonkey and KJS):
js> [1, 2, 3, 4, 5].length
5
js> [1, 2, 3, 4, 5, ].length
5although explicitly specifying undefined does:
js> [1, 2, 3, 4, 5, undefined].length
6As do extra commas:
js> [1, 2, 3, 4, 5, , ].length
6

jscheuer1
11-24-2007, 08:04 PM
<script type="text/javascript">
var t=[1,2,3];
var tc=[1,2,3,];
alert (t.length+' '+tc.length);
</script>

Gotta love IE:


3 4

Opera, FF, and Safari (win) all say 3 3.

I'm now not getting the bluish or ghostly bg changes at all, even with the default page. I think you misunderstood me, the bluish one was working with the default page, last time - only stopped working when I changed the page's bg color. Both times I took off my glasses and put my face right up to the screen, nothing.

Funning thing is, FF's DOM inspector shows the values changing. Now, suddenly, I'm just not sure - why not make the bg ones contrast enough for about anyone to be able to tell?

Twey
11-24-2007, 08:15 PM
why not make the bg ones contrast enough for about anyone to be able to tell?Because it doesn't look nearly as cool and the ones I have contrast nicely enough with the black :p Nevertheless, I've added some Very Definitely Blue/Green Background links.

jscheuer1
11-24-2007, 08:45 PM
Because it doesn't look nearly as cool and the ones I have contrast nicely enough with the black :p Nevertheless, I've added some Very Definitely Blue/Green Background links.

I thought it might be something like that however, on a laptop, the are way too cool (read absolute zero - dead). A middle ground would be good, I do see the high contrast ones as a bit much.

Also, there is a delay property, but it seems to be between cycles, smoothness depends upon the number of changes, perhaps a speed property could be added.

Twey
11-25-2007, 08:49 AM
Well, the demo page isn't of great importance. I'm sure if DD decides to feature it, he'll edit it anyway (aren't the DD demo pages white?).
Also, there is a delay property, but it seems to be between cycles, smoothness depends upon the number of changes, perhaps a speed property could be added.I'm not sure I understand you. Speed would just be another way of calculating the delay, unless you're talking about fading one colour to another programmatically? I was thinking of doing that, but the syntax would become much more complex.

jscheuer1
11-25-2007, 04:13 PM
You understand, I'm thinking of either generating intermediate stages or slowing the changes between the existing stages depending upon how many there are.

I think if this could all be worked out, DD might want it. His initial comment in this thread seemed to indicate that he wasn't interested in a rainbow clone though. So, if you get this thing whipped into a shape that you'd like to submit it as, I think a new thread and a title like:

Pulsing Links

would be in order.