Message Boards Message Boards

CloudDeploy Example: Custom FromFunction Design for Gas Pressure

Posted 8 years ago

Background Information

The attached notebook provides examples of how to stylize for a FormFunction[] of CloudDeploy[].

The deployed function is HERE on the Wolfram cloud.

The attached notebook specifically demonstrates the following by example:

  1. How to nicely format numbers having large exponents in input fields;

  2. How to nicely format numbers having large exponents in results;

  3. How to adjust the size of an input field;

  4. How to get subscripts within FormFunction text;

  5. How to get overbars on characters within FormFunction text;

  6. How to stylize elements inside the FormFunction[ ];

  7. How to do a layout within FormFunction[ ], including embedding the result and avoid a submit button (the FormPage[ ] function is much less controllable, so its functionality is reproduced within the FormFunction[ ] approach used herein);

  8. How to display equations in a visually appealing way in vector graphics.

The attached notebook also answers my questions previously posted here.

Set Up: Options

Allow any member of the public to use the FormFunction's (i.e., does not require log in through Wolfram community)

cloudDeployOptions = {Permissions -> "Public"}
Out[]= {Permissions -> "Public"}

Width of InputField in the deployed FormFunction's

inputFieldSize = 25
Out[]= 25

Precision of numbers in the Input (i.e., InputField's) in the deployed FormFunction's

inputPrecision = 6
Out[]=6

Precision of numbers in the Output of the deployed FormFunction's

outputPrecision = 6
Out[]=6

Set Up: Functions

Formatting Expressions

  • toFormForInputField

Convert numbers to FortranForm (e.g., for InputField's). Avoid long numbers with many decimals points by using SetPrecision within ToString.

toFormForInputField[value : _Missing] := ""

(* 1. How to nicely format numbers having large exponents in input fields *)

toFormForInputField[value : _?NumberQ] := 
 ToString[SetPrecision[value, inputPrecision], FortranForm]
  • toFormForOutput

Show either as '0.0025' for exponents of 4 and smaller or in superscript form of '2.5 10^-6' for larger exponents. This function is basically a customized version of NumberForm.

(* 2. How to nicely format numbers having large exponents in results *)

toFormForOutput[value : _] :=

 Module[
  {mantissaExponent, mantissa, exponent, 
   numericalValue = SetPrecision[N[value], outputPrecision]},

  CompoundExpression[
   mantissaExponent = MantissaExponent[numericalValue],
   mantissa = 10 First@mantissaExponent,
   exponent = Last@mantissaExponent - 1,
   If[
    (*if*)
    -4 <= exponent <= 4,
    StringTemplate["`1`"][numericalValue],
    (*else*)

    StringTemplate["`1` \[Times] 10<sup>`2`</sup>"][mantissa, exponent]
    ]
   ]
  ]

Input Fields

See FormObject[] and Interpreter[] (e.g., tied also to "Control" for something fancy like an 'Image' in 'guide/InterpretingStrings').

inputField[deployVariable : _String, label : _String | _Style, 
  initialInput : _String | _Missing, 
  interpreter : _ : Restricted["Real", {0, Infinity}]] :=

 deployVariable ->
  <|
   "Label" -> label,
   (* 3. How to adjust the size of an input field [I picked up this hint on the forums] *)

   "Control" -> Function[InputField[##, FieldSize -> inputFieldSize]],
   "Input" -> initialInput,
   "Interpreter" -> interpreter (* declared default if omitted: Restricted[
   "Real",{0,Infinity}] *)
   |>

HTML templates

  • Basic elements of bold, italics, superscript, and subscript

    CompoundExpression[
    (* 4. How to get subscripts within FormFunction text (i.e., mix in HTML coding such as <sub>character</sub>)*)
    (* 5. How to get overbars on characters within FormFunction text (i.e., mix in CSS coding such as "<span style=\"text-decoration:overline\">character</span>")*)
    htmlBoldTemplate=StringTemplate["<b>`1`</b>"] (* [expression] *),
    htmlItalicsTemplate=StringTemplate["<i>`1`</i>"] (* [expression] *),
    htmlSubscriptTemplate=StringTemplate["<sub>`1`</sub>"] (* [expression] *),
    htmlSuperscriptTemplate=StringTemplate["<sup>`1`</sup>"] (* [expression] *)
    ];
    
  • Assembled elements - level 1

    htmlSubscriptItalicsTemplate=StringTemplate["<* htmlItalicsTemplate[#1] *><* htmlSubscriptTemplate[#2] *>"] 
    (* [symbol, subscript] *) ;
    
    htmlSuperscriptItalicsTemplate=StringTemplate["<* htmlItalicsTemplate[#1] *><* htmlSuperscriptTemplate[#2] *>"] 
    (* [symbol, subscript] *) ;
    
  • Assembled elements - level 2

    htmlTermListTemplate=StringTemplate["<* htmlSubscriptItalicsTemplate[#1,#2] *>, `3`"] 
    (* [symbol, subscript, name] *);
    
    htmlInputLabelTemplate=StringTemplate["<* htmlSubscriptItalicsTemplate[#1,#2] *> (<* StringRiffle[#3] *>)"] 
    (* [symbol, subscript, {units}] *);
    
    htmlResultTemplate=StringTemplate["<* htmlSubscriptItalicsTemplate[#1,#2] *> = `3` <* StringRiffle[#4] *>"] 
    (* [symbol, subscript, result, {units}] *);
    

HTML functions with styles included

  • For term list:

    htmlTermList[name:_String,symbol:_String,symbolSubscript:_String]:=
    Style[htmlTermListTemplate[name,symbol,symbolSubscript],termStyle]
    
  • For label on input field:

    htmlInputLabel[symbol:_String,symbolSubscript:_String:""]:=
    Style[htmlSubscriptItalicsTemplate[symbol,symbolSubscript],inputLabelStyle]
    
    htmlInputLabel[symbol:_String,symbolSubscript:_String,units:_List]:=
    Style[htmlInputLabelTemplate[symbol,symbolSubscript,units],inputLabelStyle]
    
  • For formatting output:

    htmlResult[symbol:_String,symbolSubscript:_String,result:_?NumberQ,units:_List]:=
    Style[htmlResultTemplate[symbol,symbolSubscript,toFormForOutput@result,units],outputStyle]
    
    htmlResult["P",result:_?NumberQ]:=htmlResult["P","",result,units["P"]]
    

Styles

(* 6. How to stylize elements inside the FormFunction[] *)
CompoundExpression[
baseFontFamily="Arial",
titleStyle={FontWeight->Bold,FontColor->Orange,FontSize->18,FontFamily->baseFontFamily},
sectionStyle={FontWeight->Bold,FontColor->Black,FontSize->14,FontFamily->baseFontFamily},
textStyle={FontWeight->Plain,FontColor->Black,FontSize->12,FontFamily->baseFontFamily},
termStyle=textStyle,
outputStyle=textStyle,
inputLabelStyle=textStyle,
equationStyle=textStyle
];

Fixed Strings

Commonly used HTML components

inverseCubicMeter=StringTemplate["m<* htmlSuperscriptTemplate[\"-3\"] *>"] [];

Text["..."]

  • Sections

Use 'sectionStyle'.

(* 6 cont'd. How to stylize elements inside the FormFunction[] *)
CompoundExpression[
text["Equation"]=Style["Equation",sectionStyle],
text["Input"]=Style["Input",sectionStyle],
text["Output"]=Style["Output",sectionStyle],
text["TermList"]=Style["Term List",sectionStyle],
text["Reference"]=Style["Reference",sectionStyle]
];
  • Text Lines

Use 'textStyle'.

text["EnterAllValues"]=Style["Adjust values in input fields and hit ENTER",textStyle]

Adjust values in input fields and hit ENTER

  • Miscellaneous

    CompoundExpression[
    text["NewLine"]="<br>"
    ];
    

Units List

CompoundExpression[
units["Ng"]={inverseCubicMeter},
units["P"]={"Pa"},
units["T"]={"K"}
];

Input Labels

Function 'htmlInputLabel' applies 'inputLabelStyle'

CompoundExpression[
input["Ng"]=htmlInputLabel["N","g",units["Ng"]],
input["T"]=htmlInputLabel["T","",units["T"]]
];

Term List

Function 'htmlTermList' applies 'termStyle'

CompoundExpression[
term["k"]=htmlTermList["k","","Boltzmann Constant"],
term["Ng"]=htmlTermList["N","g","Molecular Number Concentration"],
term["P"]=htmlTermList["P","","Pressure"],
term["T"]=htmlTermList["T","","Temperature"]
];

CloudDeploy[] the FormFunction[]

formObject

This function constructs the interface, including present values of the inputs and the solved quantity (by calling on FormSolver[ ]).

formObject[temperature:_,numberConcentration:_]:=

With[
{
(* input fields on form including present values *)
function1InputField=inputField["temperature",input["T"],toFormForInputField[temperature]],

function2InputField=inputField["numberConcentration",input["Ng"],toFormForInputField[numberConcentration]]
},

With[
{
formSpecification=
{
(* START FORM *)

(* 7. How to do a layout within FormFunction[],including embedding the result and avoid a submit button: SEE BELOW  *)

(* Title *)
Style["Gas Pressure",titleStyle],text["NewLine"],text["NewLine"],

(* Equation *)
(* 8. How to display equations in a visually appealing way in vector graphics: use ExportString as SVG [I picked up this hint on the forums] *)
text["Equation"],text["NewLine"],ExportString[Style["P = kTSubscript[N, g]",equationStyle],"SVG"],text["NewLine"],text["NewLine"],

(* Input *)
text["Input"],text["NewLine"],text["EnterAllValues"],text["NewLine"],function1InputField,
function2InputField,text["NewLine"],

(* Output *)
text["Output"],text["NewLine"],
formSolver[temperature,numberConcentration],text["NewLine"],text["NewLine"],

(* Term List *)
text["TermList"],text["NewLine"],term["P"],text["NewLine"],term["k"],text["NewLine"],term["T"],text["NewLine"],term["Ng"],text["NewLine"],text["NewLine"],

(* Reference *)
text["Reference"],text["NewLine"],
Style["Equation 2-43 of W. Kauzmann, <i>Kinetic Theory of Gases</i>, Benjamin: New York, 1966.",textStyle],text["NewLine"],text["NewLine"]

(* END FORM *)

}
},

FormObject[formSpecification,AppearanceRules->{"SubmitLabel"->None}]
]
]

formSolver

This function provides the target quantity based on the missing input (Missing["NoInput"]).

With[
{boltzmannConstant=1.38 10^-23},

formSolver[temperature:_,numberConcentration:_]:=

htmlResult["P",boltzmannConstant temperature numberConcentration]
]

formFunction

Here the FormFunction is defined as an interface of 'formObject' and call back to itself, i.e., to update solved quantity and its value based on input quantities and values.

formFunction[temperature:_,numberConcentration:_]:=

FormFunction[

(* interface construction *)
formObject[temperature,numberConcentration],

(* function to execute, i.e., a call back to itself *)
formFunction[#temperature,#numberConcentration]&
]

Deploy to Cloud

Deploy the FormFunction to the Wolfram Cloud.

CloudDeploy[
(* function to deploy, including initial values *)
formFunction[293.15,2.50347*^25],
(* location to deploy *)
"PressureDemo",
(* options, such as public permissions *)
Sequence@@cloudDeployOptions
]

Please see the attached notebook for a convenient code summary.

Attachments:
POSTED BY: Scot Martin
5 Replies

Hi,

First of all it's great to see our little function being put to such good use, I really like the form you've deployed!

I've noticed you use bare HTML tags in your form. Please note that the fact that doing that works at all right now is a serious bug and your form will probably break in the next week or two. The right way to use HTML in a form (or template) is by using EmbeddedHTML, which tells the templating engine not to escape the tags.

Another thing you might want to be aware of is the $Permissions global variable that you can set to "Public" directly. This way you won't have to pass options to CloudDeploy.

And lastly (but I'm sure you've already know about this) a style suggestion.

CompoundExpression[
    a,
    b
]

is exactly equivalent to

a;
b

which is, in my opinion, a bit more readable.

Thanks!

Carlo

POSTED BY: Carlo Barbieri

Thanks Scot...this is very useful!

POSTED BY: Aeyoss Antelope

enter image description here - you have earned "Featured Contributor" badge, congratulations !

This is a great post and it has been selected for the curated Staff Picks group. Your profile is now distinguished by a "Featured Contributor" badge and displayed on the "Featured Contributor" board.

POSTED BY: EDITORIAL BOARD
Posted 8 years ago

Carlo,

That is really an excellent (and important!) hint about EmbeddedHTML[ ]. Thank you for that. I'll put it to use right away so that my code becomes compliant with the expected upcoming updates that you mentioned.

I hope you could give a hint or solution on two other items that I have struggled with and that still stump me:

  1. For the following function, how can I stylize InputField[ ], e.g., to change the field color to yellow?

    inputField[deployVariable : _String, label : _String | _Style, 
      initialInput : _String | _Missing, 
      interpreter : _ : Restricted["Real", {0, Infinity}]] :=
    
     deployVariable ->
      <|
       "Label" -> label,
       (* 3. How to adjust the size of an input field [
       I picked up this hint on the forums] *)
       "Control" -> Function[InputField[##, FieldSize -> inputFieldSize]],
       "Input" -> initialInput,
       "Interpreter" -> interpreter (* declared default if omitted: 
       Restricted["Real",{0,Infinity}] *)
       |>
    

1a. I tested the normal options listed in Options[InputField], such as Rule[Background,Yellow], but these options do not appear to work (i.e., the color is still white) after CloudDeploy[]. In fact, of all the Options[InputField], the only option tested by me that appears to work is FieldSize.

1b. Related to this question, an actual call to the foregoing function returns something like the following on the Wolfram Cloud (i.e., via view source):

<input type="text" value="293.15" size="25" class="form-control" name="temperature" id="id_temperature" data-field-name="Real" data-field-type="Structured" data-field-verbose="real number"/>

Question - How can I pass through some styling in the Wolfram framework of the options and their specifications so that I would get a return like the following in the produced HTML on the cloud. That is, how can I pass through verbatim ' style="background-color: yellow;" ' to get included within <input>?

 <input type="text" style="background-color: yellow;" value="293.15" size="25" class="form-control" name="temperature" id="id_temperature" data-field-name="Real" data-field-type="Structured" data-field-verbose="real number"/>

.2. More generally, how can I associate my own CSS style sheet with the return from FormFunction[ ] ?

Thank you! I am looking forward to your hints and solutions!

Scot

POSTED BY: Scot Martin
Posted 8 years ago

Hello @Scot Martin and @Carlo Barbieri, the link that Scot gave us in his post (https://www.wolframcloud.com/objects/user-9a32cd4b-ac8e-41b8-a00d-a9bf698ed3b0/PressureDemo) works great in my Windows PC, however it does not work from my iPad or iPhone: I am able to change the numbers, however the calculation is Not performed after hitting Enter (the Enter key in the iPhone/iPad screen actually becomes labeled "ir", which is Spanish for "Go", I am in Mexico). I really really really want to use Wolfram Development Platform to create interactive web pages to be used from mobile phones and tablets of any brand and operative system, will I be able to do it? do you know why this example (and others, even simple ones) do not work properly from my iPad and iPhone? Does this happen with any mobile device? Thank you

POSTED BY: Jose Gomez
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract