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         this.response = response;
71         this.failureType = Roo.form.Action.CONNECT_FAILURE;
72         this.form.afterAction(this, false);
73     },
74
75     processResponse : function(response){
76         this.response = response;
77         if(!response.responseText){
78             return true;
79         }
80         this.result = this.handleResponse(response);
81         return this.result;
82     },
83
84     // utility functions used internally
85     getUrl : function(appendParams){
86         var url = this.options.url || this.form.url || this.form.el.dom.action;
87         if(appendParams){
88             var p = this.getParams();
89             if(p){
90                 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
91             }
92         }
93         return url;
94     },
95
96     getMethod : function(){
97         return (this.options.method || this.form.method || this.form.el.dom.method || 'POST').toUpperCase();
98     },
99
100     getParams : function(){
101         var bp = this.form.baseParams;
102         var p = this.options.params;
103         if(p){
104             if(typeof p == "object"){
105                 p = Roo.urlEncode(Roo.applyIf(p, bp));
106             }else if(typeof p == 'string' && bp){
107                 p += '&' + Roo.urlEncode(bp);
108             }
109         }else if(bp){
110             p = Roo.urlEncode(bp);
111         }
112         return p;
113     },
114
115     createCallback : function(){
116         return {
117             success: this.success,
118             failure: this.failure,
119             scope: this,
120             timeout: (this.form.timeout*1000),
121             upload: this.form.fileUpload ? this.success : undefined
122         };
123     }
124 };
125
126 Roo.form.Action.Submit = function(form, options){
127     Roo.form.Action.Submit.superclass.constructor.call(this, form, options);
128 };
129
130 Roo.extend(Roo.form.Action.Submit, Roo.form.Action, {
131     type : 'submit',
132
133     haveProgress : false,
134     uploadComplete : false,
135     
136     // uploadProgress indicator.
137     uploadProgress : function()
138     {
139         if (!this.form.progressUrl) {
140             return;
141         }
142         
143         if (!this.haveProgress) {
144             Roo.MessageBox.progress("Uploading", "Uploading");
145         }
146         if (this.uploadComplete) {
147            Roo.MessageBox.hide();
148            return;
149         }
150         
151         this.haveProgress = true;
152    
153         var uid = this.form.findField('UPLOAD_IDENTIFIER').getValue();
154         
155         var c = new Roo.data.Connection();
156         c.request({
157             url : this.form.progressUrl,
158             params: {
159                 id : uid
160             },
161             method: 'GET',
162             success : function(req){
163                //console.log(data);
164                 var rdata = false;
165                 var edata;
166                 try  {
167                    rdata = Roo.decode(req.responseText)
168                 } catch (e) {
169                     Roo.log("Invalid data from server..");
170                     Roo.log(edata);
171                     return;
172                 }
173                 if (!rdata || !rdata.success) {
174                     Roo.log(rdata);
175                     return;
176                 }
177                 var data = rdata.data;
178                 
179                 if (this.uploadComplete) {
180                    Roo.MessageBox.hide();
181                    return;
182                 }
183                    
184                 if (data){
185                     Roo.MessageBox.updateProgress(data.bytes_uploaded/data.bytes_total,
186                        Math.floor((data.bytes_total - data.bytes_uploaded)/1000) + 'k remaining'
187                     );
188                 }
189                 this.uploadProgress.defer(2000,this);
190             },
191        
192             failure: function(data) {
193                 Roo.log('progress url failed ');
194                 Roo.log(data);
195             },
196             scope : this
197         });
198            
199     },
200     
201     
202     run : function()
203     {
204         // run get Values on the form, so it syncs any secondary forms.
205         this.form.getValues();
206         
207         var o = this.options;
208         var method = this.getMethod();
209         var isPost = method == 'POST';
210         if(o.clientValidation === false || this.form.isValid()){
211             
212             if (this.form.progressUrl) {
213                 this.form.findField('UPLOAD_IDENTIFIER').setValue(
214                     (new Date() * 1) + '' + Math.random());
215                     
216             } 
217             if (this.form.maskEl) {
218                 this.form.maskEl.mask("Saving");
219             }
220             
221             Roo.Ajax.request(Roo.apply(this.createCallback(), {
222                 form:this.form.el.dom,
223                 url:this.getUrl(!isPost),
224                 method: method,
225                 params:isPost ? this.getParams() : null,
226                 isUpload: this.form.fileUpload
227             }));
228             
229             this.uploadProgress();
230
231         }else if (o.clientValidation !== false){ // client validation failed
232             this.failureType = Roo.form.Action.CLIENT_INVALID;
233             this.form.afterAction(this, false);
234         }
235     },
236
237     success : function(response)
238     {
239         this.uploadComplete= true;
240         if (this.haveProgress) {
241             Roo.MessageBox.hide();
242         }
243         if (this.form.maskEl) {
244             this.form.maskEl.unmask();
245         }
246         
247         var result = this.processResponse(response);
248         if(result === true || result.success){
249             this.form.afterAction(this, true);
250             return;
251         }
252         if(result.errors){
253             this.form.markInvalid(result.errors);
254             this.failureType = Roo.form.Action.SERVER_INVALID;
255         }
256         this.form.afterAction(this, false);
257     },
258     failure : function(response)
259     {
260         this.uploadComplete= true;
261         if (this.haveProgress) {
262             Roo.MessageBox.hide();
263         }
264         if (this.form.maskEl) {
265             this.form.maskEl.unmask();
266         }
267         
268         this.response = response;
269         this.failureType = Roo.form.Action.CONNECT_FAILURE;
270         this.form.afterAction(this, false);
271     },
272     
273     handleResponse : function(response){
274         if(this.form.errorReader){
275             var rs = this.form.errorReader.read(response);
276             var errors = [];
277             if(rs.records){
278                 for(var i = 0, len = rs.records.length; i < len; i++) {
279                     var r = rs.records[i];
280                     errors[i] = r.data;
281                 }
282             }
283             if(errors.length < 1){
284                 errors = null;
285             }
286             return {
287                 success : rs.success,
288                 errors : errors
289             };
290         }
291         var ret = false;
292         try {
293             ret = Roo.decode(response.responseText);
294         } catch (e) {
295             ret = {
296                 success: false,
297                 errorMsg: "Failed to read server message: " + (response ? response.responseText : ' - no message'),
298                 errors : []
299             };
300         }
301         return ret;
302         
303     }
304 });
305
306
307 Roo.form.Action.Load = function(form, options){
308     Roo.form.Action.Load.superclass.constructor.call(this, form, options);
309     this.reader = this.form.reader;
310 };
311
312 Roo.extend(Roo.form.Action.Load, Roo.form.Action, {
313     type : 'load',
314
315     run : function(){
316         Roo.Ajax.request(Roo.apply(
317                 this.createCallback(), {
318                     method:this.getMethod(),
319                     url:this.getUrl(false),
320                     params:this.getParams()
321         }));
322     },
323
324     success : function(response){
325         var result = this.processResponse(response);
326         if(result === true || !result.success || !result.data){
327             this.failureType = Roo.form.Action.LOAD_FAILURE;
328             this.form.afterAction(this, false);
329             return;
330         }
331         this.form.clearInvalid();
332         this.form.setValues(result.data);
333         this.form.afterAction(this, true);
334     },
335
336     handleResponse : function(response){
337         if(this.form.reader){
338             var rs = this.form.reader.read(response);
339             var data = rs.records && rs.records[0] ? rs.records[0].data : null;
340             return {
341                 success : rs.success,
342                 data : data
343             };
344         }
345         return Roo.decode(response.responseText);
346     }
347 });
348
349 Roo.form.Action.ACTION_TYPES = {
350     'load' : Roo.form.Action.Load,
351     'submit' : Roo.form.Action.Submit
352 };