...

View Full Version : setting onClick attribute with javascript that points to a function with param



deadseasquirrel
05-25-2004, 05:35 PM
I've read the threads about how to set the onclick attribute with a javascript and I am implementing it as such right now.

temptemp.onclick = Function("displayStaff()");

But now I want to make my displayStaff() function take a parameter, how do I go about doing it. I tried this:

temptemp.onclick = Function("displayStaff(" + newCenterName + ")");

where newCenterName was a string variable but it didn't work. The error was that newCenterName (or rather the string it represented, so it does recognize the string) was undefined. Does somebody know how to deal with this issue so that I can put a parameter in my javascript? Thanks

Let me ask this short and sweet. How can I write a javascript such that it creates the following:

<a href="#" onclick="somefunction(dynamic)"></a>

where the word dynamic is dynamically chosen by the javascript. Thanks, this is driving me crazy.

Basscyst
05-25-2004, 06:31 PM
define your parameters when you define the function like this:

If passing a string to the function the paramaters should be in quotes when the function is called:

EX.


<html>
<head>
<script type="text/javascript">
function showExample(param1,param2)
{
var x=param1;
var y=param2;
alert(x+' '+y);
}

</script>
</head>
<body>
<a href="#" onclick="showExample('Hello','World');">Coding Forums</a>
<iframe src="http://www.google.com" id="main"></iframe>
</body>
</html>


If you are passing a variable to the function then you don't need the quotes:

EX.


<html>
<head>
<script type="text/javascript">
function showExample(param1,param2)
{
var x=param1;
var y=param2;
showExample2(x,y);
}

function showExample2(param1,param2)
{
var str=param1+' '+param2;
alert(str);
}
</script>
</head>
<body>
<a href="#" onclick="showExample('Hello','World')";>Coding Forums</a>
<iframe src="http://www.google.com" id="main"></iframe>
</body>
</html>


Basscyst

deadseasquirrel
05-25-2004, 06:47 PM
Ok, but the question here is how do I make this code:

<a href="#" onclick="showExample('Hello','World')";>Coding Forums</a>

dynamically in a javascript.

For those who understand what my issue is, you will know that you can not just do

aElement.setAttribute ("onclick", "showExample(...)");

I need a javascript that will set the onclick attribute to:
onclick = "someFunction(dynamic)"

Where the word dynamic is, well, dynamic and decided by the javascript.

swmr
05-25-2004, 07:11 PM
possibly:

...setAttribute("onclick", function(){return functionName("blah")});

edit:// actually, that only works in IE, so:
...onclick=function(){return functionName("blah")};

Basscyst
05-25-2004, 07:20 PM
I'm sorry I didn't fully answer your questoin.

Does this answer it better?

You need quotes around the string else it will pass the variable named whatever your string says, which would be undefined.

Just a tip:
When posting it's best to state what you are trying to do in English, then showing an example of your code (working or not) within the code tags. If you wish to place notation within the code use the comment tag.It will generally lead to a more clearly communicated question.




<html>
<head>
<script type="text/javascript">
function showExample(param1,param2)
{
var x=param1;
var y=param2;
alert(x+' '+y);
}

function setOnclick()
{
var x='Hello';
var y='World';
document.getElementById('link1').onclick=Function("showExample('"+x+"','"+y+"')");
}
</script>
</head>
<body onload="setOnclick()">
<a href="#" id="link1">Coding Forums</a>
</body>
</html>


Basscyst

Rex
05-25-2004, 07:37 PM
Hello Basscyst -

What if the string itself contains an apostrophe? That would lead to a syntax error. So we should maybe use a function to escape some characters:

<html>
<head>
<script type="text/javascript">
function escapeChars(str)
{
str = str.replace(/\\/g, '\\\\');
str = str.replace(/\'/g, '\\\'');
return str;
}

function showExample(param1,param2)
{
var x=param1;
var y=param2;
alert(x+' '+y);
}

function setOnclick()
{
var x='Hello';
var y='World';
document.getElementById('link1').onclick=Function("showExample('"+escapeChars(x)+"','"+escapeChars(y)+"')");
}
</script>
</head>
<body onload="setOnclick()">
<a href="#" id="link1">Coding Forums</a>
</body>
</html>

- Rex

Basscyst
05-25-2004, 07:46 PM
Or you can just switch around the order in which you use your quotes in the script. My mistake. :eek:



<html>
<head>
<script type="text/javascript">
function showExample(param1,param2)
{
var x=param1;
var y=param2;
alert(x+' '+y);
}

function setOnclick()
{
var x="Hello";
var y="World's";
document.getElementById('link1').onclick=Function('showExample("'+x+'","'+y+'")');
}
</script>
</head>
<body onload="setOnclick()">
<a href="#" id="link1">Coding Forums</a>
</body>
</html>


Basscyst

Rex
05-25-2004, 08:00 PM
Hello Basscyst -

Your code works well if you are certain that the string doesn't contain a double quote or a backslash. It could be used with user input and then you don't know what it contains... In such a case, a simple escaping function wouldn't be useless. :)

- Rex

Basscyst
05-25-2004, 08:14 PM
Indeed far from useless but in the above example we are setting the attributes of onclick in which case it would be fairly safe to assume, unless the end user is somehow customizing the links, that we know what values are going to be contained in the variable and code it as such. While in his\her case it may be usefull, it wasn't really the question here. Though I didn't exactly answer the question first out either. :rolleyes: :D :o
Basscyst

deadseasquirrel
05-25-2004, 08:21 PM
I think the issue here is not really the question about quotes or double quotes or anything like that. swmr hit it on the mark with his reponse (though I haven't tried it yet). The issue here is with IE handling of
setAttributes("onclick", [function(param)]);

The problem is with mixing of double quotation marks and single quotation marks. swmr, if you are around, perhaps you can explain it a little more elegantly.

Basscyst
05-25-2004, 08:44 PM
The problem with your example code above was in fact a syntax error in your usage of the quotation marks. Though swmr's way may in fact be a better solution.



temptemp.onclick = Function("displayStaff(" + newCenterName + ")");


should be:



temptemp.onclick = Function("displayStaff('" + newCenterName + "')");


Sorry to have gone off on a brief tangent.


Basscyst

swmr
05-25-2004, 08:46 PM
strings aren't my thing. :p

Re: attributes - all I can offer is what's been discussed here (http://codingforums.com/showthread.php?t=38567).

deadseasquirrel
05-25-2004, 09:26 PM
basscyst your code:
temptemp.onclick = Function("displayStaff('" + newCenterName + "')");

would be correct (maybe, I can't even say if it would work) if newCenterName was a string that I wanted to pass, but newCenterName is a variable within the javascript which should change depending a number of things. So I the way I wrote it, though it didn't work, should have been logically sound.

temptemp.onclick = Function("displayStaff(" + newCenterName + ")");

would have produced
temptemp.onclick = Function("displayStaff([dynamic part]"));

which should have, mind you should have, created the html code:

<a onclick="displayStaff([dynamic part])"></a>

Willy Duitt
05-25-2004, 10:40 PM
I had the same problem of adding an event handler which includes a parameter to a dynamically created element. Below is an example of how I solved it.


<script type="text/javascript">
<!--//
var count = 0;
function addRow(insertHere){
newRow = document.createElement("tr");
newRow["onclick"] = new Function("addRow(this)");
newCell = document.createElement("td");
newCell.innerHTML = insertHere.innerHTML+'('+count+++')';
newRow.appendChild(newCell);
insertHere.parentNode.insertBefore(newRow,insertHere.nextSibling);
}
//-->
</script>
</head>

<body>
<table>
<tr onclick="addRow(this)"><td>data 1</td></tr>
<tr onclick="addRow(this)"><td>data 2</td></tr>
<tr onclick="addRow(this)"><td>data 3</td></tr>
</table>

.....Willy

Vladdy
05-25-2004, 10:54 PM
Just like a program can be written without "goto" statements, efficient organization of data and interfaces will erase the perceived need to have arguments in event handlers.

swmr
05-25-2004, 11:47 PM
Sounds good!

What does it mean? :D

deadseasquirrel
05-26-2004, 04:04 AM
swmr, you beat me to it. Yeah if programming in Java, with SWING yes, maybe a better design would nullify the need for parameters in eventHandlers, but how do I achieve what Willy doing it the "right" way?

I'm not exactly sure how to extrapolate what Willy did to what I need just quite yet, but if anybody have a better solution, I am all ears, and even point me to some literature as to how I should be designing a javascript I would be more than happy to read that as well.

Vladdy
05-26-2004, 04:18 AM
Explain what you are trying to accomplish...

In general:
The only variables that are set during onclick event are those that passed to your function in an event variable (or can be retrieved from window.event in the sub-par HTML renderer :p ). Any other variable that you need for processing onclick event can be associated with the object/element by other means.

deadseasquirrel
05-26-2004, 05:00 AM
Ok, even though this thread is 17 messages deep, let me try to start from the beginning. I am not going to include my code, because it is huge, and I think it is much more beneficial to just have me explain things (if you really want it, I'll email it).

There are three windows. In window1 I have a list of states, when I click on a state, it grabs information from and XML file and displays all the stores in that state in window2. That part is working fine. Now I am trying to make the name of the each store in window2 be an
<a href="#" onclick=function()></a>

so that when you click on a name of a store in window2, it opens up other information, such as hours, location, map, in window3.

In any other situation I want window2 and 3 to be blank as default. So lets say I click on a state that fills windows1-2-3, and the I click on Wisconsin, which doesn't have a store, then I want windows 2 and 3 to go blank.
so the following is the a small part of the javascript that is activated after clicking the state:


var temptemp = document.createElement("a");
tempDiv.setAttribute("id", "city");
temptemp.setAttribute("href", "#");
temptemp.setAttribute("id", "city");
temptemp.appendChild(document.createTextNode(newCenterName));
tempDiv.appendChild(temptemp);
tempCenter.appendChild(tempDiv);


Any variable not explicitly declared, was declared somewhere else (that is not the problem I have). Mind you this code is only a small tidbit of the object created that makes up the stores in window2, but you should get the point.

Now all I want to add is an onclick attribute to that <a> tag, and set it to some javascript function called displayWindow3([storeName]), where storeName is the name of the store which was clicked on to create a display in window3.

Does that make sense? I am getting close, that is I can make it call a function, but I can't seem to make it accept a parameter in the function.

glenngv
05-26-2004, 05:36 AM
You can use the Function constructor but it is slow (just like eval) and prone to problems when the parameter has single or double quotes in it.

You should use swmr's suggestion.

var temptemp = document.createElement("a");
tempDiv.setAttribute("id", "city");
temptemp.setAttribute("href", "#");
temptemp.setAttribute("id", "city");
temptemp.onclick = function() {displayWindow3(storeName)};
temptemp.appendChild(document.createTextNode(newCenterName));
tempDiv.appendChild(temptemp);
tempCenter.appendChild(tempDiv);

If that doesn't work, try setting the onclick handler AFTER appending the element.

var temptemp = document.createElement("a");
tempDiv.setAttribute("id", "city");
temptemp.setAttribute("href", "#");
temptemp.setAttribute("id", "city");
temptemp.appendChild(document.createTextNode(newCenterName));
tempDiv.appendChild(temptemp);
tempCenter.appendChild(tempDiv);
document.getElementById("city").onclick = function() {displayWindow3(storeName)};


But why do you have the same id for tempDiv and temptemp?
Ids must be unique. Resolve it first then apply my suggestion.

Vladdy
05-26-2004, 03:23 PM
Ok, so you have a set of dynamically generated elements that onclick envoke the same function, but with different parameter...
1. Anchor element is used to link to a URI. Using it to envoke a script is a misuse. Span element is sufficient; if you need tabbing functionality, use button.
2. Use event processing function to do just that: process event
3. As Glenn said, id has to be unique, and I do not see a need for it at all.

If you follow the above here is the code:

tspan = document.createElement('span');
// Associate additional information, that you need to pass along, with the element
tspan.storeName = 'Name of the store';
// Add text node
tspan.appendChild(document.createTextNode('Element Text'));
// onclick processing function
tspan.onclick = function (e)
{ // Find which element was acted upon (DOM2 and IE branching)
target = e?e.target:window.event?window.event.srcElement:null;
// Call your function with the parameter associated with event target
if(target) displayWindow3(target.storeName);
}
Actually you may not even need the additional .storeName property since you can simply pass the string representing the element text:
displayWindow3(target.firstChild.nodeValue);

deadseasquirrel
05-26-2004, 05:56 PM
Vladdy,
Thanks a lot, that worked, and you were right. I do not need storeName as an attribute to the tag. In fact I have storeName stored within the Javascript.

I need to read more about eventHandlers for DOM. Anyway, is there a way to make <span> elements look like <a> elements, that is with the hover color change and such and make the mouse cursor change too. I tried doing:
span:hover{}
span:active{}
etc. But that did not work.

Vladdy
05-26-2004, 06:18 PM
span:hover and span:active works fine in real browsers.
Here is what I do to make it work in IE: www.vladdy.net/Demos/IEPseudoClassesFix.html

deadseasquirrel
05-26-2004, 09:46 PM
One small correction Vladdy that I noticed: (edit: not working)

you have to change the code to:


tspan = document.createElement('span');
// Associate additional information, that you need to pass along, with the element
tspan.storeName = 'Name of the store';
// Add text node
tspan.appendChild(document.createTextNode('Element Text'));
// onclick processing function
tspan.onclick = new function (e)
{ // Find which element was acted upon (DOM2 and IE branching)
target = e?e.target:window.event?window.event.srcElement:null;
// Call your function with the parameter associated with event target
if(target) displayWindow3(target.storeName);
}


I'm not exactly sure how "function" works, but I guess that makes a little sense.
Otherwise it will just use the same target.storeName (namely the last one) in every single instance of the function.

Sorry I actually noticed that this does not work.

without the "new function" statement, this code will just use the most recent target.storeName variable, so if I had that code in a while loop, which I do, every single <span onclick="displayWindow3(var)"> will have the same var value, namely the last var that was determined. When I add the new word, then what happens is that the var will be different, but then it no longer SETs onclick to displayWindow3(var), it calls it. So now what, I can't get this, and it is driving me crazy.

Vladdy
05-26-2004, 10:22 PM
I forgot to put var target=e?.....
This way target is local to the function, it still should not matter, because the target variable is updated within the event processing function.
You do not need "new" in front of the function.

Not sure what you mean by the "while loop" the function is called during the onclick event, presumably after all your objects are created...

deadseasquirrel
05-26-2004, 10:48 PM
I just meant that I have a while loop creating a number of the aforementioned code, so that if you looked at the html it would look something like:

<span onclick="displayWindow3(var1)">something1</span>
<span onclick="displayWindow3(var2)">something2</span>
<span onclick="displayWindow3(var3)">something3</span>

I was wondering if the while loop did something to screw that up.

Vladdy
05-26-2004, 11:03 PM
If you use the code I provided to create those elements, everything should work.

Willy Duitt
05-26-2004, 11:36 PM
I think the problem is is that the O/P is calling the function and is using a loop to create multiple instances of a new element. Not just one new element.

I've seen example code from everyone but the O/P.
Why don't you show us the code you are working with.

deadseasquirrel
05-27-2004, 12:44 AM
I am always weary of putting up code, especially when it is too long. But here it goes. Whatever is not there assume it is somewhere else that i have not shown. All variables are declared.


/* Displays the information in the current xmlObj, namely the center information
of the state which is loaded
*/
function displayCenters(_xmlObj){
var newStateAbbrev = _xmlObj.getAttribute("abbrev"); // handle to state abbreviation in XML doc
var newStateCenters;
var center;
// var newCenterName;
var newAddress;
var newCity;
var newZipCode;
var newTelephone;
var newFax;

newStateCenters = document.createElement("div");
newStateCenters.setAttribute("id", "statecenters");

if (_xmlObj.hasChildNodes()){
var newCenterName;
var centerNum = 0; // counter for number of Centers
var tempCenter; // temporary variable to hold center during stateCenters loop
var tempDiv; // temporary variable for center information object
var phoneOptions; // temporary variable for possible phone option attributes
var hours = _xmlObj.getElementsByTagName("hours"); // handle to hours object in XML document
var staff = _xmlObj.getElementsByTagName("staff"); // handle to staff object in XML document

while((center = _xmlObj.childNodes[centerNum++]) != null){

var day; // Temporary variable to hold day for hours of operations information
var dayNum = 0; // counter for hours of operation days
var positionNum = 0; // counter for positions for staff information


newCenterName = center.getElementsByTagName("name")[0].firstChild.text;
newAddress = center.getElementsByTagName("address")[0].firstChild.text;
newCity = center.getElementsByTagName("city")[0].firstChild.text;
newZipCode = center.getElementsByTagName("zipcode")[0].firstChild.text;
newTelephone = center.getElementsByTagName("telephone")[0].firstChild.text;
newFax = center.getElementsByTagName("fax")[0].firstChild.text;

tempCenter = document.createElement("div");
tempCenter.setAttribute("className", "center");
tempDiv = document.createElement("div");


var tempA = document.createElement("a");
tempA.setAttribute("id", "city");
tempA.setAttribute("href", "#");
tempA.appendChild(document.createTextNode(newCenterName));
alert("outside newCenterName is " + newCenterName);
tempA.onclick = function (e){
var target = e?e.target:window.event?window.event.srcElement:null;
alert("inside newCenterName is " + newCenterName);
if (target) displayStaff(newCenterName);
}

tempDiv.appendChild(tempA);
tempCenter.appendChild(tempDiv);

tempDiv = document.createElement("div");
tempDiv.setAttribute("id", "address");
tempDiv.appendChild(document.createTextNode(newAddress));
tempCenter.appendChild(tempDiv);

tempDiv = document.createElement("div");
tempDiv.setAttribute("id", "address2");
tempDiv.appendChild(document.createTextNode(newCity + ", " + newStateAbbrev + " " + newZipCode));
tempCenter.appendChild(tempDiv);

phoneOptions = center.getElementsByTagName("telephone")[0].getAttribute("option")
tempDiv = document.createElement("div");
tempDiv.setAttribute("id", "telephone");
if (phoneOptions != null){
tempDiv.appendChild(document.createTextNode("(tel) " + newTelephone + " Options: " + phoneOptions));
}
else{
tempDiv.appendChild(document.createTextNode("(tel) " + newTelephone));
}
tempCenter.appendChild(tempDiv);

tempDiv = document.createElement("div");
tempDiv.setAttribute("id", "fax");
tempDiv.appendChild(document.createTextNode("(fax) " + newFax));
tempCenter.appendChild(tempDiv);

while(hours[0].hasChildNodes() && (day = hours[0].childNodes[dayNum++]) != null){
tempDiv = document.createElement("div");
tempDiv.setAttribute("className", "hours");
tempDiv.appendChild(document.createTextNode(day.getAttribute("name") + ": " + day.firstChild.nodeValue));
tempCenter.appendChild(tempDiv);
}
newStateCenters.appendChild(tempCenter);
stateInfo.replaceChild(newStateCenters, stateCenters);
stateCenters = document.getElementById("statecenters");
}
}
else{
newStateCenters.appendChild(document.createTextNode(NOCENTERS));
stateInfo.replaceChild(newStateCenters, stateCenters);
stateCenters = document.getElementById("statecenters");
}
}

Here are a couple of notes. Do a search for tempA that is where the incident occurs. I know I know, I am suppose to use span, but i wanted the hover effect without too much hassle, so bear with me (that is not the problem anyway). Also as you can see, I did not but the original coders code in there, I took it out, but trust me I did put it in there with the correct reference to the correct information, and it did not work.

The variable newCenterName is dynamic within that while loop. displayStaff() is another function somewhere else. I think that is all the pointers. IF you want everything, please PM me.

Vladdy
05-27-2004, 01:40 AM
var tempA = document.createElement("a");
//You can not do that. Elements should have unique id!!!
tempA.setAttribute("id", "city");
tempA.setAttribute("href", "#");
tempA.appendChild(document.createTextNode(newCenterName));
alert("outside newCenterName is " + newCenterName);
tempA.onclick = function (e)
{ var target = e?e.target:window.event?window.event.srcElement:null;
//newCenterName is useless here. This function is run onclick!!!
alert("inside newCenterName is " + newCenterName);
if (target) displayStaff(newCenterName);
//Since you are using newCenterName to set the node's text:
if(target) displayStaff(target.firstChild.nodeValue);
}

deadseasquirrel
05-27-2004, 02:45 AM
I'm sorry, but i thought i took out the other id="city", am I going crazy. Also if you are referring to the alert(), that was just for testing. Thanks for the tip, I'll try it and see if it works, and try to wrap my head around why it should work.

deadseasquirrel
05-27-2004, 07:18 PM
Thank you, it worked, and it is making a little more sense. One final question. Is there a way to pass an object back to displayStaff in my example, or can it only be strings? can I just define another attribute that holds an object? Or is that an html no no.

Vladdy
05-27-2004, 07:47 PM
Which object are you talking about? HTML element or a custom one?

deadseasquirrel
05-27-2004, 08:30 PM
A custom one a handle to an element from an XML file. Within the javascript the object in question is the "center" object which is defined within the while loop as:

while((center = _xmlObj.childNodes[centerNum++]) != null)

Vladdy
05-27-2004, 08:40 PM
As I showed in my original example:


//create a custom attribute of your anchor and point it to your object:
tempA.myObject = center;
....
//then send it wherever when processing onclick
myFunction(target.myObject);



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum