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