Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Paint tool integration

From MoodleDocs
Revision as of 15:25, 10 July 2009 by Mihai Sucan (talk | contribs) (updates regarding localization and API changes)

PaintWeb is the paint tool which is going to be integrated into Moodle. For more information about PaintWeb please read the project specification.

Overview

PaintWeb is currently a strictly client-side project, a Web application. It provides an API for developers who wish to extend its functionality, via new drawing tools, new extensions and new commands.

The plan is to integrate PaintWeb in Moodle in the appropriate places. Meaning, in some cases, users would like to be able to edit images, in place, in the HTML editor (TinyMCE mostly). Another place of integration would be the file manager - there users should be allowed to pick images files and edit them. Another use-case for PaintWeb is separate loading, stand-alone usage - for example a page which only allows the user to draw on the Canvas and save the result.

PaintWeb already includes a TinyMCE plugin which allows users to start editing any image in the HTML document. The plugin allows users to start editing an image by clicking an Edit button which shows overlayed on top of images when they are selected. Additionally, users can right-click an image to pick the Edit in PaintWeb. Lastly, when the advanced theme is used, the paintwebEdit button is also available.

Things to take into consideration:

  • PaintWeb can only edit images from the same domain, due to security restrictions. This means that any image from a different domain is either denied from editing, or we can use a server-side script which downloads the image locally on the server. The latter option is more cumbersome, and I believe it implies some security risks: the user can point to arbitrary malicious files which the server downloads and sends back to the browser. The TinyMCE plugin I have does not allow the users to edit of any image from a different domain.
  • The TinyMCE plugin needs to be loaded dynamically. The PaintWeb image editor should not show up in all cases where TinyMCE is used. Thus, Moodle needs an API which other developers can use to show the HTML editor and configure it: "hey, I want PaintWeb as well!" or not.
  • There's an important difference between the use of PaintWeb inside TinyMCE and standalone use. Inside TinyMCE the user already has a dialog for inserting images - thus in PaintWeb we do not need an option to load another image. In PaintWeb-TinyMCE we only need the options to save and cancel the changes. In a standalone instance of PaintWeb we might want to allow the user to load and save images at will. The file manager use-case is the same as in TinyMCE: the file manager handles the files itself, PaintWeb should be strictly the image editor (with save/cancel).

Given the above, here is what I consider needs to be done:

  • Moodle 2 has an API for inserting the HTML editor (TinyMCE) anywhere desired. This API needs to be extended such that the developer can tell which plugins need to be loaded - in this case PaintWeb.
  • Moodle 2 has a File API which needs to be used by PaintWeb when the file save/load operations are performed. On the client-side of things this can be done by writing an extension for PaintWeb which handles events like imageSave. PaintWeb in Moodle needs some "common backend" which handles image save/load in all use-cases.
  • It should be noted that having a PaintWeb extensions specific for Moodle would replace the need of having custom patches applied to PaintWeb - like Moodle does for TinyMCE.
  • The PaintWeb script needs to communicate with the server to perform file load/save. So, on the server-side these operations can be handled by a piece of common code, e.g. /lib/paintweb/ext/moodle/lib.php. Suggestions for a different file name / place are welcome. This PHP script needs to use the File API to perform the desired operations. An API needs to be exposed by this file, an API others can use to integrate PaintWeb in a standalone page. For example paintweb_setup() which sets-up the required JS file in the page, for the current page. Then paintweb_insert(options) to insert the PaintWeb initialization code, with user-defined options.
  • The upcoming file manager needs an API for adding "file handlers". For example, PaintWeb can be a file handler for images. Thus, a button, or some context menu item for images could be displayed Edit this image in PaintWeb.

The Moodle editors API

Currently, developers who want to have a textarea element in their page with TinyMCE can do the following:

// setup the page requirements (JS files needed to be loaded) editors_head_setup();

// get an instance of the editor $editor = get_preferred_texteditor(FORMAT_HTML);

// use the editor: textarea element ID, and options. $editor->use_editor('elementId', array());

echo '<textarea rows="20" cols="10" id="elementId">some HTML</textarea>';

According to Petr Škoda, the developer of the API, the API still needs lots of work. Personally I consider the API only needs ... further work. Here's how I'd like to do things:

$editor->use_editor('elementId',

 array('imageEditing' => true,
       'mathEditing' => true
 )

);

Basically, I don't think there's something inherently "bad" about the current API. I only want to tell the editor instance "hey, I'd like image editing, math editing, etc, if possible".

I'd say try to keep things abstracted. So, if I say in the options array I want image editing, then TinyMCE can load the PaintWeb plugin. If I want math editing, then load dragmath and anything related.

The way each editor implements these features should be left up to the editor itself.

Obviously, based on such options, even the editor GUI can be altered: say if the PaintWeb plugin is desired, then the paintwebEdit button can be included in the theme toolbar.

Additionally, we should have options for configuring the GUI - but not something tied to the TinyMCE config. I don't think the API should go down the road of allowing the direct input of TinyMCE configuration options. If that's desired, then do not have multiple editors. Switch to a single editor: TinyMCE and have all the API tailored to this editor.

The Moodle file manager

As explained above, the Moodle file manager should provide an API for registering file handlers, file processing tools, etc.

In the file manager the user might want to edit HTML files with TinyMCE, edit images with PaintWeb, or select multiple files to apply some batch process - like image resize.

It should be taken into consideration that some file operations can be performed on the server or client-side. Meaning, image resize can be performed server-side, but image editing needs to be performed client-side. When registering file handlers, one should be able to define the kind of operation: does the action need to load and invoke a client-side JavaScript method from a library? or is the action supposed to be performed by a server-side script from some Moodle library?

The PaintWeb extension

The whole PaintWeb package should live in /lib/paintweb.

In the overview I pointed out a PaintWeb extension needs to be developed to properly integrate into Moodle. Sample code:

pwlib.extensions.moodle = function (app) {

 this.extensionRegister = function () {
   // add an event listener for the imageSave event.
   app.events.add('imageSave', this.imageSave);
   // add a hidden form in the document
   // used for submitting the image to the server
   // ...
 };
 this.imageSave = function (ev) {
   ev.preventDefault();
   // a hidden form we can submit to the server
   form.imageFile.value = ev.dataURI;
   form.submit();
 };
 // ...

};

When the user decides to save, the browser outputs the image data as a data URI, base64 encoded. We can submit this to the server.

The PaintWeb lib code

The /lib/paintweb/ext/moodle/lib.php file.

On the server side, all the requests for file save need to be handled using the new File API:

// reference to the temporary imageFile uploaded by php $imgfile = $_FILES['imageFile']['tmp_name']; $filename = $_FILES['imageFile']['name']; $fs = get_file_storage(); $file_record = array('contextid' => $context->id,

   'filearea' => $filearea,
   'itemid'=> 0,
   'filepath'=> '/',
   'filename' => $filename,
   'timecreated' => time(),
   'timemodified' => time());

$fs->create_file_from_pathname($file_record, $imgfile);

Questions:

  • What context should be used? A different context depending where PaintWeb is used? Or a single context for all the files saved by PaintWeb? If different contexts need to be used, how should we pass the context to PaintWeb? Maybe the script which integrates PaintWeb also needs to pass the context?
  • How about the file area? Same question as above.

The PaintWeb library code must also provide API for using PaintWeb standalone in any page desired by the developer. Here's an idea:

function paintweb_setup () {

 global $PAGE;
 $PAGE->requires->js('/lib/paintweb/build/paintweb.js');
 $PAGE->requires->js('/lib/paintweb/ext/moodle/lib.js');

};

function paintweb_insert ($elementId, $config = array()) {

 global $PAGE;
 $PAGE->requires->js_function_call('paintweb_moodle_init',
     array($elementId, $config));

};

The ext/moodle/lib.js can initialize PaintWeb:

function paintweb_moodle_init (elemId, config) {

 var pw = new PaintWeb();
 pw.config.guiPlaceholder = document.getElementById(elemId);
 // The Moodle config file.
 pw.config.configFile = 'config-moodle.json';
 // Use the configuration provided by the Moodle
 // server-side script.
 if (config) {
   for (var prop in config) {
     pw.config[prop] = config[prop];
   }
 }
 pw.init();

};

Localization

The TinyMCE integration has a script which generates Moodle language files from the original files provided by TinyMCE.

I have two scripts which convert the PaintWeb JSON language files into Moodle PHP languages files, and back.

I presume that Moodle translators will want to work with the Moodle PHP language files. This means that they (or someone else) can update the PaintWeb JSON language files using the convertor script.

Should PaintWeb load static JSON files or should it load a script which automatically generates the JSON using the strings stored in the moodle/lang/*/paintweb.php files?