Javascript help

Soldato
Joined
2 Dec 2005
Posts
5,514
Location
Herts
Don't know anything about javascript really so need a bit of help. This is for the ocuk collage (link in sig). At the moment it uses php to read all the images and echos them. Now what I want is to use the method at http://www.devarticles.com/c/a/JavaScript/Creating-PopUp-Notes-with-CSS-and-JavaScript-Part-I/2/ to have little floaty notes. The problem is in the javascript. I don't know how to make it recursive for every element in the array. The js is:
Code:
createNotes=function(){
            showNote=function(){
                        // gets note1 element
                        var note[COLOR=Yellow]1[/COLOR]=document.getElementById('note[COLOR=Yellow]1[/COLOR]');
                        // assigns X,Y mouse coordinates to 'note1' element
                        note[COLOR=Yellow]1[/COLOR].style.left=event.clientX;
                        note[COLOR=Yellow]1[/COLOR].style.top=event.clientY;
                        // makes note1 element visible
                        note[COLOR=Yellow]1[/COLOR].style.visibility='visible';
            }

            hideNote=function(){
                        // gets note1 element
                        var note[COLOR=Yellow]1[/COLOR]=document.getElementById('note[COLOR=Yellow]1[/COLOR]');
                        // hides note1 element
                        note[COLOR=Yellow]1[/COLOR].style.visibility='hidden';
            }

            var a[COLOR=Yellow]1[/COLOR]=document.getElementById('a[COLOR=Yellow]1[/COLOR]');
            // shows note1 element when mouse is over
            a[COLOR=Yellow]1[/COLOR].onmousemove=showNote;
            // hides note element when mouse is out 
            a[COLOR=Yellow]1[/COLOR].onmouseout=hideNote;
}

// execute code once page is loaded
onload=createNotes;
Seems to me that all the yellow numbers need to increment up to the number of pictures in the collage.

note1, note2, note3... are unique id's of divs with the persons username in it. a1, a2, a3... are unique ids of pics corresponding to the note. So you mouse over a pic and it does the javascript for that particular picture/note pair, displaying the username when moused over the relevant pic.

Is this possible?
 
Some more info in case it helps.

There's a foreach in the php. The image is echoed with an id
Code:
echo "<img id='a$id' src='$pic' alt='$user' ";
And the note underneath with the same $id
Code:
echo ("<div id='note$id' class='note'>$user</div>");
So it looks to me like the js needs to have a function for every img/note pair? Or can it be done more generally with only one function? Presumably by passing the id to the js when the image is moused over which then reveals/hides accordingly?
 
Code:
var divs = document.getElementsByTagName("div");

for ( var i = 0; i < divs.length; i++ ) {
    if ( divs[i].className == "note" ) {
        // divs[i] is a note, you can do stuff with it like:
        // divs[i].style.left = event.clientX;
    }
}

If you want to do something with all the images, give them a class and use the same as above (replacing "div" with "img" and "note" with the new class, naturally).
 
Good thinking rob, excellent.

I've got this now
Code:
createNotes=function(){
var divs = document.getElementsByTagName("div");
var imgs = document.getElementsByTagName("img");

for ( var i = 1; i < imgs.length+1; i++ ) {

	imgs[i].onmousemove=function(){
                        divs[i].style.left=event.clientX;
                        divs[i].style.top=event.clientY;
                        divs[i].style.visibility='visible';
            }

    imgs[i].onmouseout=function(){
                        divs[i].style.visibility='hidden';
			}

}
}
onload=createNotes;
It works for all images but only displays the last div in the list. Why? Maybe the functions must be unique? Is not being passed to the function?
 
joeyjojo said:
Good thinking rob, excellent.

I've got this now
Code:
createNotes=function(){
var divs = document.getElementsByTagName("div");
var imgs = document.getElementsByTagName("img");

for ( var i = 1; i < imgs.length+1; i++ ) {

	imgs[i].onmousemove=function(){
                        divs[i].style.left=event.clientX;
                        divs[i].style.top=event.clientY;
                        divs[i].style.visibility='visible';
            }

    imgs[i].onmouseout=function(){
                        divs[i].style.visibility='hidden';
			}

}
}
onload=createNotes;
It works for all images but only displays the last div in the list. Why? Maybe the functions must be unique? Is not being passed to the function?



for starters your for loop is wrong, it should be

for ( var i = 1; i < imgs.length; i++ ) {

the "+1" is not necessery. also you can only use left, and right when the position is relative or absolute
 
The i=1 and +1 sort out the header from being included as it is the 0th element in the array.

The actual functions are sound. The problem is making the functions work. As above, they are all associated a note, but they all get the last note in the set, not their partner note.
 
joeyjojo said:
The i=1 and +1 sort out the header from being included as it is the 0th element in the array.

The actual functions are sound. The problem is making the functions work. As above, they are all associated a note, but they all get the last note in the set, not their partner note.

sorry i didnt notice.

i think you should loop through the Divs, and inside the function you can use

this.style... etc instead of div.style..
 
Even if you're starting at image 1 instead of image 0, there are still only `images.length - 1` images in the array: you're going to get an index out of bounds error if you try and access `images[images.length]`, which you'll do on the last iteration of your loop.

joeyjojo said:
It works for all images but only displays the last div in the list. Why? Maybe the functions must be unique? Is i not being passed to the function?

`i` isn't in scope.

Easiest solution: make `i` and `divs` global:

Code:
var divs, imgs, i;
createNotes=function(){
	divs = document.getElementsByTagName("div");
	imgs = document.getElementsByTagName("img");
	for ( i = 1; i < imgs.length; i++ ) {
		imgs[i].onmousemove = function() {
			divs[i].style.left = event.clientX;
			divs[i].style.top = event.clientY;
			divs[i].style.visibility = 'visible';
		}

		imgs[i].onmouseout = function() {
			divs[i].style.visibility = 'hidden';
		}
	}
}
onload = createNotes;

Untested but I'm sure it'll work :)
 
No dice :( Same problem in that it displays the last note for all of them.

Code:
var divs, imgs, i;
createNotes=function(){
	divs = document.getElementsByTagName("div");
	imgs = document.getElementsByTagName("img");
	for ( i = 0; i < imgs.length; i++ ) {
		function showNote[i]() {
			divs[i].style.left = event.clientX;
			divs[i].style.top = event.clientY;
			divs[i].style.visibility = 'visible';
		}

		function hideNote[i]() {
			divs[i].style.visibility = 'hidden';	
		}
	imgs[i].onmousemove=showNote[i];
	imgs[i].onmouseout=hideNote[i];
	}
}
onload = createNotes;
Is equivalent I think but no good either? Doesn't show anything at all. Thanks for the help thus far lets try and crack this mate :)
 
Could you post all your source up of what you have so far (the image generating PHP, CSS etc)? It'll be easier to take a look that way :)

/ mail me if you like.
 
Yeah no worries getting a bit confusing aint it :)

index.php
Code:
<html>
<head><title>OcUK Collage</title>
<link href="styles.css" rel="stylesheet" type="text/css" />
<script language="javascript" src="popup.js" type="text/javascript"></script>
<?php
$cols = $_GET["cols"];
if(!$cols){
$cols = 10;
}
if($cols > 30){
$cols = 30;
}
$width = 75*$cols;
?>
</head>
<body>

<div id="container">
<img src="header.png">
<form method="get">
  <label>Columns
  <input name="cols" type="text" value="<?php echo $cols ?>" size="4" maxlength="3">
  </label>
  <label>User?
  <input name="username" type="text" id="username" size="20" value="<?php echo $_GET['username'] ?>">
  </label>
  <input type="submit" value="Go!">
  
</form>
<p><a href="list.php">See this in list form</a> | <a href="images/upload.php">Submit your mugshot </a> | <a href="report.html">Report a bad picture</a></p>
<p>Currently <?php echo count(glob('images/*.{jpg,JPG}', GLOB_BRACE)) ?> members have joined the collage.
<div id="collage" style="width:<?php echo $width ?>px;">
<?php
$id = 1;
$pictures = glob('images/*.{jpg,JPG}', GLOB_BRACE);
shuffle($pictures);
foreach ($pictures as $pic) {
$user = substr($pic, 7, -4);
$get = strtolower($_GET['username']);
echo "<img src='$pic' alt='$user' ";
if (substr($get, -1, 1)=="*"){
	if (substr($get, 0, -1) == strtolower(substr($user, 0, (strlen(substr($get, 0, -1)))))){
		echo ("width='67' height='92' style='border:4px solid #F5D61F;'>");
	}else{
		echo ("width='75' height='100'>");
	}
	}
else
	{
	if ($get == strtolower($user)){
		echo ("width='67' height='92' style='border:4px solid #F5D61F;'>");
	}else{
		echo ("width='75' height='100'>");
	}
	}
echo ("<div class='note'>$user</div>");
$id++;
}
?>
</div>
</div>
</body>
</html>

popup.js
Code:
var divs, imgs, i;
createNotes=function(){
	divs = document.getElementsByTagName("div");
	imgs = document.getElementsByTagName("img");
	for ( i = 0; i < imgs.length; i++ ) {
		function showNote[i]() {
			divs[i].style.left = event.clientX;
			divs[i].style.top = event.clientY;
			divs[i].style.visibility = 'visible';
		}

		function hideNote[i]() {
			divs[i].style.visibility = 'hidden';	
		}
	imgs[i].onmousemove=showNote[i];
	imgs[i].onmouseout=hideNote[i];
	}
}
onload = createNotes;

styles.css doesn't have anything of interest just some styling for the note I suppose, which is:
Code:
.note {
position: absolute;
top: 0px;
left: 0px;
background: #ffc;
padding: 10px;
border: 1px solid #000;
z-index: 1;
visibility: hidden;
font: bold 11px "Verdana", Arial, Helvetica, sans-serif;
color: #000;
}

Thanks for any help :)
 
Right. I hate javascript. :)


js:
Code:
function showNote(i) {
	var div = document.getElementsByTagName("div");
	
	div[i+1].style.display = "block";
	
// causing problems in firefox for me	
//	div[i+1].style.left = event.clientX;
//	div[i+1].style.top = event.clientY;
	
	div[i+1].style.visibility = 'visible';
}

function hideNote(i) {
	var div = document.getElementsByTagName("div");
	div[i+1].style.visibility = 'hidden';
}

function hideNotes()
{
	var divs = document.getElementsByTagName("div");
	var i;
	
	for ( i = 1; i < divs.length; i++ ) {
		
		if ( divs[i].className == "note" )
		{
			divs[i].style.visibility = 'hidden';		
		}
	}
}



index:
Code:
<html>
<head><title>OcUK Collage</title>
<link href="styles.css" rel="stylesheet" type="text/css" />
<script language="javascript" src="popup.js" type="text/javascript"></script>
<?php
$cols = $_GET["cols"];
if(!$cols){
$cols = 10;
}
if($cols > 30){
$cols = 30;
}
$width = 75*$cols;
?>
</head>
<body onload="hideNotes()">

<div id="container">
<img src="header.png">
<form method="get">
  <label>Columns
  <input name="cols" type="text" value="<?php echo $cols ?>" size="4" maxlength="3">
  </label>
  <label>User?
  <input name="username" type="text" id="username" size="20" value="<?php echo $_GET['username'] ?>">
  </label>
  <input type="submit" value="Go!">
  
</form>
<p><a href="list.php">See this in list form</a> | <a href="images/upload.php">Submit your mugshot </a> | <a href="report.html">Report a bad picture</a></p>
<p>Currently <?php echo count(glob('images/*.{jpg,JPG}', GLOB_BRACE)) ?> members have joined the collage.
<div id="collage" style="width:<?php echo $width ?>px;">
<?php
$id = 1;
$pictures = glob('images/*.{jpg,JPG}', GLOB_BRACE);
shuffle($pictures);
foreach ($pictures as $pic) {
$user = substr($pic, 7, -4);
$get = strtolower($_GET['username']);
echo "\n<img src='$pic' alt='$user' onmouseover=\"showNote($id)\" onmouseout=\"hideNote($id)\" ";
if (substr($get, -1, 1)=="*"){
	if (substr($get, 0, -1) == strtolower(substr($user, 0, (strlen(substr($get, 0, -1)))))){
		echo ("width='67' height='92' style='border:4px solid #F5D61F;'>");
	}else{
		echo ("width='75' height='100'>");
	}
	}
else
	{
	if ($get == strtolower($user)){
		echo ("width='67' height='92' style='border:4px solid #F5D61F;'>");
	}else{
		echo ("width='75' height='100'>");
	}
	}
echo ("<div class='note'>$user</div>");
$id++;
}
?>
</div>
</div>
</body>
</html>


Works in IE/Firefox for me :)
 
Nice, knew there was a way to pass i to the function but couldn't get it right. Good work mate thanks, and thanks to rob for his help throughout. :)

The div appears at the left of the row, looks pretty good actually and I prefer it to appearing at the mouse co-ords. Worked out nicely.

Uploading it in a bit :cool:
 
Sounds good, I'll check it out later on (I'm just about to go to bed :o).

As I didn't have the full CSS (and the link in your sig was down) all my images were displayed one-per-line so I didn't know about the left side thing :).

If you uncomment this I found that Firefox wouldn't like any of the rollovers, I didn't look into it but I guess Firefox has a different way of setting/getting coords.

// div[i+1].style.left = event.clientX;
// div[i+1].style.top = event.clientY;


Also, it may be worth giving each note div its own id, then using document.getElementById() rather than grabbing all divs. It's probably more efficient too.
 
Back
Top Bottom