cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Try the Materials Informatics Toolkit, which is designed to easily handle SMILES data. This and other helpful add-ins are available in the JMP® Marketplace
Choose Language Hide Translation Bar
Combined and Connected Number Edit Box and Slider Box
Problem

In many situations, when you are using a slider box to control a numeric variable, you also want a editable number display to display the value of the variable, and that allows you to manually set the value of the variable.  

 

The current way to do this is to create two display objects: a Number Edit Box() and a Slider Box().  You have to code this in such a way that they are connected.  In addition, the way the number edit box interacts with changes to manually entered values (using <<Set Function())  is different than the way the Slider Box works (providing an expression as an argument to the display box that runs evertime the slider is moved).

 

I often find myself having to take a lot of time reading the scripting guide on how to create these objects and how to connect them. (I wish there were an built in JMP display object like this)

Solution

I have created a function SliderNumberEditBox() that creates an evaluated expression that creates both display boxes together. These display boxes will be connected as described above.  It takes as arguments character strings that define the references to the Number Edit Box, the initial value for the Number Edit Box, the reference to the Slider Box, the upper and lower range for the slider box, the variable that is controlled by the slider box, and optionally, the expression you want to run when the Number Edit Box is updated manually, and the expression you want to run when the Slider Box is changed.  (note that the expressions must be defined as character strings, and the appropriate escape sequences must be used for reserved characters that you want quoted inside the string).  


SliderNumberEditBox = Function( {nebref, nebinitval, sbref, sblower, sbupper, sbvar, nebFunction = "", sbFunction = ""}, 

	Eval(
		Parse(

			"H List Box(" || nebref || " = Number Edit Box(" || nebinitval || ",
		<<Set Function(
			Function( {this}," || sbref ||
			" << set( this << get );" || nebFunction || "
			)
		)
	)," || sbref || "= Slider Box(" || sblower || "," || sbupper || ","
			 || sbvar || "," || nebref || " << Set( " || sbvar || " );" || sbFunction || "
	)
)
"
		)
	)
);
The function uses string concatenation to create the entire string version of the expression for the display boxes, and then parses the string into an expression and returns the evaluated expression.
Syntax

SliderNumberEditBox(string for the reference to the number edit box, string for the initial value of the number edit box, string for the reference to the slider box, string for the lower range of the slider, string for the upper range of the slider, string for the variable controlled by the slider, <string representation of the expresssion you want to evaluate when the number edit box is manually changed>, <string representation of the expression you want to evaluate when the slider box is changed>)

 
k = 1;
SliderNumberEditBox(
			"_neb1",
			Char( k ),
			"_sb1",
			"0",
			"2",
			"k")
returns the evaluated expression below
H List Box(
	_neb1 = Number Edit Box(
		0.5,
		<<Set Function( Function( {this}, _sb1 << set( this << get ) ) )
	),
	_sb1 = Slider Box( 0, 2, k, _neb1 << Set( k ) )
)
Example
SliderNumberEditBox = Function( {nebref, nebinitval, sbref, sblower, sbupper, sbvar, nebFunction = "", sbFunction = ""}, 

	Eval(
		Parse(

			"H List Box(" || nebref || " = Number Edit Box(" || nebinitval || ",
		<<Set Function(
			Function( {this}," || sbref ||
			" << set( this << get );" || nebFunction || "
			)
		)
	)," || sbref || "= Slider Box(" || sblower || "," || sbupper || ","
			 || sbvar || "," || nebref || " << Set( " || sbvar || " );" || sbFunction || "
	)
)
"
		)
	)
);

k = 1;
_nw = New Window( "Slider Number Edit Box",
	_vlb = V List Box(
		SliderNumberEditBox(
			"_neb1",
			Char( k ),
			"_sb1",
			"0",
			"2",
			"k",
			"
_tb << delete;
_vlb << Append(
	_tb=Text Box(\!"The number is \!" || char(k))
)",
			"
_tb << delete;
_vlb << Append(
	_tb=Text Box(\!"The number is \!" || char(k))
)"
		),
		_tb = Text Box( "The number is " || Char( k ) )
	)
);

creates a window that looks like this (I changed the slider box to a different value)

2018-03-31_20-46-33.png

Comments

Cool! You can set the contents of a text box without recreating it, which makes the example easier to read:

k = 1;
_nw = New Window( "Slider Number Edit Box",
	_vlb = V List Box(
		SliderNumberEditBox(
			"_neb1",
			Char( k ),
			"_sb1",
			"0",
			"2",
			"k",
			"_tb << settext(\!"The number is \!" || char(k))",
			"_tb << settext(\!"The number is \!" || char(k))"
		),
		_tb = Text Box( "The number is " || Char( k ) )
	)
);

I wooder if I should add to the "JMP Wish List" that the Slider Box() have an option to have a connected Number Edit Box(), or that a new display object be created that does this function does.

I was looking through the Community for some good examples of using Eval/Eval Expr when I came accross this and thought I would share my implementation of the SliderNumberEditBox function that uses expression building rather than string concatenation.

Many of the arguments passed into the function are no longer strings and there is now an option nsName argument for providing the name of the namespace the variables should exist (defaults to global).

SliderNumberEditBox = Function( {nebref, nebinitval, sbref, sblower, sbupper, sbvar, 
				nsName = "global", nebFunction = Expr(), sbFunction = Expr()}, 
  Eval( // evaluate to create the diplay boxes
    Eval Expr( // evaluate everything wrapped with Expr()
      H List Box(
        // Create the Number Edit Box
        // As Scoped() is used when the variable names are to be dynamic
        As Scoped( Expr( nsName ), Expr( nebref ) ) = Number Edit Box(
          Expr( nebinitval ),
          <<Set Function(
            Function( {this},
              As Scoped( Expr( nsName ), Expr( sbref ) ) << set( this << get );
              Expr( // Get the contents of the expression without evaluating it
                Name Expr( nebFunction )
              );
            )
          )
        ),
        // Create the Slider Box, with the given name
        As Scoped( global, Expr( sbref ) ) = Slider Box(
          Expr( sblower ),
          Expr( sbupper ),
          As Scoped( Expr( nsName ), Expr( sbvar ) ), 
          As Scoped( Expr( nsName ), Expr( nebref ) ) << Set( As Scoped( Expr( nsName ), Expr( sbvar ) ) );
          Expr(
            Name Expr( sbFunction )
          );
        )
      )
    )
  )
);

k = 1;

_nw = New Window( "Slider Number Edit Box",
  _vlb = V List Box(
    SliderNumberEditBox(
      "_neb1",  // NumberEditBox variable name
      k,        // Initial value
      "_sb1",   // SliderBox variable name
      0,        // Min value
      2,        // Max value
      "k",      // SliderBox value variable name
      "global", // Namespace name for symbols
      Expr(     // NumberEditBox function (as an expression)
        _tb << settext( "The number is " || Char( k ) )
      ),
      Expr(     // SliderBox function (as an expression)
        _tb << settext( "The number is " || Char( k ) )
      )
    ),
    _tb = Text Box( "The number is " || Char( k ) )
  )
);

 Anyone interested in more about expression building might check out @ih's post in the JSL Cookbook: Insert one expression into another using Eval Insert, Eval Expr, Parse, and Substitute

JSL Cookbook

If you’re looking for a code snippet or design pattern that performs a common task for your JSL project, the JSL Cookbook is for you.

This knowledge base contains building blocks of JSL code that you can use to reduce the amount of coding you have to do yourself.

It's also a great place to learn from the experts how to use JSL in new ways, with best practices.