onClick / onmouseover / onmouseout image gallery question

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
Working on updating my personal portfolio site. I generate a lot of content for the web but rarely do much in the way of javascript/html/etc. I am pretty bad at it.

screenshot:

16h29mc.jpg


I'm trying to setup a typical little gallery, with the navbar having the usual color changes (labled), and a large image that loads when the corresponding number-button is clicked.

The problem I'm having is that anytime I include onmouseout in the string of actions to set this up, it not only swaps the button back to the original (when the cursor is moved off the button), but the big image as well. I assume there's a better way to do this, but I don't know what it is and I'm failing at google.

Also - It would also be great if clicking the big image cycled to the next one (and the last back to the first) but it's not necessary.

Suggestions? what's the best strategy for simple galleries like this?
 

Ka0t1x

Golden Member
Jan 23, 2004
1,724
0
71
I believe there's an addon for JQuery that does just this, if not it may be easier with jQuery in general, but I don't know what you're currently using.
 

PhatoseAlpha

Platinum Member
Apr 10, 2005
2,131
21
81
Images do not change by themselves. If mouseout is changing an imaging, you have told it to do so, somehow.

What you're asking for isn't very complicated - a pair of arrays, a counter to which large image it's currently showing. But there's no chance we'll be able to solve it with what you've given us. Link?
 

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
Images do not change by themselves. If mouseout is changing an imaging, you have told it to do so, somehow.

What you're asking for isn't very complicated - a pair of arrays, a counter to which large image it's currently showing. But there's no chance we'll be able to solve it with what you've given us. Link?

I didn't post any code because I figured I was doing it wholly wrong. Apparently I was, and I need to look into how to use arrays/counter to do this. My attempts thus far involved a chain of onClick/onmouseover events, and trying to figure out how to make onmouseout apply only to the onmouseover events.

any good links of the basics of arrays/counters in JS?
 

Aluvus

Platinum Member
Apr 27, 2006
2,913
1
0
How is the "1 2 3 4 5" bar actually implemented? Is there any particular reason you can't just use the CSS a:hover pseudo-class?

I'm not clear on what "down" means. Visited? Left of the current item?
 

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
How is the "1 2 3 4 5" bar actually implemented? Is there any particular reason you can't just use the CSS a:hover pseudo-class?

I'm not clear on what "down" means. Visited? Left of the current item?

right now, 30x30 .gifs that swap in & out. I figured there was a way to do it with css, but assumed (perhaps incorrectly) that js would be easier.

'down' is the current image you're on. so when the gallery loads, 1 is gray. click on 3, then 3 is gray and 1 is brown (and the '3' large image loads). The blue mouseover happens regardless.
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,649
4,591
75
anytime I include onmouseout in the string of actions to set this up, it not only swaps the button back to the original (when the cursor is moved off the button), but the big image as well.
Somehow you must have included code to set the large image in the function called from onmouseout.

The problem with a:hover is that it only affects the link and its contents.
 

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
Ok, got a chance to get into this again, I've been looking through some example javascript galleries, and I think I have a decent idea of how this will work.

One question I'm having trouble finding any examples for - for the array holding the "1 2 3 4 5 6" images, what's the best way to structure that, given that each number has three states (normal, down, hover)?
 

PhatoseAlpha

Platinum Member
Apr 10, 2005
2,131
21
81
If the only thing changing on the selections are borders, then you should really only need one array - the one holding the urls of the large images. If basic old html square colored borders are good enough, then that's all you actually need. If they aren't, then efficiency requires some extra information, along the the lines of Are all the button the same size, and is the selected, hover and unselected border the same on all of them?

Assuming that square colored backgrounds are good enough, I'd store *only* the value of the currently selected button, and use some html trickery to handle mouseovers entirely separately. By having a border div, then another div of the exact same size and position inside of it, you can use the outer level for selected/deselected, and use the inner for hovering. The trick is to make the outer the color for selected/unselected, and the inner opaque and colored when mouseovered and transparent when not. Saves you the trouble of having to keep track of mouseovers, and making comparisons to the currently selected button when changing back.

For example (excuse the inline stylesheet and javascript), with 3 buttons, each image 50x50 with a 2 pixel border:

Code:
<div id='ButtonOuter1' class='ButtonOuter'>
<div id='ButtonInner1' class='ButtonInner' onmouseover='MousedOver(1)' onmouseout='MousedOut(1)' onClick='Select(1)'>
<img src='URLtoImage1' class='ButtonImage'>
</div>
</div>

<div id='ButtonOuter2' class='ButtonOuter'>
<div id='ButtonInner2' class='ButtonInner' onmouseover='MousedOver(2)' onmouseout='MousedOut(2)' onClick='Select(2)'>
<img src='URLtoImage1' class='ButtonImage'>
</div>
</div>

<div id='ButtonOuter3' class='ButtonOuter'>
<div id='ButtonInner3' class='ButtonInner' onmouseover='MousedOver(3)' onmouseout='MousedOut(3)' onClick='Select(3)'>
<img src='URLtoImage1' class='ButtonImage'>
</div>
</div>

<img id='BigImage' src='DefaultImage' onClick='nextBigImage()'>

<style>
.ButtonOuter {width: 54px; height: 54px; position: relative; background-color: black;}
.ButtonInner {width: 54px; height: 54px; position: absolute; top: 0px; left: 0px; background-color: transparent;}
.ButtonImage {width: 50px; height: 50px; position: absolute; top: 2px; left: 2px;}
</style>
<script>
var SelectedImage = 1;
var BigImages = new Array();
BigImages[1] = "URLofBigImage1";
BigImages[2] = "URLofBigImage2";
BigImages[3] = "URLofBigImage3";
var NumberofImages = 3;

function MousedOver(index)
{
document.getElementById("ButtonInner" + index).style.backgroundColor = 'blue';
}
function MousedOut(index)
{
document.getElementById("ButtonInner" + index).style.backgroundColor = 'transparent';
}

function Select(index)
{
document.getElementById("ButtonOuter" + SelectedImage).style.backgroundColor = 'black';
document.getElementById("ButtonOuter" + index).style.backgroundColor = 'gray';
document.getElementById("BigImage").src = BigImages[index];
SelectedImage = index;
}

function nextBigImage()
{
var new = SelectedImage + 1;
if (new > NumberofImages)
  {new = 1;}
Select(new);

}
</script>

Explanations: As mentioned, we use a transparent or blue div to function as a mousedover border(or not). We only keep track of the currently selected image, and when a new one is changed the current one's selected/unselected color is changed back to normal, the new one is changed to active, the image changes and we update which one is selected. On clicking the big image, it adds one to the current index, rolls back around to 1 if it's at the end, then acts like you clicked that image.


If you need image borders, then it's a bit more complicated. If you have different sized images, it's more complicated. If your borders are different for each image, then it's a bunch more complicated. But if not, this should work after the appropriate cleanup to fit in your page.
 

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
If the only thing changing on the selections are borders, then you should really only need one array - the one holding the urls of the large images. If basic old html square colored borders are good enough, then that's all you actually need. If they aren't, then efficiency requires some extra information, along the the lines of Are all the button the same size, and is the selected, hover and unselected border the same on all of them?

Assuming that square colored backgrounds are good enough, I'd store *only* the value of the currently selected button, and use some html trickery to handle mouseovers entirely separately. By having a border div, then another div of the exact same size and position inside of it, you can use the outer level for selected/deselected, and use the inner for hovering. The trick is to make the outer the color for selected/unselected, and the inner opaque and colored when mouseovered and transparent when not. Saves you the trouble of having to keep track of mouseovers, and making comparisons to the currently selected button when changing back.

For example (excuse the inline stylesheet and javascript), with 3 buttons, each image 50x50 with a 2 pixel border:

Hey, cool - thank you. I like this approach, and I think I follow everything you're doing, but it's late and in my quick test I managed to bork it so that none of the mouseover /click actions work. I'm sure I just overlooked something simple.

I'll retire for tonight and go over it again tomorrow, posting just in case anyone feels like pointing out my idiocy for me.


Code:
<html>
<head>
<title>Image Slideshow test</title>

<style>
.ButtonOuter {width: 30px; height: 30px; position: relative; background-color: 3E1B08;}
.ButtonInner {width: 30px; height: 30px; position: absolute; top: 0px; left: 0px; background-color: transparent;}
.ButtonImage {width: 22px; height: 22px; position: absolute; top: 4px; left: 4px;}
</style>

<script>
var SelectedImage = 1;
var BigImages = new Array();
BigImages[1] = "../../images/GD1.jpg";
BigImages[2] = "../../images/GD2.jpg";
BigImages[3] = "../../images/GD3.jpg";
var NumberofImages = 3;

function MousedOver(index)
{
document.getElementById("ButtonInner" + index).style.backgroundColor = '62AFCE';
}
function MousedOut(index)
{
document.getElementById("ButtonInner" + index).style.backgroundColor = 'transparent';
}

function Select(index)
{
document.getElementById("ButtonOuter" + SelectedImage).style.backgroundColor = '3E1B08';
document.getElementById("ButtonOuter" + index).style.backgroundColor = '898989';
document.getElementById("BigImage").src = BigImages[index];
SelectedImage = index;
}

function nextBigImage()
{
var new = SelectedImage + 1;
if (new > NumberofImages)
  {new = 1;}
Select(new);

}
</script>
</head>
<body>

<div id='ButtonOuter1' class='ButtonOuter'>
<div id='ButtonInner1' class='ButtonInner' onmouseover='MousedOver(1)' onmouseout='MousedOut(1)' onClick='Select(1)'>
<img src='../../images/num1.gif' class='ButtonImage'>
</div>
</div>

<div id='ButtonOuter2' class='ButtonOuter'>
<div id='ButtonInner2' class='ButtonInner' onmouseover='MousedOver(2)' onmouseout='MousedOut(2)' onClick='Select(2)'>
<img src='../../images/num2.gif' class='ButtonImage'>
</div>
</div>

<div id='ButtonOuter3' class='ButtonOuter'>
<div id='ButtonInner3' class='ButtonInner' onmouseover='MousedOver(3)' onmouseout='MousedOut(3)' onClick='Select(3)'>
<img src='../../images/num3.gif' class='ButtonImage'>
</div>
</div>

<img id='BigImage' src='../../images/GD1.jpg' width="976" height="550" onClick='nextBigImage()'>


</body>
</html>
 

PhatoseAlpha

Platinum Member
Apr 10, 2005
2,131
21
81
Bah, my fault. Somehow I managed to forget that new is a reserved keyword, so the nextBigImage function chokes the parser and kills the entire script. replace

Code:
function nextBigImage()
{
var new = SelectedImage + 1;
if (new > NumberofImages)
  {new = 1;}
Select(new);

}

with

Code:
function nextBigImage()
{
var newSelected= SelectedImage + 1;
if (newSelected> NumberofImages)
  {newSelected= 1;}
Select(newSelected);

}
 

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
Bah, my fault. Somehow I managed to forget that new is a reserved keyword, so the nextBigImage function chokes the parser and kills the entire script. replace

Code:
function nextBigImage()
{
var new = SelectedImage + 1;
if (new > NumberofImages)
  {new = 1;}
Select(new);

}

with

Code:
function nextBigImage()
{
var newSelected= SelectedImage + 1;
if (newSelected> NumberofImages)
  {newSelected= 1;}
Select(newSelected);

}

awesome, this works great. Thanks so much for pointing out a clever solution.

one final oddity: when I pasted the pieces into their respective existing site files, the border-related functions stoped working. I went through, copying pieces bit by bit into the working test file, until it broke. The culprit? the header, written by dreamweaver 5-6 years ago when I first wanted my own website:

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>

I can only assume that that includes an older/different set of standards that confused the browser. So I guess the question is, what should I include at the very top of the file?
 

CoinOperatedBoy

Golden Member
Dec 11, 2008
1,809
0
76
There's nothing wrong with that doctype. If you're using a valid doctype declaration, then it's the code that's broken. In what browser does this break?
 
Last edited:

PhatoseAlpha

Platinum Member
Apr 10, 2005
2,131
21
81
He's right, there's nothing wrong with the doctype per se. But minor difference between HTML and XHTML can break things. Probably a requirement for end tags, or a case sensitivity problem. I'll have to take another look.

EDIT:
Ah, Ok, I see it. 2 things. First, all the places it sets colors needs to have the # in front of the hex codes. Looks like I left them off, and strict compliance mode doesn't care for that. Secondly, images in xhtml need to have the self closing tag / added.

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Image Slideshow test</title>

<style>
.ButtonOuter {width: 30px; height: 30px; position: relative; background-color: #3E1B08;}
.ButtonInner {width: 30px; height: 30px; position: absolute; top: 0px; left: 0px; background-color: transparent;}
.ButtonImage {width: 22px; height: 22px; position: absolute; top: 4px; left: 4px;}
</style>


</head>
<body>

<div id='ButtonOuter1' class='ButtonOuter'>
<div id='ButtonInner1' class='ButtonInner' onmouseover='MousedOver(1);' onmouseout='MousedOut(1);' onClick='Select(1);'>
<img src='../../images/num1.gif' class='ButtonImage' />
</div>
</div>

<div id='ButtonOuter2' class='ButtonOuter'>
<div id='ButtonInner2' class='ButtonInner' onmouseover='MousedOver(2);' onmouseout='MousedOut(2);' onClick='Select(2);'>
<img src='../../images/num2.gif' class='ButtonImage' />
</div>
</div>

<div id='ButtonOuter3' class='ButtonOuter'>
<div id='ButtonInner3' class='ButtonInner' onmouseover='MousedOver(3);' onmouseout='MousedOut(3);' onClick='Select(3);'>
<img src='../../images/num3.gif' class='ButtonImage' />
</div>
</div>

<img id='BigImage' src='../../images/GD1.jpg' width="976" height="550" onClick='nextBigImage()' />

<script>
var SelectedImage = 1;
var BigImages = new Array();
BigImages[1] = "../../images/GD1.jpg";
BigImages[2] = "../../images/GD2.jpg";
BigImages[3] = "../../images/GD3.jpg";
var NumberofImages = 3;

function MousedOver(index)
{
document.getElementById("ButtonInner" + index).style.backgroundColor = '#62AFCE';
}
function MousedOut(index)
{
document.getElementById("ButtonInner" + index).style.backgroundColor = 'transparent';
}

function Select(index)
{
document.getElementById("ButtonOuter" + SelectedImage).style.backgroundColor = '#3E1B08';
document.getElementById("ButtonOuter" + index).style.backgroundColor = '#898989';
document.getElementById("BigImage").src = BigImages[index];
SelectedImage = index;
}

function nextBigImage()
{
var newSelected = SelectedImage + 1;
if (newSelected > NumberofImages)
  {newSelected = 1;}
Select(newSelected);

}
</script>
</body>
</html>
 
Last edited:

Dubb

Platinum Member
Mar 25, 2003
2,495
0
0
Ah, got it.

Rolling along now, not much more to do. In the future I may look into ways to have the initial large image be half-width, with some text on the other half - so if anyone has suggestions about the best strategies for that, I'm all ears.

Thanks again for the help.