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