Work on PaintWeb image save using files instead of data URLs.
[moodle/mihaisucan.git] / lib / paintweb / src / extensions / moodle.js
blob8e2d2508b1ffe05df34e8d32ad1d83f9ed23bb1c
1 /*
2  * Copyright (C) 2009 Mihai Şucan
3  *
4  * This file is part of PaintWeb.
5  *
6  * PaintWeb is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * PaintWeb is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with PaintWeb.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * $URL: http://code.google.com/p/paintweb $
20  * $Date: 2009-07-26 22:32:00 +0300 $
21  */
23 /**
24  * @author <a lang="ro" href="http://www.robodesign.ro/mihai">Mihai Şucan</a>
25  * @fileOverview Holds the integration code for PaintWeb inside <a 
26  * href="http://www.moodle.org">Moodle</a>.
27  */
29 /**
30  * @class The Moodle extension for PaintWeb. This extension handles the Moodle 
31  * integration inside the PaintWeb code.
32  *
33  * @param {PaintWeb} app Reference to the main paint application object.
34  */
35 pwlib.extensions.moodle = function (app) {
36   var _self    = this,
37       appEvent = pwlib.appEvent,
38       config   = app.config,
39       gui      = app.gui,
40       lang     = app.lang.moodle;
42   // Holds properties related to Moodle.
43   var moodle = {
44     // Holds the URL of the image the user is saving.
45     imageURL: null,
47     // The class name for the element which holds the textarea buttons (toggle 
48     // on/off).
49     textareaButtons: 'textareaicons',
51     // The image save handler script on the server-side. The path is relative to 
52     // the PaintWeb base folder. If the value is set to '-' then the image src 
53     // attribute is updated to hold the generated dataURL.
54     //imageSaveHandler: '../ext/moodle/imagesave.php'
55     imageSaveHandler: '-'
56   };
58   /**
59    * The <code>extensionRegister</code> event handler.
60    *
61    * @returns {Boolean} True if the extension initialized successfully, or false 
62    * if not.
63    */
64   this.extensionRegister = function () {
65     // Register application events.
66     app.events.add('guiShow',   this.guiShow);
67     app.events.add('guiHide',   this.guiHide);
68     app.events.add('imageSave', this.imageSave);
70     return true;
71   };
73   /**
74    * The <code>extensionUnregister</code> event handler.
75    */
76   this.extensionUnregister = function () {
77     return;
78   };
80   /**
81    * The <code>imageSave</code> application event handler. When the user 
82    * attempts to save an image, this extension handles the event by sending the 
83    * image data to the Moodle server, to perform the actual save operation.
84    *
85    * @private
86    * @param {pwlib.appEvent.imageSave} ev The application event object.
87    */
88   this.imageSave = function (ev) {
89     if (!ev.dataURL) {
90       return;
91     }
93     ev.preventDefault();
95     moodle.imageURL = config.imageLoad.src;
96     if (!moodle.imageURL || moodle.imageURL.substr(0, 5) === 'data:') {
97       moodle.imageURL = '-';
98     }
100     if (moodle.imageSaveHandler === '-') {
101       app.events.dispatch(new appEvent.imageSaveResult(true, moodle.imageURL, 
102             ev.dataURL));
103     } else {
104       var handlerURL = PaintWeb.baseFolder + moodle.imageSaveHandler,
105           send       = 'url=' + encodeURIComponent(moodle.imageURL) +
106                        '&dataURL=' + encodeURIComponent(ev.dataURL),
107           headers    = {'Content-Type': 'application/x-www-form-urlencoded'};
109       pwlib.xhrLoad(handlerURL, imageSaveReady, 'POST', send, headers);
110     }
111   };
113   /**
114    * The image save <code>onreadystatechange</code> event handler for the 
115    * <code>XMLHttpRequest</code> which performs the image save. This function 
116    * uses the reply to determine if the image save operation is successful or 
117    * not.
118    *
119    * <p>The {@link pwlib.appEvent.imageSaveResult} application event is 
120    * dispatched.
121    *
122    * <p>The server-side script must reply with a JSON object with the following 
123    * properties:
124    *
125    * <ul>
126    *   <li><var>successful</var> which tells if the image save operation was 
127    *   successful or not;
128    *
129    *   <li><var>url</var> which must tell the same URL as the image we just 
130    *   saved (sanity/security check);
131    *
132    *   <li><var>urlNew</var> is optional. This allows the server-side script to 
133    *   change the image URL;
134    *
135    *   <li><var>errorMessage</var> is optional. When the image save was not 
136    *   successful, an error message can be displayed.
137    * </ul>
138    *
139    * @private
140    * @param {XMLHttpRequest} xhr The XMLHttpRequest object.
141    */
142   function imageSaveReady (xhr) {
143     if (!xhr || xhr.readyState !== 4) {
144       return;
145     }
147     var result = {successful: false, url: moodle.imageURL};
149     if ((xhr.status !== 304 && xhr.status !== 200) || !xhr.responseText) {
150       alert(lang.xhrRequestFailed);
152       app.events.dispatch(new appEvent.imageSaveResult(false, result.url, null, 
153             lang.xhrRequestFailed));
155       return;
156     }
158     try {
159       result = JSON.parse(xhr.responseText);
160     } catch (err) {
161       result.errorMessage = lang.jsonParseFailed + "\n" + err;
162       alert(result.errorMessage);
163     }
165     if (result.successful) {
166       if (result.url !== moodle.imageURL) {
167         alert(pwlib.strf(lang.urlMismatch, {
168                 url: moodle.imageURL,
169                 urlServer: result.url || 'null'}));
170       }
171     } else {
172       if (result.errorMessage) {
173         alert(lang.imageSaveFailed + "\n" + result.errorMessage);
174       } else {
175         alert(lang.imageSaveFailed);
176       }
177     }
179     app.events.dispatch(new appEvent.imageSaveResult(result.successful, 
180           result.url, result.urlNew, result.errorMessage));
181   };
183   /**
184    * The <code>guiShow</code> application event handler. When the PaintWeb GUI 
185    * is shown, we must hide the textarea icons for the current textarea element, 
186    * inside a Moodle page.
187    * @private
188    */
189   this.guiShow = function () {
190     var pNode = config.guiPlaceholder.parentNode,
191         elem = pNode.getElementsByClassName(moodle.textareaButtons)[0];
193     if (elem) {
194       elem.style.display = 'none';
195     }
196   };
198   /**
199    * The <code>guiHide</code> application event handler. When the PaintWeb GUI 
200    * is hidden, we must show again the textarea icons for the current textarea 
201    * element, inside a Moodle page.
202    * @private
203    */
204   this.guiHide = function () {
205     var pNode = config.guiPlaceholder.parentNode,
206         elem = pNode.getElementsByClassName(moodle.textareaButtons)[0];
208     if (elem) {
209       elem.style.display = '';
210     }
211   };
214 // vim:set spell spl=en fo=wan1croqlt tw=80 ts=2 sw=2 sts=2 sta et ai cin fenc=utf-8 ff=unix: