MDL-64573 output: ajax form event
[moodle.git] / lib / editor / atto / yui / src / editor / js / autosave-io.js
CommitLineData
240a9de4
FM
1// This file is part of Moodle - http://moodle.org/
2//
3// Moodle is free software: you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// Moodle is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
15
16/**
17 * A autosave function for the Atto editor.
18 *
19 * @module moodle-editor_atto-autosave-io
20 * @submodule autosave-io
21 * @package editor_atto
22 * @copyright 2016 Frédéric Massart
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26var EditorAutosaveIoDispatcherInstance = null;
27
28function EditorAutosaveIoDispatcher() {
29 EditorAutosaveIoDispatcher.superclass.constructor.apply(this, arguments);
30 this._submitEvents = {};
31 this._queue = [];
32 this._throttle = null;
33}
34EditorAutosaveIoDispatcher.NAME = 'EditorAutosaveIoDispatcher';
35EditorAutosaveIoDispatcher.ATTRS = {
36
37 /**
38 * The relative path to the ajax script.
39 *
40 * @attribute autosaveAjaxScript
41 * @type String
42 * @default '/lib/editor/atto/autosave-ajax.php'
43 * @readOnly
44 */
45 autosaveAjaxScript: {
46 value: '/lib/editor/atto/autosave-ajax.php',
47 readOnly: true
48 },
49
50 /**
51 * The time buffer for the throttled requested.
52 *
53 * @attribute delay
54 * @type Number
55 * @default 50
56 * @readOnly
57 */
58 delay: {
59 value: 50,
60 readOnly: true
61 }
62
63};
64Y.extend(EditorAutosaveIoDispatcher, Y.Base, {
65
66 /**
67 * Dispatch an IO request.
68 *
69 * This method will put the requests in a queue in order to attempt to bulk them.
70 *
71 * @param {Object} params The parameters of the request.
72 * @param {Object} context The context in which the callbacks are called.
73 * @param {Object} callbacks Object with 'success', 'complete', 'end', 'failure' and 'start' as
74 * optional keys defining the callbacks to call. Success and Complete
75 * functions will receive the response as parameter. Success and Complete
76 * may receive an object containing the error key, use this to confirm
77 * that no errors occured.
78 * @return {Void}
79 */
80 dispatch: function(params, context, callbacks) {
81 if (this._throttle) {
82 this._throttle.cancel();
83 }
84
85 this._throttle = Y.later(this.get('delay'), this, this._processDispatchQueue);
86 this._queue.push([params, context, callbacks]);
87 },
88
89 /**
90 * Dispatches the requests in the queue.
91 *
92 * @return {Void}
93 */
94 _processDispatchQueue: function() {
95 var queue = this._queue,
96 data = {};
97
98 this._queue = [];
99 if (queue.length < 1) {
100 return;
101 }
102
103 Y.Array.each(queue, function(item, index) {
104 data[index] = item[0];
105 });
106
107 Y.io(M.cfg.wwwroot + this.get('autosaveAjaxScript'), {
108 method: 'POST',
109 data: Y.QueryString.stringify({
110 actions: data,
111 sesskey: M.cfg.sesskey
112 }),
113 on: {
114 start: this._makeIoEventCallback('start', queue),
115 complete: this._makeIoEventCallback('complete', queue),
116 failure: this._makeIoEventCallback('failure', queue),
117 end: this._makeIoEventCallback('end', queue),
118 success: this._makeIoEventCallback('success', queue)
119 }
120 });
121 },
122
123 /**
124 * Creates a function that dispatches an IO response to callbacks.
125 *
126 * @param {String} event The type of event.
127 * @param {Array} queue The queue.
128 * @return {Function}
129 */
130 _makeIoEventCallback: function(event, queue) {
131 var noop = function() {};
132 return function() {
133 var response = arguments[1],
134 parsed = {};
135
136 if ((event == 'complete' || event == 'success') && (typeof response !== 'undefined'
137 && typeof response.responseText !== 'undefined' && response.responseText !== '')) {
138
139 // Success and complete events need to parse the response.
140 parsed = JSON.parse(response.responseText) || {};
141 }
142
143 Y.Array.each(queue, function(item, index) {
144 var context = item[1],
145 cb = (item[2] && item[2][event]) || noop,
146 arg;
147
148 if (parsed && parsed.error) {
149 // The response is an error, we send it to everyone.
150 arg = parsed;
151 } else if (parsed) {
152 // The response was parsed, we only communicate the relevant portion of the response.
153 arg = parsed[index];
154 }
155
156 cb.apply(context, [arg]);
157 });
158 };
159 },
160
161 /**
162 * Form submit handler.
163 *
164 * @param {EventFacade} e The event.
165 * @return {Void}
166 */
167 _onSubmit: function(e) {
168 var data = {},
169 id = e.currentTarget.generateID(),
170 params = this._submitEvents[id];
171
172 if (!params || params.ios.length < 1) {
173 return;
174 }
175
176 Y.Array.each(params.ios, function(param, index) {
177 data[index] = param;
178 });
179
180 Y.io(M.cfg.wwwroot + this.get('autosaveAjaxScript'), {
181 method: 'POST',
182 data: Y.QueryString.stringify({
183 actions: data,
184 sesskey: M.cfg.sesskey
185 }),
186 sync: true
187 });
188 },
189
190 /**
191 * Registers a request to be made on form submission.
192 *
193 * @param {Node} node The forum node we will listen to.
194 * @param {Object} params Parameters for the IO request.
195 * @return {Void}
196 */
197 whenSubmit: function(node, params) {
198 if (typeof this._submitEvents[node.generateID()] === 'undefined') {
199 this._submitEvents[node.generateID()] = {
200 event: node.on('submit', this._onSubmit, this),
260565e3 201 ajaxEvent: node.on(M.core.event.FORM_SUBMIT_AJAX, this._onSubmit, this),
240a9de4
FM
202 ios: []
203 };
204 }
205 this._submitEvents[node.get('id')].ios.push([params]);
206 }
207
208});
209EditorAutosaveIoDispatcherInstance = new EditorAutosaveIoDispatcher();
210
211
212function EditorAutosaveIo() {}
213EditorAutosaveIo.prototype = {
214
215 /**
216 * Dispatch an IO request.
217 *
218 * This method will put the requests in a queue in order to attempt to bulk them.
219 *
220 * @param {Object} params The parameters of the request.
221 * @param {Object} context The context in which the callbacks are called.
222 * @param {Object} callbacks Object with 'success', 'complete', 'end', 'failure' and 'start' as
223 * optional keys defining the callbacks to call. Success and Complete
224 * functions will receive the response as parameter. Success and Complete
225 * may receive an object containing the error key, use this to confirm
226 * that no errors occured.
227 * @return {Void}
228 */
229 autosaveIo: function(params, context, callbacks) {
230 EditorAutosaveIoDispatcherInstance.dispatch(params, context, callbacks);
231 },
232
233 /**
234 * Registers a request to be made on form submission.
235 *
236 * @param {Node} form The forum node we will listen to.
237 * @param {Object} params Parameters for the IO request.
238 * @return {Void}
239 */
240 autosaveIoOnSubmit: function(form, params) {
241 EditorAutosaveIoDispatcherInstance.whenSubmit(form, params);
242 }
243
244};
245Y.Base.mix(Y.M.editor_atto.Editor, [EditorAutosaveIo]);