57
$\begingroup$

Update

Since more and more issues are revealed as I venture deeper into the world of CDF, I decided to make this thread more general and hopefully more useful. I now posted my findings as an answer, but please feel free to edit this post or my answer below if you know something useful.

Questions

I have a quite large project that I want to deploy to the web. I expect users to only have the browser plugin or Mathematica Player, but not Player Pro.

  1. Can I use DynamicModule in a CDF that is to be viewed by the plugin or the Mathematica Player? Does it always have to be a Manipulate in focus in the dynamic interface that is generated?
  2. Can I deploy the dynamic output somehow without piling all the used functions and data into the DynamicModule-s body or Initialization option? Manipulate has the option SaveDefinitions but DynamicModule does not. Does SaveDefinitions work with packaged functions as well?
  3. What exactly happens when only the dynamic output is selected and deployed (and not the whole document) to CDF via the wizard? What is the difference between deploying only the output or deploying the whole notebook, but with all the code cells being hidden? What is the technical difference between demonstrations and CDFs?
  4. Is there any difference (and if so, what) between Mathematica Player, Player Pro and the browser plugin?
  5. What are the differences between CDFs intended for Mathematica Player or Player pro, i.e. free CDFs and non-free CDFs (see discussion here)?
  6. How to overcome security issues (discussed here and here): when the deployed CDF shows up as a gray box because dynamic updating is disabled for security reasons?
$\endgroup$
10
  • $\begingroup$ You say you deployed the code, but I think you should deploy the executed code, i.e., the resulting panel. This will include your package (probably only the functions you actually call). This can't be done in runtime with Needs as you do it now. $\endgroup$ Apr 6, 2012 at 6:26
  • $\begingroup$ No, I have deployed the output, just as it is done in the video. While Mathematica opens and displays the cdf correctly, neither Player nor plugin succeeds to load the packaged function. $\endgroup$ Apr 6, 2012 at 7:05
  • $\begingroup$ Has the function perhaps attribute ReadProtected? $\endgroup$ Apr 6, 2012 at 18:41
  • $\begingroup$ @SjoerdC.deVries: Only Protected, nothing extra. $\endgroup$ Apr 6, 2012 at 20:22
  • 1
    $\begingroup$ @IstvánZachar I would change this so that Manipulate is the outer most Head. I have done this before with a complex nested TabView that called functions. I wrapped Manipulate around it with SaveDefinitions -> True and ran it in fullscreen mode and it worked on a web page. $\endgroup$ Apr 7, 2012 at 2:28

3 Answers 3

32
$\begingroup$

Actually this is just meant as a side note to your own answer, but it became too long for a comment. As you can guess I'm interested in this myself and have done some testing, most of what I mentioned is from that experience. It has been reported that there would be differences in what the player would allow depending on whether Mathematica is installed or not. I don't believe that this is true, at least not by design, but as of now this is one of the things I have not explicitly checked..

I think some of the confusion about what can be done in a CDF format comes from the fact that one has to make a distinction between:

  1. CDF as a format
  2. restrictions of the Wolfram Player Pro (called Mathematica Player Pro for vs. 6 and 7)
  3. restrictions of the free CDF-Player
  4. restrictions of the browser plugin (full window mode)
  5. restrictions of the browser plugin (embedded cdf in html)
  6. restrictions of the pre version 8 Mathematica Reader
  7. restrictions of the demonstration site

and of course it doesn't help that some of the WRI documentation seems to not be very precise concerning these distinctions. The most relevant statement on restrictions seems to be this, from here

Can I use any Mathematica functionality that I want?

Yes. Almost all of Mathematica's computational functions can be incorporated into CDFs. However, in files saved straight out of Mathematica 8 for the free CDF Player, some functionality is not available: non-numeric input fields, dialog windows, and data import and export (except from Wolfram-curated data sources, e.g. ChemicalData, CountryData, and WordData). Please contact us about activating higher-level application content in CDFs.

To me it looks like the CDF format itself does not imply any restrictions, meaning that when you open a CDF document with a full version of Mathematica, it just behaves like a normal notebook (NB) file. The main difference seems to be a signature that is added to the CDF but not the NB files. I guess it is this signature that will be checked by the various players to see which restrictions are to be used when e.g. showing the dynamic content. While saving with Mathematica will create a signature that will only let the free CDF player use some functionality, it seems possible (but only by WRI) to create signatures that will allow the free CDF-Player to allow more or all (?) functionality. It is most probably this possibility that they are calling "activate higher-level application content in CDFs" or "CDFs with enhanced functionality". You would need to contact WRI to make use of that possibility, of course. This is a very different approach from using the Wolfram Player Pro, which already could show and play dynamic content within normal notebook files in earlier versions and of course can do so with CDF files as well. Unlike the CDF-Player, the Wolfram Player Pro will even allow shift-return-evaluations and import and export external files, including loading packages, which must be Encoded, though.

I think you got the restrictions mostly sorted right by now in your own answer, except for some details:

Complex Functions

I think the restriction that only a very limited set of functions is allowed in dynamic content of a CDF document is only enforced for the CDF browser plugin, but the standalone free CDF Player will run dynamic content that makes use of almost every function. The CDF will then be shown with a warning header about potentially dangerous content but after explicitly enabling dynamics there the dynamic content will work alright. Unlike mentioned elsewhere I also don't think that the way how you create the CDF document will make a difference concerning these restrictions. It is the use of the CDF browser plugin for showing that document that makes a difference. If you deploy to be embedded in html the formatting of the CDF document will be slightly changed to something more condensed. But when opening the CDF document created that way with the standalone CDF Player, it behaves mostly like one that is deployed as "Standalone" or saved directly as CDF (except for the mentioned formatting).

Edit: I just learned that there is another distinction, since the browser plugin will behave differently when it is embedded in html or running in a "full screen" mode which will fill the full browser window. The difference is that in the latter it can show the docked cell to let the user allow "dynamic content for potential dangerous code" while it can't do so in the embedded mode. If the user allows dynamic content then some of the restrictions of the browser-plugin are released, but I think there will still be some more than with the standalone player. There is a workaround which allows for that docked cell to appear even in when the cdf is embedded in html, which was obviously uncovered here, but that might have problems with resizing (and probably other) and is not officially supported, so could even go away with future versions. In any case, the difference seems again not be within the CDF document but in by which program and how it is shown.

Manipulate

From all test I have done there seems to be no need to use a Manipulate, despite the fact that this is mentioned in the WRI docs. It is just the most comfortable way to get the initialization of your dynamic content right, especially if the dynamic content depends on nontrivial functionality (that is many functions/symbols). Using the SaveDefinitions option is much more convenient than putting all the function definitions in the Initialization option of a DynamicModule or Dynamic by hand, and it is only available for Manipulate, not e.g. DynamicModule. Nevertheless, the following will make your first example work well in the (standalone) free CDF-Player, with no Manipulate involved at all:

DynamicModule[{x = 0},
 Panel[Column@{InputField[Dynamic@x, Number], Dynamic@func@x}],
 Initialization :> (func[x_] := 100*x)
]

For most practical considerations I think you can think of SaveDefinitions as an option that will create a correct Initialization option for you by inspecting the code, trying to determine dependencies and save all definitions that the code depends to that Initialization option. This can go wrong, and whether it works or not most probably doesn't have anything to do with what the CDF document or any of the ways to show such a document would allow to be run.

Needs

For the Needs restriction I think the point is that it's not possible to read external files in the free CDF-Player from CDF-documents created from a normal Mathematica, and thus it's not possible to load an external package file in the free CDF-Player from such a CDF-document. I don't have seen any restrictions concerning anything related to the name spaces (Contexts) so I think as long as you manage to get the initialization right (so that all dynamic content will work correctly) the symbols used can live in any namespace you want. It's just not that easy to achieve this, as has been discussed in e.g. this post (which I think you know about), and in some cases the SaveDefinition option probably isn't getting things right, too.

I think it's worth repeating here that you will need to enclose all code ("function definitions") and all data that is used by the dynamic content in the CDF document for it to work in the free CDF Player or the browser plugin. Only when shown in Wolfram Player Pro or Mathematica, code and data could come in separate files as well. Edit: I just learned that Import will actually work for nonlocal url's, so it should be possible to load data from a public webserver with the CDF-Player and even the browser plugin, but probably not for every format that Mathematica supports. But it's definitely not supposed to be possible to load data from a local filesystem, neither in the standalone version nor the browser plugin.

Nontrivial Example

During my tests I was trying to get as far as I could in deploying an application in the free CDF player. The following is what I managed to do, some of it is still worth improving and the whole example is just a proof of concept, but I think it shows that one can do a lot more in the free CDF player than is obvious at first sight.

CurrentValue[EvaluationNotebook[], TaggingRules] = {
   "Context" -> "cdfapp`",
   "Code" -> Compress["
       BeginPackage[\"cdfapp`\"];
       run::usage=\"run[]\";
       clear::usage=\"clear[]\";
       Begin[\"`Private`\"];
       run[]:=With[{cntxt=CurrentValue[ButtonNotebook[],{TaggingRules,\"Context\"}]},
        Set@@Join[
         ToExpression[cntxt<>\"content\",InputForm,Hold],
        Hold[Manipulate[Plot[x^n,{x,0,1},PlotRange->{0,1}],
        {n,1,100},AppearanceElements->None]]
        ]
       ];
       clear[]:=With[{cntxt=CurrentValue[ButtonNotebook[],{TaggingRules,\"Context\"}]},
        Unset@@ToExpression[cntxt<>\"content\",InputForm,Hold]
       ];
       End[];
       EndPackage[];
       "
     ]
   };

SetOptions[EvaluationNotebook[], DockedCells -> {
   Cell[BoxData[ToBoxes[
      Row[{
        Button["Run",
         ToExpression[
          Uncompress[
           CurrentValue[ButtonNotebook[], {TaggingRules, "Code"}]]]; 
         Symbol["run"][], Method -> "Queued"
         ],
        Button["Clear",
         ToExpression[
          Uncompress[
           CurrentValue[ButtonNotebook[], {TaggingRules, "Code"}]]]; 
         Symbol["clear"][], Method -> "Queued"
         ],
        Spacer[30],
        Button["Quit", FrontEnd`FrontEndToken["EvaluatorQuit"], 
         Evaluator -> None],
        Spacer[30],
        Button["Show Packed Code", 
         CreateDialog[
          CurrentValue[ButtonNotebook[], {TaggingRules, "Code"}],
          WindowSize -> {500, 500}], Method -> "Queued"],
        Button["Show Clear Code", 
         CreateDialog[
          Uncompress@
           CurrentValue[ButtonNotebook[], {TaggingRules, "Code"}],
          WindowSize -> {500, 500}], Method -> "Queued"]
        }]
      ]], "DockedCell"]
   }];

Dynamic[Replace[cdfapp`content, s_Symbol :> ""], 
 TrackedSymbols :> {cdfapp`content}]

To run this do the following: create a new CDF document in Mathematica, copy the above code to it and evaluate. It should add a docked cell to the document and an empty output cell. Delete everything except for the empty output cell and save it. Then open it with the free CDF player and try the buttons in the docked cells.

Disclaimer

As I said, much is just deduced from my experiments, some I learned from the CDF-Workshop and the documentation. Anyway I'm glad to hear about any corrections or improvements to these statements.

$\endgroup$
1
  • $\begingroup$ Thanks Albert, this was really useful, and after a 4 hour online WRI workshop on CDF, I can confirm that what you wrote basically agrees with the official canon. $\endgroup$ Apr 24, 2012 at 22:43
26
$\begingroup$

Updated: presentations are now available from the Wolfram CDF Virtual Workshop.

General info on the CDF format/creation/deployment:


1. Manipulate or DynamicModule?

Though it is often stated that the interactive content in a CDF must be Manipulate-based, or must be generated with the Manipulate command, this is not necessarily true. Thus one can create a DynamicModule object:

In[1] := func[x_] := 123;

In[2] := DynamicModule[{x = 0}, Panel[Column@{InputField[Dynamic@x, Number], Dynamic@func@x}]]

Mathematica graphics

but when the output cell is deployed, and the created CDF file is opened (in Mathematica or with the plugin in the browser), the result is this:

Mathematica graphics

Apparently, the DynamicModule is accepted by the CDF-deployer, but the external function is not recognized. This, according to Sjoerd's answer, can be solved by wrapping the internals (or the whole) of DynamicModule in Manipulate. Manipulate, however, does not solve everything, see next section. To conclude, it is definitely not true that only Manipulate objects can be used in a deployed cdf. Looking at the source code of the examples of the CDF Info Kit, one can realize that rather complex dynamic interfeces can be constructed within the boundaries of the cdf-restrictions, that can be opened as fully functional documents with the Player. It was explicitly stated by Yu-Sung Chang (CDF Workshop 2012) that Manipulate, Dynamic and DynamicModule are allowed to be the backbone of a CDF. The major benefit of using Manipulate instead of DynamicModule is described next, and in Albert's answer.


2. Save definitions

First, there is no need to put every function that is external to the Manipulate/DynamicModule/Dynamic output into the Manipulate/... body. If they are in the same notebook when the output panel is deployed, and SaveDefinitions->True is used, they are saved with the output correctly.

This works for even packaged function, while we are using full CDFs (i.e. non-free CDFs, to open with Mathematica or Player Pro), as this video demonstrates it.

The problem happens when one wants to deploy for the web or for the CDF Player. The following example demonstrates, that SaveDefinitions does not grab all the definitions from the packages:

func[x_] := 123;

DynamicModule[{x = 0},
 Manipulate[
  Column@{Dynamic@func@x, myPackage`myFunc@"test"},
  {dummy, None},
  Initialization :> (Needs@"myPackage`"),
  SaveDefinitions -> True]
 ]

where myPackage` is a custom package. When the above code is deployed for the browser plugin, the result is this:

Mathematica graphics

Thus func is saved but not the packaged function myFunc. The same thing happens if I remove the DynamicModule wrapper, or move the Manipulate to be the outer wrapper. It very much seems so that the free CDF version, deployed for the browser plugin or CDF Player, is not able to handle packaged functions, only the full CDF version, intended to open with Mathematica or with Player Pro.

One important point to mention here is the difference of the evaluation sequence of CDFs. While a normal notebook's evaluation sequence follows cell order, loading initialization cells before anything else, this is not the case for CDFs! Dynamic CDF content is evaluated when it is first displayed on screen (i.e. in order of display), in a preemptive method. Input cells, including initialization cells, will not be evaluated! "There is no guarantee that cells will be evaluated in order." (Yu-Sung Chang). It is wrong to assume that a following cell relying on the evaluation of a previous cell will be evaluated correctly, as their order of evaluation is not determined by cell order. This prompts that all content for a CDF (if it is outside of the Manipulate/DynamicModule) should be in the same dynamic cell, where the actual dynamic content resides, to make sure they got evaluated together. Since no order of evaluation can be guaranteed, a Dynamic cell should not depend on any other cell! So instead of deploying

p = 10;
Dynamic[p]

where p = 10 won't be saved with the deployed dynamic output cell, use instead:

Dynamic[p, Initialization :> (p = 10)]

which explicitly saves the value of p with the dynamic cell. Another way to ensure evaluation is to use SaveDefinitions -> True, if one uses Manipulate.

Also, it is stated here by the User Interface Group at WRI:

"SaveDefinitions can also be used for function definitions, although it doesn't always reach into packages correctly. Nonetheless, it often works well, and is used in Demonstrations by default."

meaning that it works well with standard packages, but not with user packages.

So SaveDefinitions does not grab the packaged function for the free player, it only gets definitions correctly with Player Pro (or Mathematica). One solution is to use DynamicModule[{(* local variables *)}, (* dynamic content *), Initialization :> (* my code *)] putting everyting under Initialization, and live with the fact that a security warning will appear when deployed. An other hacky method exists though (Yu-Sung's trick), that can be used to load user packages in CDFs, during runtime, via ImportString:

data = ImportString["myPackage.m", "Text"];
Manipulate[
   (* dynamic content *),
   {a, None},
   Initialization :> (ImportString[a, "NB"])
]

3. Deploying the output only vs. the whole document

...


4. Differences between Mathematica Player, the browser plugin, and Mathematica Player Pro

Basically, there are two Players and two types of CDF files (as Albert has pointed out as well). The players are: the free CDF Player and the non-free Player Pro. The formats are: free CDF and licenced CDF. Any of Mathematica, CDF Player or Player Pro installs the web plugin as well:

"The free player installs the browser plug-in, as do all Mathematica-based products. The plug-in tends to be the lowest common denominator wrt to feature support."

(by André Kuzniarek, CDF Workshop 2012). These plugins can also be installed from the Mathematica preferences page or during installation. Also, the plugin is different from all other applications (CDF Player, Player Pro, Mathematica), as for it the strictest security concerns apply, and therefore it is sandboxed. It provides the most restricted (though most secure) environment. The browser plugin (at the moment) is not available under Linux.

Following detailes gathered mostly from here:

Mathematica Player (or CDF Player)

  • Released just after V6 (pre V6 there was MathReader, a free static notebook viewer with no interactive elements and no evaluation capability)
  • Static notebook viewer
  • Free desktop runtime for viewing Manipulate-based interactive content (and supported the launch of the Demonstrations site) (note that it is not necessary to use Manipulate as the base, see above sections)
  • Required uploading of notebooks to Demonstrations site to be "playable"
  • The CDF Player also installs a web plug-in:
    • Full-screen mode
    • Embeddable objects (as seen on the Demonstrations site)
  • concerning licensing:
    • Terms spelled out on website
    • CDF usage is tied to Player licensing
    • Free when content is free, licensing required when content is licensed
    • Player displays logo in corner of embedded content, and terms language on toolbar for full page and desktop content
    • Publisher level signing of CDF docs removes these "watermarks" for commercial content

Mathematica Player Pro (to open commercial/full CDFs)

  • Same features as Player but allowing evaluation of inputs and higher level Mathematica functionality (data loading etc.)
  • $200 app
  • No need to upload notebooks, works with any notebook
  • Commercial app deployment channel

5. Differences between free CDF and full CDF

I borrowed the terminology from Jens' post. Some differences are listed in the official guidelines here, indicating what you can not do in a free CDF:

  • All interactive content must be generated with the Manipulate command and may only use mouse-driven elements, such as Slider, Locator, Checkbox, PopupMenu, etc.
  • Dialog windows are not supported.
  • MathLink operations, including J/Link and .NET/Link, are not supported.
  • Data import and export are not supported from within CDF Player with the exception of Wolfram-curated data sources (ChemicalData, CountryData, WordData, etc.).

More from the CDF Workshop:

  • Import from public web sources is allowed
  • online Wolfram curated data is available
  • local file operations are prohibited
  • any *Link technology is disabled
  • string InputField is not allowed
  • notebook related operations are not allowed
  • no webcam (though there is a debate ATM, so it could change in the future)
  • no parallel computation
  • no GPU access
  • no 3D hardware antialiasing

Though there are methods to partially overcome some of these. Some other restrictions I figured out:

  • Free CDF does not work with Initialization :> Needs["MyPackage`"] calls.
  • Mostly all complex functions (more complex than f[x_] := x + 2) cause some kind of security issues causing the disabling of dynamic updating, see next section.

6. Security issues

The followings are small detailes gathered from the CDF Workshop. The security issue rises when a function is involved in the dynamic output:

  • with definitions
  • that changes attributes
  • with options
  • package related functions
  • ToExpression/MakeExpression
  • Compress/Uncompress

These are only issues in the CDF Player or in the browser plugin, as they have more strict restrictions on security. This kind of security issue is due to the fact that the location where the CDF lives, is not part of a default trusted path. John McLoone stated in the CDF Workshop that this issue wouldn't be an issue at all on a server, where the CDF would be opened from a safe location on the server, under the browser. He also stated that it is in development (or planned) to set up a trusting mechanism, where the user can set trusted paths and authors.

$\endgroup$
2
  • $\begingroup$ Thank you for adding the content from the workshop. The video and material will be available later. Besides, current security restrictions will improve quite a bit in the future version. So, the suggested solutions should be understood as rather temporary solutions than permanent, for the people who need the feature now. $\endgroup$ Apr 25, 2012 at 3:12
  • $\begingroup$ Some comments. I've made extensive use of TabView (with each tab a Manipulate) in embedded CDFs so it's not just Manipulate and DynamicModule. I've found that SaveDefinitions works fine for my own packages in the free CDF player -- I have never encountered any problems. However it will fail if you have attributes for your functions set to ReadProtected. For some reason existence of DownValues can trigger security issues. For example I once had a tick function that caused a security issue. Wolfram advised to re-write it as a pure function and it worked fine with no security issues. $\endgroup$ May 9, 2012 at 2:05
12
$\begingroup$

You can use SaveDefinitions->True to do this. If you copy a Manipulate box created with this option set to an empty notebook and save this as CDF, it will contain all necessary definitions to let it stand alone. The use of Manipulate is a prerequisite for CDF deployments. More information here:

All interactive content must be generated with the Manipulate command and may only use mouse-driven elements, such as Slider, Locator, Checkbox, PopupMenu, etc.

However, Mike and you are right that the CDF plug-in seems to allow DynamicModule contrary to claims in the documentation. Anyway, if you add a Manipulate you will be able to use SaveDefinitions and your code works in my browser.

DynamicModule[{x = 0},
 Manipulate[
  Panel[Column@{InputField[Dynamic@x, Number], Dynamic@func@x}], 
  SaveDefinitions -> True]]

I don't think a CDF doc used in a browser plug-in can read external packages. So, any definitions you rely on have to be in place before deployment. You therefore need to evaluate the code and deploy the resulting panel, not the code itself.

$\endgroup$
6
  • 1
    $\begingroup$ I don't really understand this. I can deploy a DynamicModule as well (just like in the example above), so why Manipulate is a prerequisite? $\endgroup$ Apr 5, 2012 at 21:38
  • $\begingroup$ Ok, so I now deployed and embedded the above cdf to a local html, and my browser correctly displays the DynamicModule panel, just as in my second figure (i.e. the func[0] is still unevaluated). So does this mean that Manipulate is not a prerequisite or that I seriously misunderstand things here? $\endgroup$ Apr 5, 2012 at 21:54
  • $\begingroup$ @SjoerdC.deVries the documentation seems unclear about a few things. You can actually use DynamicModule and in fact last year I found a bug (acknowledged by Wolfram) in which something worked in DynamicModule but not in Manipulate $\endgroup$ Apr 5, 2012 at 22:17
  • $\begingroup$ SaveDefinitions->True is great ! This is one of the most important thing I learned about manipulate. Save my day! Thanks Sjoerd C. de Vries $\endgroup$
    – matheorem
    Aug 19, 2016 at 14:48
  • $\begingroup$ @matheorem however, see also stackoverflow.com/questions/6579644/… and other posts here. $\endgroup$ Aug 24, 2016 at 6:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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