Roo/form/Action.js
[roojs1] / Roo / form / Action.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11  
12  /**
13  * @class Roo.form.Action
14  * Internal Class used to handle form actions
15  * @constructor
16  * @param {Roo.form.BasicForm} el The form element or its id
17  * @param {Object} config Configuration options
18  */
19  
20  
21 // define the action interface
22 Roo.form.Action = function(form, options){
23     this.form = form;
24     this.options = options || {};
25 };
26 /**
27  * Client Validation Failed
28  * @const 
29  */
30 Roo.form.Action.CLIENT_INVALID = 'client';
31 /**
32  * Server Validation Failed
33  * @const 
34  */
35  Roo.form.Action.SERVER_INVALID = 'server';
36  /**
37  * Connect to Server Failed
38  * @const 
39  */
40 Roo.form.Action.CONNECT_FAILURE = 'connect';
41 /**
42  * Reading Data from Server Failed
43  * @const 
44  */
45 Roo.form.Action.LOAD_FAILURE = 'load';
46
47 Roo.form.Action.prototype = {
48     type : 'default',
49     failureType : undefined,
50     response : undefined,
51     result : undefined,
52
53     // interface method
54     run : function(options){
55
56     },
57
58     // interface method
59     success : function(response){
60
61     },
62
63     // interface method
64     handleResponse : function(response){
65
66     },
67
68     // default connection failure
69     failure : function(response){
70         if (this.form.maskEl) {
71             this.form.maskEl.unmask();
72         }
73         this.response = response;
74         this.failureType = Roo.form.Action.CONNECT_FAILURE;
75         this.form.afterAction(this, false);
76     },
77
78     processResponse : function(response){
79         this.response = response;
80         if(!response.responseText){
81             return true;
82         }
83         this.result = this.handleResponse(response);
84         return this.result;
85     },
86
87     // utility functions used internally
88     getUrl : function(appendParams){
89         var url = this.options.url || this.form.url || this.form.el.dom.action;
90         if(appendParams){
91             var p = this.getParams();
92             if(p){
93                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
94             }
95         }
96         return url;
97     },
98
99     getMethod : function(){
100         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
101     },
102
103     getParams : function(){
104         var bp = this.form.baseParams;
105         var p = this.options.params;
106         if(p){
107             if(typeof p == "object"){
108                 p = Roo.urlEncode(Roo.applyIf(p, bp));
109             }else if(typeof p == 'string' && bp){
110                 p += '&' + Roo.urlEncode(bp);
111             }
112         }else if(bp){
113             p = Roo.urlEncode(bp);
114         }
115         return p;
116     },
117
118     createCallback : function(){
119         return {
120             success: this.success,
121             failure: this.failure,
122             scope: this,
123             timeout: (this.form.timeout*1000),
124             upload: this.form.fileUpload ? this.success : undefined
125         };
126     }
127 };
128
129 Roo.form.Action.Submit = function(form, options){
130     Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
131 };
132
133 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
134     type : 'submit',
135
136     haveProgress : false,
137     uploadComplete : false,
138     
139     // uploadProgress indicator.
140     uploadProgress : function()
141     {
142         if (!this.form.progressUrl) {
143             return;
144         }
145         
146         if (!this.haveProgress) {
147             Roo.MessageBox.progress("Uploading", "Uploading");
148         }
149         if (this.uploadComplete) {
150            Roo.MessageBox.hide();
151            return;
152         }
153         
154         this.haveProgress = true;
155    
156         var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
157         
158         var c = new Roo.data.Connection();
159         c.request({
160             url : this.form.progressUrl,
161             params: {
162                 id : uid
163             },
164             method: 'GET',
165             success : function(req){
166                //console.log(data);
167                 var rdata = false;
168                 var edata;
169                 try  {
170                    rdata = Roo.decode(req.responseText)
171                 } catch (e) {
172                     Roo.log("Invalid data from server..");
173                     Roo.log(edata);
174                     return;
175                 }
176                 if (!rdata || !rdata.success) {
177                     Roo.log(rdata);
178                     return;
179                 }
180                 var data = rdata.data;
181                 
182                 if (this.uploadComplete) {
183                    Roo.MessageBox.hide();
184                    return;
185                 }
186                    
187                 if (data){
188                     Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
189                        Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
190                     );
191                 }
192                 this.uploadProgress.defer(2000,this);
193             },
194        
195             failure: function(data) {
196                 Roo.log('progress url failed ');
197                 Roo.log(data);
198             },
199             scope : this
200         });
201            
202     },
203     
204     
205     run : function()
206     {
207         // run get Values on the form, so it syncs any secondary forms.
208         this.form.getValues();
209         
210         var o = this.options;
211         var method = this.getMethod();
212         var isPost = method == 'POST';
213         if(o.clientValidation === false || this.form.isValid()){
214             
215             if (this.form.progressUrl) {
216                 this.form.findField('UPLOAD_IDENTIFIER').setValue(
217                     (new Date() * 1) + '' + Math.random());
218                     
219             } 
220             if (this.form.maskEl) {
221                 this.form.maskEl.mask("Saving");
222             }
223             
224             Roo.Ajax.request(Roo.apply(this.createCallback(), {
225                 form:this.form.el.dom,
226                 url:this.getUrl(!isPost),
227                 method: method,
228                 params:isPost ? this.getParams() : null,
229                 isUpload: this.form.fileUpload
230             }));
231             
232             this.uploadProgress();
233
234         }else if (o.clientValidation !== false){ // client validation failed
235             this.failureType = Roo.form.Action.CLIENT_INVALID;
236             this.form.afterAction(this, false);
237         }
238     },
239
240     success : function(response)
241     {
242         this.uploadComplete= true;
243         if (this.haveProgress) {
244             Roo.MessageBox.hide();
245         }
246         if (this.form.maskEl) {
247             this.form.maskEl.unmask();
248         }
249         
250         var result = this.processResponse(response);
251         if(result === true || result.success){
252             this.form.afterAction(this, true);
253             return;
254         }
255         if(result.errors){
256             this.form.markInvalid(result.errors);
257             this.failureType = Roo.form.Action.SERVER_INVALID;
258         }
259         this.form.afterAction(this, false);
260     },
261     failure : function(response)
262     {
263         this.uploadComplete= true;
264         if (this.haveProgress) {
265             Roo.MessageBox.hide();
266         }
267         if (this.form.maskEl) {
268             this.form.maskEl.unmask();
269         }
270         
271         this.response = response;
272         this.failureType = Roo.form.Action.CONNECT_FAILURE;
273         this.form.afterAction(this, false);
274     },
275     
276     handleResponse : function(response){
277         if(this.form.errorReader){
278             var rs = this.form.errorReader.read(response);
279             var errors = [];
280             if(rs.records){
281                 for(var i = 0, len = rs.records.length; i < len; i++) {
282                     var r = rs.records[i];
283                     errors[i] = r.data;
284                 }
285             }
286             if(errors.length < 1){
287                 errors = null;
288             }
289             return {
290                 success : rs.success,
291                 errors : errors
292             };
293         }
294         var ret = false;
295         try {
296             ret = Roo.decode(response.responseText);
297         } catch (e) {
298             ret = {
299                 success: false,
300                 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
301                 errors : []
302             };
303         }
304         return ret;
305         
306     }
307 });
308
309
310 Roo.form.Action.Load = function(form, options){
311     Roo.form.Action.Load.superclass.constructor.call(this, form, options);
312     this.reader = this.form.reader;
313 };
314
315 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
316     type : 'load',
317
318     run : function(){
319         if (this.form.maskEl) {
320             this.form.maskEl.mask("Loading");
321         }
322         Roo.Ajax.request(Roo.apply(
323                 this.createCallback(), {
324                     method:this.getMethod(),
325                     url:this.getUrl(false),
326                     params:this.getParams()
327         }));
328     },
329
330     success : function(response){
331         if (this.form.maskEl) {
332             this.form.maskEl.unmask();
333         }
334         var result = this.processResponse(response);
335         if(result === true || !result.success || !result.data){
336             this.failureType = Roo.form.Action.LOAD_FAILURE;
337             this.form.afterAction(this, false);
338             return;
339         }
340         this.form.clearInvalid();
341         this.form.setValues(result.data);
342         this.form.afterAction(this, true);
343     },
344
345     handleResponse : function(response){
346         if(this.form.reader){
347             var rs = this.form.reader.read(response);
348             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
349             return {
350                 success : rs.success,
351                 data : data
352             };
353         }
354         return Roo.decode(response.responseText);
355     }
356 });
357
358 Roo.form.Action.ACTION_TYPES = {
359     'load' : Roo.form.Action.Load,
360     'submit' : Roo.form.Action.Submit
361 };