cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
shampton82
Level VII

Dynamic list of buttons linked to scripts in a folder

Hey JMP crew!

I was hoping to get some guidance on how I might be able to have a dynamic window with buttons that would link to whatever scripts are in a referenced folder.  So if I had two scripts in the folder, I would have a window with two button boxes.  If I had 50 then I would have 50 button boxes.  Ideally there might be a way to dynamically tell the window how many "columns" to arrange the button boxes in.

 

Any help would be appreciated!

 

Steve

3 ACCEPTED SOLUTIONS

Accepted Solutions
txnelson
Super User

Re: Dynamic list of buttons linked to scripts in a folder

Here is a sample using the scripts installed as samples for JMP.  The directory reference needs to be changed from JMPPRO to JMP if you do not have JMPPRO.  Also the version number 18 needs to be changed to your version number.

Names Default To Here( 1 );
dir = "C:\Program Files\JMP\JMPPRO\18\Samples\Scripts";
files = Files In Directory( dir );
For( i = N Items( files ), i >= 1, i--,
	If( Word( -1, files[i], "." ) != "jsl",
		Remove From( files, i, 1 )
	)
);
theExpr = "";
For Each( {scr}, files,
	theExpr = theExpr || ",ButtonBox(\!"" || Word( -2, scr, "./\" ) || "\!", include(\!""
	 || dir || "\" || scr || "\!") )"
);
Eval(
	Parse(
		"nw = New Window( \!"Scripts\!",
			Outline Box( \!"Select Script to Run\!",
				Lineup Box( N Col( 4 )"
		 || theExpr || " )
			)
		);"
	)
);

txnelson_0-1720735205706.png

I prefer not to use the Eval(Parse()) methodology, however it proved to be too late in the day for me to work through a more readable syntax version.  This method does the job.  Look for other Community Members to improve on my code.

Jim

View solution in original post

jthi
Super User

Re: Dynamic list of buttons linked to scripts in a folder

A bit different version of Jim's code (Filter Each to get list of .jsl files, Eval(EvalExpr()) to append buttons with the paths)

Names Default To Here(1);
dir = "$SAMPLE_SCRIPTS/";
dir = Convert File Path(dir, windows);

files = Files In Directory(dir);
jslfiles = Filter Each({filename}, files, Word(-1, filename, ".") == "jsl");


// Not sure how you would like to determine column count, but with Lineup box it is fairly easy
lub = Lineup Box(N Col(4));


For Each({filename}, jslfiles,
	Eval(EvalExpr(
		lub << Append(Button Box(filename,
			nw = New Window(Expr(filename),
				Script Box(Load Text File(Expr(dir || filename)), "JSL", 600, 600)
			);
		));
	));
);


nw = New Window("Scripts in " || dir,
	Outline Box("Click to Open a Script",
		lub	
	);
);

Depending on what you are doing, you might also consider having function/expression which each of the buttons call. Doing it in robust manner does take a bit of extra work though, so knowing how to create these simpler solutions is always a good idea.

-Jarmo

View solution in original post

jthi
Super User

Re: Dynamic list of buttons linked to scripts in a folder

This might give an idea how you can do it

Names Default To Here(1);

init_cols = 4;

dir = "$SAMPLE_SCRIPTS/";
dir = Convert File Path(dir, windows);

files = Files In Directory(dir);
jslfiles = Filter Each({filename}, files, Word(-1, filename, ".") == "jsl");


// Not sure how you would like to determine column count, but with Lineup box it is fairly easy
lub = Lineup Box(N Col(init_cols));


For Each({filename}, jslfiles,
	Eval(EvalExpr(
		lub << Append(Button Box(filename,
			nw = New Window(Expr(filename),
				Script Box(Load Text File(Expr(dir || filename)), "JSL", 600, 600)
			);
		));
	));
);


nw = New Window("Scripts in " || dir,
	Outline Box("Click to Open a Script",
		V List Box(
			Lineup Box(N Col(2),
				Button Box("Press to update Col count", << Set Function(function({this}, 
					lub << N Col((this << sib) << get)
				))),
				Number Edit Box(init_cols)
			),
			lub	
		)
	);
);

Number Edit Box can also trigger on commit (<< Set Function()) / change (<< Set Number Changed()) so you don't necessarily need a button

-Jarmo

View solution in original post

6 REPLIES 6
txnelson
Super User

Re: Dynamic list of buttons linked to scripts in a folder

Here is a sample using the scripts installed as samples for JMP.  The directory reference needs to be changed from JMPPRO to JMP if you do not have JMPPRO.  Also the version number 18 needs to be changed to your version number.

Names Default To Here( 1 );
dir = "C:\Program Files\JMP\JMPPRO\18\Samples\Scripts";
files = Files In Directory( dir );
For( i = N Items( files ), i >= 1, i--,
	If( Word( -1, files[i], "." ) != "jsl",
		Remove From( files, i, 1 )
	)
);
theExpr = "";
For Each( {scr}, files,
	theExpr = theExpr || ",ButtonBox(\!"" || Word( -2, scr, "./\" ) || "\!", include(\!""
	 || dir || "\" || scr || "\!") )"
);
Eval(
	Parse(
		"nw = New Window( \!"Scripts\!",
			Outline Box( \!"Select Script to Run\!",
				Lineup Box( N Col( 4 )"
		 || theExpr || " )
			)
		);"
	)
);

txnelson_0-1720735205706.png

I prefer not to use the Eval(Parse()) methodology, however it proved to be too late in the day for me to work through a more readable syntax version.  This method does the job.  Look for other Community Members to improve on my code.

Jim
shampton82
Level VII

Re: Dynamic list of buttons linked to scripts in a folder

@txnelson You may not feel it is the cleanest code but it works wonderfully!  Thanks for the help and quick response!!

 

Steve

lala
Level VII

Re: Dynamic list of buttons linked to scripts in a folder

2024-07-12_11-37-07.png

jthi
Super User

Re: Dynamic list of buttons linked to scripts in a folder

A bit different version of Jim's code (Filter Each to get list of .jsl files, Eval(EvalExpr()) to append buttons with the paths)

Names Default To Here(1);
dir = "$SAMPLE_SCRIPTS/";
dir = Convert File Path(dir, windows);

files = Files In Directory(dir);
jslfiles = Filter Each({filename}, files, Word(-1, filename, ".") == "jsl");


// Not sure how you would like to determine column count, but with Lineup box it is fairly easy
lub = Lineup Box(N Col(4));


For Each({filename}, jslfiles,
	Eval(EvalExpr(
		lub << Append(Button Box(filename,
			nw = New Window(Expr(filename),
				Script Box(Load Text File(Expr(dir || filename)), "JSL", 600, 600)
			);
		));
	));
);


nw = New Window("Scripts in " || dir,
	Outline Box("Click to Open a Script",
		lub	
	);
);

Depending on what you are doing, you might also consider having function/expression which each of the buttons call. Doing it in robust manner does take a bit of extra work though, so knowing how to create these simpler solutions is always a good idea.

-Jarmo
shampton82
Level VII

Re: Dynamic list of buttons linked to scripts in a folder

@jthi and @txnelson If I could pick your brains one more time on this:

 

If I wanted to add in a number edit box that had the value for the Line up box and then a button box to press that would apply the value in the number edit box to change the orientation of the script buttons in the window how would that look?

 

So something like this

shampton82_0-1720804211117.png

 

jthi
Super User

Re: Dynamic list of buttons linked to scripts in a folder

This might give an idea how you can do it

Names Default To Here(1);

init_cols = 4;

dir = "$SAMPLE_SCRIPTS/";
dir = Convert File Path(dir, windows);

files = Files In Directory(dir);
jslfiles = Filter Each({filename}, files, Word(-1, filename, ".") == "jsl");


// Not sure how you would like to determine column count, but with Lineup box it is fairly easy
lub = Lineup Box(N Col(init_cols));


For Each({filename}, jslfiles,
	Eval(EvalExpr(
		lub << Append(Button Box(filename,
			nw = New Window(Expr(filename),
				Script Box(Load Text File(Expr(dir || filename)), "JSL", 600, 600)
			);
		));
	));
);


nw = New Window("Scripts in " || dir,
	Outline Box("Click to Open a Script",
		V List Box(
			Lineup Box(N Col(2),
				Button Box("Press to update Col count", << Set Function(function({this}, 
					lub << N Col((this << sib) << get)
				))),
				Number Edit Box(init_cols)
			),
			lub	
		)
	);
);

Number Edit Box can also trigger on commit (<< Set Function()) / change (<< Set Number Changed()) so you don't necessarily need a button

-Jarmo