PDA

View Full Version : Variable function call



Badman3k
Feb 23rd, 2007, 11:59 AM
I want to be able to have an array of items, which I add to the DOM. One of the values in the multi-dimension array is a string that I want to use to call a different function. How do I go about doing this?

This example may help to make things more clear, if they aren't already.


var aItems = new Array(
Array("Item1", "fnOne"),
Array("Items", "fnTwo")
);

function initialise() {
for (i = 0; i < aItems.length; i++) {
oDiv = document.createElement('div');
oDiv.id = aItems[i][0];
oDiv.onclick = function () {
aItems[i][1]();
}
document.body.appendChild(oDiv);
}
}

Then to top it off, how do I pass variables to the called function?! i.e. the simple hard coded way would be to do something like: fnOne(this.id);

Many thanks in advance,

BarrMan
Feb 23rd, 2007, 12:13 PM
Create global variables to pass information between functions.
ie:

var myText = "hello";
function changeText()
{
myText = "world";
}
function writeText()
{
alert(myText);
}

Once you call changeText, the value of myText is changed and when you call writeText, you'll get the new value of it.

Badman3k
Feb 23rd, 2007, 12:31 PM
Thanks for replying, but I don't think you've understood the problem. I don't want to pass a variable to different functions, I want the basically use the value within the variable and call it as if it were a function:

aVariable = "fnOne";
//now call the function:
aVariable();
//...
//...
fnOne() {
// Do some stuff in here
}

Does that make any more sense?

Arty Effem
Feb 23rd, 2007, 01:14 PM
I want to be able to have an array of items, which I add to the DOM. One of the values in the multi-dimension array is a string that I want to use to call a different function. How do I go about doing this?

Store a reference to the function, i.e. its name:
var aItems = new Array( Array("Item1", fnOne), Array("Items", fnTwo));
.
.
aItems[i][1]( this.id );

glenngv
Feb 23rd, 2007, 10:19 PM
oDiv.onclick = function () {
window[aItems[i][1]]();
}
Global functions and variables can be accessed via the global window object. See square bracket notation link in my sig for more info on this.

Arbitrator
Feb 23rd, 2007, 10:42 PM
One of the values in the multi-dimension array is a string that I want to use to call a different function. How do I go about doing this?Not sure if this is a poor way of going about it, but you can use eval() to do this:


function initialise() {
for (var i = 0; i < aItems.length; i++) {
oDiv = document.createElement('div');
oDiv.id = aItems[i][0];
eval("oDiv.onclick = function() {"\
+ aItems[i][1] + "();\
}");
document.body.appendChild(oDiv);
}
}


Then to top it off, how do I pass variables to the called function?!The this variable is automatic for a function called by a registered event (if not registered inline); whatever element that the event is associated with automatically gets the this keyword. If you need to pass other variables, just pass them normally using the code above.

glenngv
Feb 24th, 2007, 04:18 AM
Not sure if this is a poor way of going about it, but you can use eval() to do this:

Yes it is (http://www.codingforums.com/showthread.php?t=20143). Javascript square bracket notation is the most efficient and appropriate solution.

Arbitrator
Feb 24th, 2007, 05:42 AM
Yes it is (http://www.codingforums.com/showthread.php?t=20143). Javascript square bracket notation is the most efficient and appropriate solution.Well, Iím interested in how this works, but it doesnít seem to make sense; how does the associative array make the variable i static for the generated output? Inserting the code you provided in your last post, you get the following (see end of post) and it doesnít seem to work.

I expect to have the following events registered, but i is still sitting there (as an undefined variable), so the script fails:


// Template
oDiv.onclick = function() {
window[aItems[i][1]]();
}

// Expected (Effective) Output
oDiv.onclick = function() { // Associated with oDiv A
aItems[0][1]();
}
oDiv.onclick = function() { // Associated with oDiv B
aItems[1][1]();
}


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html lang="en-US">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>HTML 4.01 Strict Document</title>

<style type="text/css">
* { margin: 0; }
html { padding: 1em; }
</style>

<script type="text/javascript">
var aItems = [["Item1", "fnOne"], ["Items", "fnTwo"]];
function initialise() {
for (var i = 0; i < aItems.length; i++) {
var oDiv = document.createElement('div');
oDiv.id = aItems[i][0];
oDiv.onclick = function() {
window[aItems[i][1]]();
}
oDiv.appendChild(document.createTextNode("Hello " + i));
document.body.appendChild(oDiv);
}
}
function fnOne() {
alert("f1");
}
function fnTwo() {
alert("f2");
}
</script>

</head>
<body onload="initialise()">

<p>Test</p>

</body>
</html>

glenngv
Feb 26th, 2007, 06:52 AM
I didn't realize there was a variable inside the onclick handler. The easiest solution for this is to attach the i as a custom attribute in the div.


function initialise() {
for (var i = 0; i < aItems.length; i++) {
var oDiv = document.createElement('div');
oDiv.id = aItems[i][0];
oDiv.ctr = i; //create a custom attribute named ctr
oDiv.onclick = function() {
alert(this.ctr + "\n" + aItems[this.ctr][1]); //test
window[aItems[this.ctr][1]]();
}
oDiv.appendChild(document.createTextNode("Hello " + i));
document.body.appendChild(oDiv);
}
}

Arbitrator
Feb 27th, 2007, 12:57 AM
I didn't realize there was a variable inside the onclick handler. The easiest solution for this is to attach the i as a custom attribute in the div.That works, though Iím still not quite sure why it only works when the associative array is used.

I changed the initialise function a bit to make it so that the DTD need not be altered to accommodate a custom attribute. It gets more complicated if you use multiple class names on the element though.


function initialise() {
for (var i = 0; i < aItems.length; i++) {
var oDiv = document.createElement('div');
oDiv.id = aItems[i][0];
oDiv.className = "a" + i;
oDiv.onclick = function() {
window[aItems[this.className.charAt(1)][1]]();
}
oDiv.appendChild(document.createTextNode("Hello " + i));
document.body.appendChild(oDiv);
}
}

Or W3C DOM-Compliant:

function initialise() {
for (var i = 0; i < aItems.length; i++) {
var oDiv = document.createElement('div');
oDiv.id = aItems[i][0];
oDiv.className = "a" + i;
oDiv.addEventListener("click", function() {
document.defaultView[aItems[this.className.charAt(1)][1]]();
}, false);
oDiv.appendChild(document.createTextNode("Hello " + i));
document.body.appendChild(oDiv);
}
}

Pyth007
Mar 1st, 2007, 12:09 AM
I believe you can also solve your closure problem using something like:


oDiv.onclick = function(myVar) {
window[aItems[myVar][1]]();
} (i);


Check out my earlier thread (http://www.codingforums.com/showthread.php?t=93648) on a similar question (after re-reading it, I may have misspoken above by calling this a "closure problem"...)