I'll write a quick overview what I talked about today in the meeting. You can see my full solutions in my earlier posts in this topic. I will modfify my Challenge A solution to use JMP's SAMPLE_IMAGE folder, so you should be able to directly run it.
Challenge A: Clicking in a data table cell should initiate something
Concept: Using Event Handler column property
This is fairly easy to do by letting JMP script this for you. Add Event Handler for web page for example and then modify the script to better fit your needs. Below is my example solution on how to open an image in cell.
Column(dtx, "Picture") << Add Column Properties(
Set Property(
"Event Handler",
Event Handler(
Click(JSL Quote(Function({thisTable, thisColumn, iRow}, {},
New Window(Char(thisTable:"File Name"n[iRow]), New Image(thisTable:thisColumn[iRow]));
))),
Tip(JSL Quote(Function({thisTable, thisColumn, iRow}, {},
"Enlarge image " || Char(thisTable:"File Name"n[iRow]);
)))
)
)
);
Event Handlers can be fairly powerful as you could for example query data from database on cell click.
Challenge B: Closing a window should trigger some action
Concept: Using << On Close()
Idea in this challenge was to perform an action when Graph Builder is closed. This is fairly simple task to perform by using << On Close(). Below is slightly modified version of the solution provided by @Robbb
gb << On Close(
dist = dt << Distribution(Nominal Distribution(Column(:age)));
image = dist << Get Picture;
image << Save Picture($temp/age_dist.png, "png");
dist << Close Window();
);
One thing to consider with this is, that when you are using references to data table (in this case dt), that if you open new table before closing gb, you will most likely close wrong table.
You can see this issue in this example script:
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
biv << On Close(
close(dt, no save);
);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
And this script provides one possible solution by using Eval(EvalExpr()) and Expr() to get explicit reference to the table
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
dt = Open("$SAMPLE_DATA/Semiconductor Capability.jmp");
Eval(EvalExpr(
biv << On Close(
Close(Expr(biv << Get Data Table), no save)
);
));
You could also possibly use function with On Close, but in this case it will generate more complicated code, as you won't have access to the bivariate platform's reference but rather to the window which has the bivariate, so you have to parse the window name which might or might not work (there might be a way to get reference to the platform inside the window).
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
biv = dt << Bivariate(Y(:Weight), X(:Height), Nonpar Density);
biv << On Close(function({this},
table_name = Trim Whitespace(Word(1, (this << Get Window Title), "-"));
If(Contains(Get Data Table List() << get name, table_name),
Close(Datatable(table_name), no save);
);
));
Challenge C: Clicking on a graph or report should trigger some action
Concept: Using << Make Row State Handler()
This had most different solutions and all were a bit different. Big challenge with this type of script is deciding on how you want to manage constantly changing row states. One option is to use a Button to trigger the action (like @Ressel did) instead of Row State Handler, this is in my opinion most robust option in this case.
Rest of the solutions did use row state handler and different ways (or not) managing the selected rows being changed all the time. One thing to note with Row State Handler is that it will return modified rows, not just selected rows. So if you are only interested in selected columns, you have to take that into account.
In most simple cases you can use something like @Georg gave as an answer.
f = Function({a},
dt << Subset(Selected Rows(1), Selected columns only(0))
);
rs = dt << make row state handler(f);
One option to manage the rows would be to create associative array (JMP allows using Matrix as key in Associative array) in which you collect the rows which have had an subset already created. This should work as long as you don't change row order or add/remove rows.
Below is a quick example using associative array to collect rows which have been subsetted. In the example I'm checking for rows which have row state 1 (selected row) and then create subset of those if it hasn't already been created. One benefit with this is, that you can also save the datatable references to the associative array and quicky access them all by with aa_subset_rows << Get Values;
but this solution might still be a bit buggy if many lines are being selected by holding and dragging mouse over them.
Names Default To Here(1);
// Open Data Table
dt = Open("$SAMPLE_DATA/Growth Measurements.jmp", invisible);
gb = dt << Graph Builder(
Size(522, 452),
Show Control Panel(0),
Legend Position("Bottom"),
Graph Spacing(8),
Variables(X(:Age), Y(:Growth), Overlay(:Subject)),
Elements(Line(X, Y, Legend(13)))
);
aa_subset_rows = Associative Array();
f = Function({rows_changed},
//Rowstate 1 is selected row
cur_rows = Loc(dt << Get Row States, 1);
//if no rows are selected, don't try to create subsets
If(N Items(cur_rows) == 0,
return()
);
//compare to previous to prevent opening extensive abmount of subsets
If(Contains(aa_subset_rows , cur_rows),
return();
);
dt_subset = dt << Subset(Output table("selected_rows"), Rows(cur_rows));
aa_subset_rows[cur_rows] = dt_subset;
);
rs = dt << make row state handler(f);
-Jarmo