Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 330 Vote(s) - 3.48 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to create dynamic buttons to call a function with different arguments

#1
I'm trying to build up a jscript interface on a WSH component for foobar2000 music player.
At some point, i need to create a variable number of buttons that will each call the same function, but using a different argument. I can create the buttons, using a *for loop* and an *array*. However, all buttons will pass the argument of the **last** button only.

Here is the code i use to add buttons :

for (var i=0; i<_groupsArray.length; i++) {
_btn = _groupsArray[i];
ƒview.addButton(_btn, _img, function () {setView(_btn)}, function () {doPlay(_btn)});
}
In this case, _btn is used both as the button label and the argument i want to pass to the function when i click on the button (it will be an artist name, or album title or something similar). *ƒview* is a custom object that holds the buttons. I created it so i don't have to specify position of buttons, *ƒview* will calculate them whenever needed.
This is the part of the addButton method that will actually create the buttons (the rest does calculate the layout). Each action argument is passed as a parameter to the button being created, without any processing by the addButton method.

this.addButton = function(label, img, action1, action2, action3, action4, action5) {
...
new ButtonObject(label, __x, __y, __w, __h, action1, action2, action3, action4, action5);
Finally, i have this in my buttonObject constructor :

function ButtonObject(label, x, y, w, h, action1, action2, action3, action4, action5) {
...
this.action1 = action1;
this.action2 = action2;
this.action3 = action3;
this.action4 = action4;
this.action5 = action5;
...
this.act1 = function () {
var __doIt = function () {this.action1();};
return __doIt;
}
The function passed during the *for loop* will finally be stored in the object as action1, action2 ... property.
I tried many different ways of calling *action1* with act1 method, including directly calling *this.action1()*; using *this.action1.apply()*; trying to form a clausure as you see above. Either it will call the correct action but using the argument of the **last** button created, or it will crash or have no effect.

I'm now out of ideas to try. I had some partial success passing the function and the argument separately but that's an ugly trick. I've read a number of tutorials on clausures and how they can keep the local variables alive, but i still didn't managed to make them work for me in this case. My last attempt (as you can see it in the code) will crash when i click the button with a "this object does not handle this property or method" pointing to the line

var __doIt = function () {this.action1();};
So how do i keep the arguments "alive" within each button?
Reply

#2
Try something like:

for (var i=0; i<_groupsArray.length; i++) {
_btn = _groupsArray[i];
ƒview.addButton(_btn, _img,
function(b) {return function () {setView(b)};}(_btn),
function(b) {return function () {doPlay(b)};}(_btn)
);
}

You need to create a closure to hold the value of _btn, not just a binding to it. The extra wrapper function does precisely that.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through