How to generate buttons within a loop?<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />I'm trying to generate buttons within a loop (one button for each column). The buttons are created correctly except that when the button executes its script it will always execute the script of the lastly created button - instead of the script that was passed to the button box object when it was created.
So, it seems that the button gets only a reference to the script - and if script is changed the button will change its function. I tried considering workaround with array of scripts but the problem is that I can't pass any argument for the button object (e.g. index which script in the array to execute).
Question: Is there any way in jsl that one can create buttons within a loop with different scripts/behaviour? E.g. is there any way of passing arguments/data to button object when it is created???
My code:
NamesDefaultToHere(1);
dt = Current Data Table();
dtCols = dt << Get Column Names( Numeric, Continuous );
// Expression for displaying distribution for strParam
Expr_ShowDistribution = Expr(
New Window( Char(strParam),
Distribution(
Continuous Distribution(
Column( strParam ) //We specify our parameter
),
SendToReport(
Dispatch( {}, "Distribution", OutlineBox, Set Title( "" ) ),
)
)
)
);
// Main Window
New Window("Main Window",
ob = OutlineBox("Buttons",
TextBox("Debugging buttons", Set Font Style("Bold"))
);
);
// Create button that only outputs to log
BB = Button Box( "ClickMe", Show("Clicked"));
ob << Append(BB);
// Create buttons for showing distributions
For( i = 1, i <= NItems(dtCols), i++,
Expr_ButtonAction = Substitute(NameExpr(Expr_ShowDistribution),
Expr(strParam), Eval(Char(dtCols)) );
Show(NameExpr(Expr_ButtonAction)); // Expression is different for each button.
BB = Button Box( Char(dtCols), Eval(Expr_ButtonAction));
ob << Append(BB);
);
Re: How to generate buttons within a loop?Your example should work if the last two rows within the loop, i.e
BB = Button Box( Char(dtCols[i]), Eval(Expr_ButtonAction));
ob << Append(BB);
are replaced with
Eval( Eval Expr( ob << Append( Button Box( Char( dtCols[i] ), Expr( Name Expr( Expr_ButtonAction ) ) ) ) ) );
Not the most obvious solution. Here, I think the "string manipulation" approach like in PMroz' example is simpler.
Re: How to generate buttons within a loop?Good idea, but not implemented. For now I'd suggest using the button's name as the key to an associative array.
Re: How to generate buttons within a loop?The Set Function() approach would seem to be more useful if I could attach some user data to the button, say by adding key-value pairs to an associative array. Is that possible?
Re: How to generate buttons within a loop?A button script can be a function with a "this" parameter that refers to the button, which means the button can find its name or its parent box.
New Window( "example", v = V List Box() );
f = Function( {this}, Show( this << getbuttonname ) );
For( i = 1, i < 10, i++,
v << append( Button Box( "number " || Char( i ), Set Function( f ) ) )
);

The "Set Function" parameter is the key to making this work. In your example I think the button names might be the column names. The VListBox in the example is named "v" so button boxes can be appended to it.
Re: How to generate buttons within a loop?Here's an implementation that works. I changed the distribution expression to a function, and then had to play with evalinsert, parse, eval to get it to work.
showdistribution = function({column_name}, {Default Local},
dist_expr = evalinsert(
"\[Distribution( Nominal Distribution( column(:name("^column_name^")) ) )]\");
eval(parse(dist_expr));
);
// Main Window
New Window("Main Window",
ob = OutlineBox("Buttons",
TextBox("Debugging buttons", Set Font Style("Bold"))
);
);
// Create button that only outputs to log
BB = Button Box( "ClickMe", Show("Clicked"));
ob << Append(BB);
dt = open("$sample_data\Big Class.jmp");
dtcols = dt << get column names(string);
for (i = 1, i <= nitems(dtcols), i++,
button_expr = evalinsert("\[one_button = button box("^dtcols^", showdistribution("^dtcols^"))]\");
eval(parse(button_expr));
ob << append(one_button);
);