2
$\begingroup$

I am trying to construct a simple form that comprises two essential parts. The first part, that comes before input fields is a question containing text (several paragraphs), matrix and so on. The second part is the form with radio buttons to select the right answer.

The second part is simple to do with the following (or similar code, here is only a simple example)

FormFunction[
 FormObject[<|
   "x" -> <|
     "Interpreter" -> {"A" -> 1, "B" -> 2},
     "Control" -> RadioButtonBar,
     "Label" -> "Select answer"
     |>|>], <function>,
AppearanceRules -> <| <some rules here> |>
]

The problem is that when deployed to Wolfram Cloud the above code generates a page that starts with input fields. The only way to put something before the input fields (here radio buttons) is to use

AppearanceRules -> <|
"Title"-> "Some title",
"Description" -> "Here some description"
|>

The title will be on the very top of the page and description below but before the input fields. There are two problems.

  1. AppearanceRules seems to be completely ignored if FormObject[] is used.
  2. I need Description to contain a couple of paragraphs of text and some simple other elements (like a table).

Questions:

  1. Can anyone confirm the first problem (I am using Mathematica 11.1 but this is cloud related so shouldn't matter)?
  2. What can be passed to Description? In particular, using ExportForm with PNG format I can create an image with text that is properly displayed but this seems like an overkill.
  3. What would be an optimal way to construct such a form? I feel that using FormFunction[] here is like overloading the intended purpose of the function.

Thanks for all help.

Edit.

As suggested by @b3m2a1 (thanks) I tried this.

FormFunction[
 {Style["Wow", "Title"],
  "This is a different character",
  "x" -> <|"Interpreter" -> {"A" -> 1, "B" -> 2},
    "Control" -> RadioButtonBar,
    "Label" -> "Select choice"|>},
 Identity,
 PageTheme -> "Blue"
 ]

This works producing the following form.

Form 1 (works)

However, when I add some other characters like in the following code (note the specific characters).

FormFunction[
 {Style["Wow", "Title"],
  "This is a different character śćńąśżź",
  "x" -> <|"Interpreter" -> {"A" -> 1, "B" -> 2},
    "Control" -> RadioButtonBar,
    "Label" -> "Select choice"|>},
 Identity,
 PageTheme -> "Blue"
 ]

I get the following results (fail).

enter image description here

There is obviously something wrong. The difference between the first working form and the second not working one are only the specific characters.

One thing that is not obvious to me is how can I add a mathematics as an element of description. In more general terms, suppose I want to add the following cell.

Cell[TextData[{
    "This is ",
    StyleBox["another",
      FontWeight -> "Bold"],
    " text. This is some mathematical notation ",
    Cell[BoxData[
       FormBox[
         RowBox[{
            RowBox[{"F", "(", "x", ")"}], "=", 
            RowBox[{
               SubsuperscriptBox["\[Integral]", 
                 RowBox[{"-", "\[Infinity]"}], "x"], 
               RowBox[{
                  RowBox[{"f", "(", "\[Tau]", ")"}], 
                  RowBox[{"\[DifferentialD]", "\[Tau]"}]}]}]}], 
      TraditionalForm]],
      FormatType -> "TraditionalForm"],
    ". "
   }], "Text"]

The capability of adding such elements solves my problem completely.

$\endgroup$
  • $\begingroup$ Use the list argument spec to FormObject. It can take text and stuff. I'll post an example when I can but here that is in action: wolframcloud.com/objects/mpmindex/PackageIndex/submit $\endgroup$ – b3m2a1 Aug 20 '17 at 17:14
  • $\begingroup$ Thank you for a hint. I've tried that but there are two problems with that. (1) How do I specify a type of control like RadialButtonBar? (2) It seems that the only way to use that is to have plain text or have graphics, meaning PNG or similar format. I can't get any styling on the text other then through a graphical format. $\endgroup$ – Michal Aug 20 '17 at 19:01
  • $\begingroup$ Also, I've just discovered that the plain text cannot contain any special characters like in some languages e.g. French, Swedish, Polish, because it leads to failure to convert the form to HTML. $\endgroup$ – Michal Aug 20 '17 at 19:06
  • $\begingroup$ You may be interested in 152218 $\endgroup$ – Kuba Aug 20 '17 at 21:02
  • $\begingroup$ @Kuba Thanks a lot. I used combination of ExportString[] and EmbeddedHTML[] with MathML format. Based on this I gave an answer to the question you pointed me to (152218). $\endgroup$ – Michal Aug 20 '17 at 21:48
5
$\begingroup$

Give this a try:

fo =
  FormFunction[{
    Style["Woopdoop", "Title"],
    "ü",
    EmbeddedHTML["</a href=\"plop\">à</a>"],
    "whee" -> <|
      "Interpreter" ->
       {"asd" -> 1, "asdasd" -> 2},
      "Control" -> RadioButtonBar
      |>
    },
   Null
   ];

ws = Quiet@HTTPHandling`StartWebServer[fo];
"http://localhost:7000" // SystemOpen

HTML

Some unicode characters clearly cause issues. We can get around this by exporting to XML first:

fo =
  FormFunction[{Style["Wow", "Title"],
    ExportString[
     XMLElement["p",
      {},
      {"This is a different character śćńąśżź"}],
     "XML"
     ],
    "x" -> <|"Interpreter" -> {"A" -> 1, "B" -> 2}, 
      "Control" -> RadioButtonBar, "Label" -> "Select choice"|>}, 
   Identity, PageTheme -> "Blue"];
ws = Quiet@HTTPHandling`StartWebServer[fo];
"http://localhost:7000" // SystemOpen

Math

As for math, you can use MathML pretty easily, as it has native support:

fo =
  FormFunction[{Style["Wow", "Title"],
    ExportString[
     XMLElement["p",
      {},
      {"This is a different character śćńąśżź"}],
     "XML"
     ],
    ExportString[
     Unevaluated[Integrate[a, {v, 0, Pi}]],
     "MathML"
     ],
    "x" -> <|"Interpreter" -> {"A" -> 1, "B" -> 2}, 
      "Control" -> RadioButtonBar, "Label" -> "Select choice"|>}, 
   Identity, PageTheme -> "Blue"];
ws = Quiet@HTTPHandling`StartWebServer[fo];
"http://localhost:7000" // SystemOpen

but I'm not gonna deny that's super ugly. On the other hand, any format a browser can read will work, so you can write something in XML and just export it.

Styled HTML

And we can also use this to add arbitrary styling. But we have to handle the fact that the basic XMLElement[_,{___, "style"->styleString, ___}, ___] method will fail. This implements correct element-specific style exports:

cssStyleBuild[rules_] :=
  StringRiffle[
   Replace[rules,
    (Rule | RuleDelayed)[k_, v_] :>
     (ToString[k] <> ":" <> ToString[v]),
    1
    ],
   "; "
   ];
styledXMLExport[xml_, styleRules_] :=
 With[{
   holdTokens =
    AssociationMap[
     CreateUUID,
     Keys[styleRules]
     ],
   styles =
    Association@
     Map[
      #[[1]] -> cssStyleBuild[#[[2]]] &,
      styleRules
      ]
   },
  StringReplace[
   ExportString[
    xml //.
     KeyValueMap[
      XMLElement[#, r_?(! KeyMemberQ[#, "style"] &), e_] :>
        XMLElement[#, Append[r, "style" -> #2], e] &,
      holdTokens
      ],
    "XML"
    ],
   KeyValueMap[
    "'" <> #2 <> "'" -> "\"" <> styles[#] <> "\"" &,
    holdTokens
    ]
   ]
  ]

And then we'll apply that here:

$styles =
  {
   "p" -> {
     "color" -> "blue"
     }
   };
fo =
  FormFunction[{Style["Wow", "Title"],
    styledXMLExport[
     XMLElement["p", {}, {"asdasd"}],
     $styles
     ],
    "x" -> <|"Interpreter" -> {"A" -> 1, "B" -> 2}, 
      "Control" -> RadioButtonBar, "Label" -> "Select choice"|>}, 
   Identity, PageTheme -> "Blue"];
ws = Quiet@HTTPHandling`StartWebServer[fo];
"http://localhost:7000" // SystemOpen

Now you can use styled arbitrary HTML in your text blocks.

$\endgroup$
  • $\begingroup$ Thank you for a hint. Please, take a look at the edit. $\endgroup$ – Michal Aug 20 '17 at 20:48
  • $\begingroup$ Thank you very much! I will try out the above approach. I accept the answer. $\endgroup$ – Michal Aug 20 '17 at 21:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.