Forum Moderators: open

Message Too Old, No Replies

Creating Links Dynamically while passing Array Parameters

A previous discussion has lead to a new topic

         

Conscientious Reject

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

10+ Year Member



I had started a topic on creating and calling dynamic menus (http://www.webmasterworld.com/forum91/4371.htm) once before, but have been lead into a new topic.

essentially this works so far.

function addRow() {
var body = document.getElementById('displayButton') .getElementsByTagName('tbody')[0];
var row = body.appendChild( document.createElement('tr'));
for (var i=0, cell; i < arguments.length; i++) {
cell = document.createElement("td");
row.appendChild(cell);
cell.appendChild(document.createTextNode( arguments[i]) ); }
}

it renders something comparable to this:

<table width=375 id="displayButton">
<tr><td>pic1</td><td>pic2</td></tr>
</table>

<comment> that is ofcourse, if the addRow() function passed pic1 and pic2 as a parameters. Like addRow(pic1, pic2).</comment>

But what I want is a way to render something comparable to this.

<table width=375 id="displayButton">
<tr><td name="gallery_Item[0]" onclick="picture.src=display[0]; changeDescript(myPic[0], myPic_descript[0])">pic1</td>
<td name="gallery_Item[1]" onclick="picture.src=display[1]; changeDescript(myPic[1], myPic_descript[1])">pic1</td>
</table>

What I need to know is how to write the following javascript properly:

function addRow() {
var body = document.getElementById('displayButton') .getElementsByTagName('tbody')[0];
var row = body.appendChild( document.createElement('tr'));
for (var i=0, cell; i < arguments.length; i++) {
cell = document.createElement("td");

/*This is part I am having a hard time with. I need the table cell that has just been rendered to have it's own functionality. Just as any button is an average online displays an online buttons that changes the image on display. This button would actually change it's value and variables based on the arguements passed, and the other functions accessed by the seperate venue button in the html itself. That's why I need need the array values to be passed into the onClick function*/
cell.onClick = "picture.src='display[" + i + "]'; changeDescript(myPic_name[" + i + "], myPic_descript[" + i + "])";

row.appendChild(cell);
cell.appendChild(document.createTextNode( arguments[i]) ); }
}

FYI:
where

display[0] = beforeLunch_pic.src;
myPic_name[0] = beforeBrunch;
myPic_descript[0] = beforeBrunch_describe;

now the arrays change once the user has opted to change the gallery venue.

display[0] = shadow_pic.src;
myPic_name[0] = afistFull;
myPic_descript[0] = afistFull_describe;

ANY HELP WOULD BE GREATLY APPRECIATED.

Bernard Marx

7:18 pm on Sep 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The first thing is that you can't add event handlers (in a script) doing this:

elm.onclick = "some js code";

You can do this using

setAttribute
, but it doesn't work in IE - so that's a loser from the start.

There is

addEventListener
(W3C)¦
attachEvent
(IE), but that adds more complication.

At this point, I suggest you have a read of this recent thread:

[webmasterworld.com...]

Inside you will find a similar question - one step on, and a common (and slightly weird) pitfall. You should also find a couple of solutions. At the end, I mention that I'd use event bubbling for this (saves you having to add event handlers at all), but since I don't know all the ins & outs of your particular arrangement I won't push for that right now.

See how you get on.

Conscientious Reject

8:19 pm on Sep 19, 2005 (gmt 0)

10+ Year Member



Thanks for filling me in. That's kinda what I was thinking. I have been doing some research on this, and I can see where people have done this using an entirly different approach. I may have to rebuild it. Still, I will read your thread and let you know. Also, I just wanted to let you know that I appreciate all of your help on these issues.

Conscientious Reject

9:45 pm on Sep 19, 2005 (gmt 0)

10+ Year Member



Wow! I often hear about closures but really never got a concise ansewer. I think I get it now. Still I am wondering what you meant by:

"Personally, if I were dealing with a good deal of objects, I'd find some other means. If it were a table for instance, I certainly wouldn't waste time attaching event handlers to every single cell, but catch any required cell events on the TABLE element as they bubble past it, then query them about the source."

okay ... okay ...

what's this look like. I keep getting an alert that says that there is an unterminated string constant, but I can't find where I would be missing any quotation marks. Here's what I got thus far.

/*this function is called by :
<A onClick="changeUpGallery(portfolio);addRow('pic1', 'pic2', 'pic3', 'pic4')
" style="cursor: hand;">Column #1, </A>,<A onClick="... >Column #2</A>, etc., in my html.
*/
//
function addRow() {
var body = document.getElementById('displayButton')
.getElementsByTagName('tbody')[0];
var row = body.appendChild( document.createElement('tr'));
for (var i=0, cell; i < arguments.length; i++) {
cell = document.createElement("td");
row.appendChild(cell);
cell.appendChild(document.createTextNode( arguments[i]) );
//
/*Here I want the cell to call the changeDescript function when clicked*/
//
cell.onClick = changeDescript;

}
}

/*this function will be called when the "cell" is clicked using array values. For example:
display[0] = beforeLunch_pic.src;
myPic_name[0] = beforeBrunch;
myPic_descript[0] = beforeBrunch_describe; Please notice that I have kept this function inside the addRow() function.
*/
//
function changeDescript() {

/* I want the gallery button that is built to change up the image. This should be comparable to: <td onClick="picture.src=display[i];">pic1</td>*/
//
document.picture.src=display[i];

/*this would update the imgName, imgDescript font nodes.*/
//
var imgName = document.getElementById("imgName");
imgName.firstChild.nodeValue = myPic_name[i];
var imgDescript = document.getElementById("imgDescript");
imgDescript.firstChild.nodeValue = myPic_descript[i];

}

}

Conscientious Reject

9:57 pm on Sep 19, 2005 (gmt 0)

10+ Year Member



urgh!

Sorry, I messed up.

function addRow() {
var body = document.getElementById('displayButton')
.getElementsByTagName('tbody')[0];
var row = body.appendChild( document.createElement('tr'));
for (var i=0, cell; i < arguments.length; i++) {
document.picture.src=display[i];
cell = document.createElement("td");
row.appendChild(cell);
cell.appendChild(document.createTextNode( arguments[i]) );
cell.onClick = changeDescript;

}
}

function changeDescript() {
var imgName = document.getElementById("imgName");
imgName.firstChild.nodeValue = myPic_name[i]'
var imgDescript = document.getElementById("imgDescript");
imgDescript.firstChild.nodeValue = 'myPic_descript[i]';

//scratch this "}"
}

I can still call "i" outside the function right? Because of "for (var i=0, cell; i < arguments.length..."

Bernard Marx

10:21 pm on Sep 19, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'm still not completely "with the script". Still...

#1 onclick not onClick

cell.onClick = changeDescript; 
// should be
cell.on[blue]c[/blue]lick = changeDescript;

(..so that'll get things moving)

#2 What's this?

document.picture.src=display[i];

Not that it hurts, but I don't know why this is being done here. It will just end up at the final value of i.

#3 Rogue inverted comma

imgName.firstChild.nodeValue = myPic_name[i][red][b]'[/b][/red]

Get yourself a decent text editor with syntax highlighting! (like Textpad)

#4 Use

[blue]this[/blue]

The function, changeDescript, is being called as a method of the cell being clicked on. That means that the keyword,

[blue]this[/blue]
, will be a ready reference to the cell itself, should you need one.

#5 Dunno

imgDescript.firstChild.nodeValue = 'myPic_descript[i]';

Firstly, I reckon you don't want those quotes around

myPic_descript[i]
.
Secondly, what is
i
here? It doesn't exist in this function.

You could get it via the cell (since it's the same as the cellIndex)

myPic_descript[this.cellIndex]

Conscientious Reject

4:55 am on Sep 20, 2005 (gmt 0)

10+ Year Member



#1 Roger that

#2 I messed this up again.
//The script starts with preloading images like this.
var beforeLunch_pic = new Image();
beforeLunch_pic.src = "Thumbnails/JustbeforeBrunch.jpg";
//than those images are passed into an array.
var display = new Array();
display[0] = beforeLunch_pic.src;
/* This way I can changes the arrays value, when and if the users changes venues using a seperate function called changeUpGallery(whatGallery). This way:
*/
display[0] = beforeLunch_pic.src;
//now equals
display[0] = shadow_pic.src;
/*This is why - depending on the venue choosen and the ammount of arguments. I would hope that the new gallery would roll out from:
*/
display[0] = shadow_pic.src;
//through to:
display[4] = tile_pic.src;
//depending on how many times it would loop.

Still, I see your point, and don't even know how this was overseen. THERE SHOULD BE AN EVENT HANDLING THIS, OR IT WILL ALWAYS BE THE SAME VALUE. Which leads me to my biggest problem, and the ansewer to your #5.

When a user clicks on the cell I need three things to happen.

A.
document.picture.src=display[i];
B.
var imgName = document.getElementById("imgName");
imgName.firstChild.nodeValue = myPic_name[i];
C.
var imgDescript = document.getElementById("imgDescript");
imgDescript.firstChild.nodeValue = myPic_descript[i];

Hopefully you can see why I need access to "i" in the loop.

#3 OOPS!

#4 I should do a little more research on the keyword "this."

#5 Awe! I was hoping that maybe I could get away with that one.

With some revision I now have this:

function addRow() {
var body = document.getElementById('displayButton')
.getElementsByTagName('tbody')[0];
var row = body.appendChild( document.createElement('tr'));
for (var i=0, cell; i < arguments.length; i++) {
cell = document.createElement("td");

row.appendChild(cell);
cell.appendChild(document.createTextNode( arguments[i]) );

cell.onclick = document.picture.src=display[i];//etc.,
/*how do I pack all that "oomph" into one fun filled package like this:
cell.onclick = document.picture.src=display[i];
var imgName = document.getElementById("imgName");
imgName.firstChild.nodeValue = myPic_name[i];
var imgDescript = document.getElementById("imgDescript");
imgDescript.firstChild.nodeValue = myPic_descript[i];
*/
}
}

Anyway, I took the last function out for now because I am pretty sure it's junk. Wouldn't you agree that I need a function to handle all three of these tasks. If so, can I still call "i"? Or maybe I could create another loop to count the newly created table cells, and get my "i" that way instead.

Bernard Marx

7:57 am on Sep 20, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yes, I'd certainly agree. You do need one fun filled package, and that was your function.
You've removed it now, and taken other retrograde steps:

cell.onclick = document.picture.src=display[i]; // XXX

[/code]

It doesn't work like that. That just assigns display[i] to the cell's onclick property.

On a side note:

[pre][code]imgName.firstChild.nodeValue = myPic_name[i];

[/pre]

This isn't as good an idea as it looks. Browsers, especially Mozilla are wont to throw in empty text nodes where one least expects..

<div>
<img>
</div>

- The <img> is likely to be the 2nd childnode of the <div>

Writing all on one line can solve the problem, but it's not good to have the script rely on it. Back to specifics, I'd advise:

imgName.getElementsByTagName('_the_tagName_')[0].nodeValue = ....


function addRow()
{
var body = document.getElementById('displayButton')
.getElementsByTagName('tbody')[0];
var row = body.appendChild( document.createElement('tr'));
for (var i=0, cell; i < arguments.length; i++)
{
cell = document.createElement("td");
row.appendChild(cell);
cell.appendChild(document.createTextNode( arguments[i]) );
cell.onclick = cell_click;
}
}

function cell_click()
{
var i = this.cellIndex;
document.picture.src = display[i];
document.getElementById("imgName")
.getElementsByTagName('_what_this_tag_')[0].nodeValue = myPic_name[i];
document.getElementById("imgDescript")
.getElementsByTagName('_what_this_tag_')[0].nodeValue = myPic_descript[i];
}

Conscientious Reject

4:32 pm on Sep 21, 2005 (gmt 0)

10+ Year Member



Hey Marx,

It's working with only a few minor glitches. Let me look over it, and see what I can fix. Or at least find out what needs attention. I will post again later.

Conscientious Reject

6:07 pm on Sep 21, 2005 (gmt 0)

10+ Year Member



IT WORKS!

...but why do I need to add the array [0] to the end of ('_what_this_tag_')[0]?

it still works without it.

Thanks Marx

Bernard Marx

7:00 pm on Sep 21, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



It shouldn't - certainly in Mozilla.

Bernard Marx

8:55 pm on Sep 21, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



getElementsByTagName returns a nodeList (kind of read-only array) of all such child tags in the element it's called on. The list is numerically ordered in source code order.

In our case, we want the 1st (in fact only) member of that list.