Roo/bootstrap/DocumentManager.js
[roojs1] / Roo / bootstrap / DocumentManager.js
1
2 /*
3 * Licence: LGPL
4 */
5
6 /**
7  * @class Roo.bootstrap.DocumentManager
8  * @extends Roo.bootstrap.Component
9  * Bootstrap DocumentManager class
10  * @cfg {String} paramName default 'imageUpload'
11  * @cfg {String} method default POST
12  * @cfg {String} url action url
13  * @cfg {Number} boxes number of boxes default 12
14  * @cfg {Boolean} multiple multiple upload default true
15  * @cfg {Number} minWidth default 300
16  * @cfg {Number} minHeight default 300
17  * @cfg {Number} thumbSize default 300
18  * @cfg {String} fieldLabel
19  * @cfg {Number} labelWidth default 4
20  * @cfg {String} labelAlign (left|top) default left
21  * @cfg {Boolean} editable (true|false) allow edit when upload a image default true
22  * 
23  * @constructor
24  * Create a new DocumentManager
25  * @param {Object} config The config object
26  */
27
28 Roo.bootstrap.DocumentManager = function(config){
29     Roo.bootstrap.DocumentManager.superclass.constructor.call(this, config);
30     
31     this.addEvents({
32         /**
33          * @event initial
34          * Fire when initial the DocumentManager
35          * @param {Roo.bootstrap.DocumentManager} this
36          */
37         "initial" : true,
38         /**
39          * @event inspect
40          * inspect selected file
41          * @param {Roo.bootstrap.DocumentManager} this
42          * @param {File} file
43          */
44         "inspect" : true,
45         /**
46          * @event exception
47          * Fire when xhr load exception
48          * @param {Roo.bootstrap.DocumentManager} this
49          * @param {XMLHttpRequest} xhr
50          */
51         "exception" : true,
52         /**
53          * @event prepare
54          * prepare the form data
55          * @param {Roo.bootstrap.DocumentManager} this
56          * @param {Object} formData
57          */
58         "prepare" : true,
59         /**
60          * @event remove
61          * Fire when remove the file
62          * @param {Roo.bootstrap.DocumentManager} this
63          * @param {Object} file
64          */
65         "remove" : true,
66         /**
67          * @event refresh
68          * Fire after refresh the file
69          * @param {Roo.bootstrap.DocumentManager} this
70          */
71         "refresh" : true,
72         /**
73          * @event click
74          * Fire after click the image
75          * @param {Roo.bootstrap.DocumentManager} this
76          * @param {Object} file
77          */
78         "click" : true,
79         /**
80          * @event edit
81          * Fire when upload a image and editable set to true
82          * @param {Roo.bootstrap.DocumentManager} this
83          * @param {Object} file
84          */
85         "edit" : true
86         
87     });
88 };
89
90 Roo.extend(Roo.bootstrap.DocumentManager, Roo.bootstrap.Component,  {
91     
92     boxes : 12,
93     inputName : '',
94     minWidth : 300,
95     minHeight : 300,
96     thumbSize : 300,
97     multiple : true,
98     files : [],
99     method : 'POST',
100     url : '',
101     paramName : 'imageUpload',
102     fieldLabel : '',
103     labelWidth : 4,
104     labelAlign : 'left',
105     editable : true,
106     delegates : [],
107     
108     getAutoCreate : function()
109     {   
110         var managerWidget = {
111             tag : 'div',
112             cls : 'roo-document-manager',
113             cn : [
114                 {
115                     tag : 'input',
116                     cls : 'roo-document-manager-selector',
117                     type : 'file'
118                 },
119                 {
120                     tag : 'div',
121                     cls : 'roo-document-manager-uploader',
122                     cn : [
123                         {
124                             tag : 'div',
125                             cls : 'roo-document-manager-upload-btn',
126                             html : '<i class="fa fa-plus"></i>'
127                         }
128                     ]
129                     
130                 }
131             ]
132         };
133         
134         var content = [
135             {
136                 tag : 'div',
137                 cls : 'column col-md-12',
138                 cn : managerWidget
139             }
140         ];
141         
142         if(this.fieldLabel.length){
143             
144             content = [
145                 {
146                     tag : 'div',
147                     cls : 'column col-md-12',
148                     html : this.fieldLabel
149                 },
150                 {
151                     tag : 'div',
152                     cls : 'column col-md-12',
153                     cn : managerWidget
154                 }
155             ];
156
157             if(this.labelAlign == 'left'){
158                 content = [
159                     {
160                         tag : 'div',
161                         cls : 'column col-md-' + this.labelWidth,
162                         html : this.fieldLabel
163                     },
164                     {
165                         tag : 'div',
166                         cls : 'column col-md-' + (12 - this.labelWidth),
167                         cn : managerWidget
168                     }
169                 ];
170                 
171             }
172         }
173         
174         var cfg = {
175             tag : 'div',
176             cls : 'row clearfix',
177             cn : content
178         };
179         
180         return cfg;
181         
182     },
183     
184     initEvents : function()
185     {
186         this.managerEl = this.el.select('.roo-document-manager', true).first();
187         this.managerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
188         
189         this.selectorEl = this.el.select('.roo-document-manager-selector', true).first();
190         this.selectorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
191         this.selectorEl.hide();
192         
193         if(this.multiple){
194             this.selectorEl.attr('multiple', 'multiple');
195         }
196         
197         this.selectorEl.on('change', this.onFileSelected, this);
198         
199         this.uploader = this.el.select('.roo-document-manager-uploader', true).first();
200         this.uploader.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
201         
202         this.uploader.on('click', this.onUploaderClick, this);
203         
204         this.renderProgressDialog();
205         
206         var _this = this;
207         
208         window.addEventListener("resize", function() { _this.refresh(); } );
209         
210         this.fireEvent('initial', this);
211     },
212     
213     renderProgressDialog : function()
214     {
215         var _this = this;
216         
217         this.progressDialog = new Roo.bootstrap.Modal({
218             cls : 'roo-document-manager-progress-dialog',
219             allow_close : false,
220             title : '',
221             buttons : [
222                 {
223                     name  :'cancel',
224                     weight : 'danger',
225                     html : 'Cancel'
226                 }
227             ], 
228             listeners : { 
229                 btnclick : function() {
230                     _this.uploadCancel();
231                     this.hide();
232                 }
233             }
234         });
235          
236         this.progressDialog.render(Roo.get(document.body));
237          
238         this.progress = new Roo.bootstrap.Progress({
239             cls : 'roo-document-manager-progress',
240             active : true,
241             striped : true,
242         });
243         
244         this.progress.render(this.progressDialog.getChildContainer());
245         
246         this.progressBar = new Roo.bootstrap.ProgressBar({
247             cls : 'roo-document-manager-progress-bar',
248             aria_valuenow : 0,
249             aria_valuemin : 0,
250             aria_valuemax : 12,
251             panel : 'success'
252         });
253         
254         this.progressBar.render(this.progress.getChildContainer());
255     },
256     
257     onUploaderClick : function(e)
258     {
259         e.preventDefault();
260         this.selectorEl.dom.click();
261     },
262     
263     onFileSelected : function(e)
264     {
265         e.preventDefault();
266         
267         if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
268             return;
269         }
270         
271         Roo.each(this.selectorEl.dom.files, function(file){
272             if(this.fireEvent('inspect', this, file) != false){
273                 this.files.push(file);
274             }
275         }, this);
276         
277         this.queue();
278         
279     },
280     
281     queue : function()
282     {
283         this.selectorEl.dom.value = '';
284         
285         if(!this.files.length){
286             return;
287         }
288         
289         if(this.files.length > this.boxes){
290             this.files = this.files.slice(0, this.boxes);
291         }
292         
293         this.uploader.show();
294         
295         if(this.files.length > this.boxes - 1){
296             this.uploader.hide();
297         }
298         
299         var _this = this;
300         
301         var files = [];
302         
303         Roo.each(this.files, function(file){
304             
305             if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
306                 files.push(file);
307                 return;
308             }
309             
310             this.delegates.push(
311                 (function(){
312                     _this.process(file);
313                 }).createDelegate(this)
314             );
315             
316         }, this);
317         
318         this.files = files;
319         
320         if(!this.delegates.length){
321             this.refresh();
322             return;
323         }
324         
325         this.progressBar.aria_valuemax = this.delegates.length;
326         
327         this.arrange();
328         
329         return;
330     },
331     
332     arrange : function()
333     {
334         if(!this.delegates.length){
335             this.progressDialog.hide();
336             this.refresh();
337             return;
338         }
339         
340         var delegate = this.delegates.shift();
341         
342         this.progressDialog.show();
343         
344         this.progressDialog.setTitle((this.progressBar.aria_valuemax - this.delegates.length) + ' / ' + this.progressBar.aria_valuemax);
345         
346         this.progressBar.update(this.progressBar.aria_valuemax - this.delegates.length);
347         
348         delegate();
349     },
350     
351     refresh : function()
352     {
353         this.uploader.show();
354         
355         if(this.files.length > this.boxes - 1){
356             this.uploader.hide();
357         }
358         
359         Roo.isTouch ? this.closable(false) : this.closable(true);
360         
361         this.fireEvent('refresh', this);
362     },
363     
364     onRemove : function(e, el, o)
365     {
366         e.preventDefault();
367         
368         this.fireEvent('remove', this, o);
369         
370     },
371     
372     remove : function(o)
373     {
374         var files = [];
375         
376         Roo.each(this.files, function(file){
377             if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
378                 files.push(file);
379                 return;
380             }
381
382             o.target.remove();
383
384         }, this);
385         
386         this.files = files;
387         
388         this.refresh();
389     },
390     
391     onClick : function(e, el, o)
392     {
393         e.preventDefault();
394         
395         this.fireEvent('click', this, o);
396         
397     },
398     
399     closable : function(closable)
400     {
401         Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
402             
403             el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
404             
405             if(closable){
406                 el.show();
407                 return;
408             }
409             
410             el.hide();
411             
412         }, this);
413     },
414     
415     xhrOnLoad : function(xhr)
416     {
417         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
418             el.remove();
419         }, this);
420         
421         if (xhr.readyState !== 4) {
422             this.arrange();
423             this.fireEvent('exception', this, xhr);
424             return;
425         }
426
427         var response = Roo.decode(xhr.responseText);
428         
429         if(!response.success){
430             this.arrange();
431             this.fireEvent('exception', this, xhr);
432             return;
433         }
434         
435         var file = this.renderPreview(response.data);
436         
437         this.files.push(file);
438         
439         this.arrange();
440         
441     },
442     
443     xhrOnError : function()
444     {
445         Roo.log('xhr on error');
446         
447         var response = Roo.decode(xhr.responseText);
448           
449         Roo.log(response);
450         
451         this.arrange();
452     },
453     
454     process : function(file)
455     {
456         if(this.editable && file.type.indexOf('image') != -1){
457             this.fireEvent('edit', this, file);
458             return;
459         }
460         
461         this.uploadStart(file, false);
462         
463         return;
464     },
465     
466     uploadStart : function(file, crop)
467     {
468         this.xhr = new XMLHttpRequest();
469         
470         if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
471             this.arrange();
472             return;
473         }
474         
475         file.xhr = this.xhr;
476             
477         this.managerEl.createChild({
478             tag : 'div',
479             cls : 'roo-document-manager-loading',
480             cn : [
481                 {
482                     tag : 'div',
483                     tooltip : file.name,
484                     cls : 'roo-document-manager-thumb',
485                     html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
486                 }
487             ]
488
489         });
490
491         this.xhr.open(this.method, this.url, true);
492         
493         var headers = {
494             "Accept": "application/json",
495             "Cache-Control": "no-cache",
496             "X-Requested-With": "XMLHttpRequest"
497         };
498         
499         for (var headerName in headers) {
500             var headerValue = headers[headerName];
501             if (headerValue) {
502                 this.xhr.setRequestHeader(headerName, headerValue);
503             }
504         }
505         
506         var _this = this;
507         
508         this.xhr.onload = function()
509         {
510             _this.xhrOnLoad(_this.xhr);
511         }
512         
513         this.xhr.onerror = function()
514         {
515             _this.xhrOnError(_this.xhr);
516         }
517         
518         var formData = new FormData();
519
520         formData.append('returnHTML', 'NO');
521         
522         if(crop){
523             formData.append('crop', crop);
524         }
525         
526         formData.append(this.paramName, file, file.name);
527         
528         if(this.fireEvent('prepare', this, formData) != false){
529             this.xhr.send(formData);
530         };
531     },
532     
533     uploadCancel : function()
534     {
535         this.xhr.abort();
536         
537         this.delegates = [];
538         
539         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
540             el.remove();
541         }, this);
542         
543         this.arrange();
544     },
545     
546     renderPreview : function(file)
547     {
548         var previewEl = this.managerEl.createChild({
549             tag : 'div',
550             cls : 'roo-document-manager-preview',
551             cn : [
552                 {
553                     tag : 'div',
554                     tooltip : file.filename,
555                     cls : 'roo-document-manager-thumb',
556                     html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
557                 },
558                 {
559                     tag : 'button',
560                     cls : 'close',
561                     html : 'x'
562                 }
563             ]
564         });
565
566         var close = previewEl.select('button.close', true).first();
567
568         close.on('click', this.onRemove, this, file);
569
570         file.target = previewEl;
571
572         var image = previewEl.select('img', true).first();
573
574         image.on('click', this.onClick, this, file);
575         
576         return file;
577     }
578     
579 });