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         this.progressDialog = new Roo.bootstrap.Modal({
216             cls : 'roo-document-manager-progress-dialog',
217             allow_close : false,
218             title : '',
219             buttons : Roo.bootstrap.Modal.OK, 
220             listeners : { 
221                 btnclick : function() { 
222                      this.hide();
223                 }
224             }
225         });
226          
227         this.progressDialog.render(Roo.get(document.body));
228          
229         this.progress = new Roo.bootstrap.Progress({
230             cls : 'roo-document-manager-progress',
231             active : true,
232             striped : true,
233         });
234         
235         this.progress.render(this.progressDialog.getChildContainer());
236         
237         this.progressBar = new Roo.bootstrap.ProgressBar({
238             cls : 'roo-document-manager-progress-bar',
239             aria_valuenow : 0,
240             aria_valuemin : 0,
241             aria_valuemax : 12,
242             panel : 'success'
243         });
244         
245         this.progressBar.render(this.progress.getChildContainer());
246     },
247     
248     updateProgressDialog : function()
249     {
250         
251     },
252     
253     onUploaderClick : function(e)
254     {
255         e.preventDefault();
256         this.selectorEl.dom.click();
257     },
258     
259     onFileSelected : function(e)
260     {
261         e.preventDefault();
262         
263         if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
264             return;
265         }
266         
267         Roo.each(this.selectorEl.dom.files, function(file){
268             if(this.fireEvent('inspect', this, file) != false){
269                 this.files.push(file);
270             }
271         }, this);
272         
273         this.queue();
274         
275     },
276     
277     queue : function()
278     {
279         this.selectorEl.dom.value = '';
280         
281         if(!this.files.length){
282             return;
283         }
284         
285         if(this.files.length > this.boxes){
286             this.files = this.files.slice(0, this.boxes);
287         }
288         
289         var _this = this;
290         
291         var files = [];
292         
293         Roo.each(this.files, function(file){
294             
295             if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
296                 files.push(file);
297                 return;
298             }
299             
300             this.delegates.push(
301                 (function(){
302                     _this.process(file);
303                 }).createDelegate(this)
304             );
305             
306         }, this);
307         
308         this.files = files;
309         
310         this.arrange();
311         
312         return;
313         
314         
315         if(!this.delegates.length){
316             return;
317         }
318         
319         this.progressBar.aria_valuemax = this.delegates.length;
320         
321         var delegate = this.delegates.shift();
322         
323         delegate();
324         
325         return;
326         
327         var xhr = new XMLHttpRequest();
328         
329         Roo.each(this.files, function(file, index){
330             if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
331                 return;
332             }
333             
334             file.xhr = xhr;
335             
336             this.managerEl.createChild({
337                 tag : 'div',
338                 cls : 'roo-document-manager-loading',
339                 cn : [
340                     {
341                         tag : 'div',
342                         tooltip : file.name,
343                         cls : 'roo-document-manager-thumb',
344                         html : '<i class="fa fa-spinner fa-pulse"></i>'
345                     }
346                 ]
347
348             });
349             
350         }, this);
351         
352         if(this.files.length > this.boxes - 1 ){
353             this.uploader.hide();
354         }
355         
356         var headers = {
357             "Accept": "application/json",
358             "Cache-Control": "no-cache",
359             "X-Requested-With": "XMLHttpRequest"
360         };
361         
362         xhr.open(this.method, this.url, true);
363         
364         for (var headerName in headers) {
365             var headerValue = headers[headerName];
366             if (headerValue) {
367                 xhr.setRequestHeader(headerName, headerValue);
368             }
369         }
370         
371         var _this = this;
372         
373         xhr.onload = function()
374         {
375             _this.xhrOnLoad(xhr);
376         }
377         
378         xhr.onerror = function()
379         {
380             _this.xhrOnError(xhr);
381         }
382         
383         var formData = new FormData();
384
385         formData.append('returnHTML', 'NO');
386         
387         Roo.each(this.files, function(file, index){
388             
389             if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
390                 return;
391             }
392             
393             formData.append(this.getParamName(index), file, file.name);
394             
395         }, this);
396         
397         if(this.fireEvent('prepare', this, formData) != false){
398             xhr.send(formData);
399         };
400         
401     },
402     
403     arrange : function()
404     {
405         if(!this.delegates.length){
406             return;
407         }
408         
409         Roo.log('arrange...');
410         
411         Roo.log(this.delegates.length);
412         
413 //        this.progressBar.aria_valuemax = this.delegates.length;
414         
415         var delegate = this.delegates.shift();
416         
417         delegate();
418     },
419     
420     refresh : function()
421     {
422         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
423             el.remove();
424         }, this);
425         
426         
427         var files = [];
428         
429         Roo.each(this.files, function(file){
430             
431             if(typeof(file.id) == 'undefined' || file.id * 1 < 1){
432                 return;
433             }
434             
435             if(file.target){
436                 files.push(file);
437                 return;
438             }
439             
440             var previewEl = this.managerEl.createChild({
441                 tag : 'div',
442                 cls : 'roo-document-manager-preview',
443                 cn : [
444                     {
445                         tag : 'div',
446                         tooltip : file.filename,
447                         cls : 'roo-document-manager-thumb',
448                         html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
449                     },
450                     {
451                         tag : 'button',
452                         cls : 'close',
453                         html : 'x'
454                     }
455                 ]
456             });
457             
458             var close = previewEl.select('button.close', true).first();
459             
460             close.on('click', this.onRemove, this, file);
461             
462             file.target = previewEl;
463             
464             var image = previewEl.select('img', true).first();
465             
466             image.on('click', this.onClick, this, file);
467             
468             files.push(file);
469             
470             return;
471             
472         }, this);
473         
474         this.files = files;
475         
476         this.uploader.show();
477         
478         if(this.files.length > this.boxes - 1){
479             this.uploader.hide();
480         }
481         
482         Roo.isTouch ? this.closable(false) : this.closable(true);
483         
484         this.fireEvent('refresh', this);
485     },
486     
487     onRemove : function(e, el, o)
488     {
489         e.preventDefault();
490         
491         this.fireEvent('remove', this, o);
492         
493     },
494     
495     remove : function(o)
496     {
497         var files = [];
498         
499         Roo.each(this.files, function(file){
500             if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
501                 files.push(file);
502                 return;
503             }
504
505             o.target.remove();
506
507         }, this);
508         
509         this.files = files;
510         
511         this.refresh();
512     },
513     
514     onClick : function(e, el, o)
515     {
516         e.preventDefault();
517         
518         this.fireEvent('click', this, o);
519         
520     },
521     
522     closable : function(closable)
523     {
524         Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
525             
526             el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
527             
528             if(closable){
529                 el.show();
530                 return;
531             }
532             
533             el.hide();
534             
535         }, this);
536     },
537     
538     xhrOnLoad : function(xhr)
539     {
540         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
541             el.remove();
542         }, this);
543         
544         if (xhr.readyState !== 4) {
545             this.arrange();
546             this.fireEvent('exception', this, xhr);
547             return;
548         }
549
550         var response = Roo.decode(xhr.responseText);
551         
552         if(!response.success){
553             this.arrange();
554             this.fireEvent('exception', this, xhr);
555             return;
556         }
557         
558         var previewEl = this.managerEl.createChild({
559             tag : 'div',
560             cls : 'roo-document-manager-preview',
561             cn : [
562                 {
563                     tag : 'div',
564                     tooltip : response.data.filename,
565                     cls : 'roo-document-manager-thumb',
566                     html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + response.data.id + '/' + response.data.filename + '">'
567                 },
568                 {
569                     tag : 'button',
570                     cls : 'close',
571                     html : 'x'
572                 }
573             ]
574         });
575
576         var close = previewEl.select('button.close', true).first();
577
578         close.on('click', this.onRemove, this, file);
579
580         response.data.target = previewEl;
581
582         var image = previewEl.select('img', true).first();
583
584         image.on('click', this.onClick, this, file);
585         
586         this.files.push(response.data);
587         
588         this.arrange();
589         
590     },
591     
592     xhrOnError : function()
593     {
594         Roo.log('xhr on error');
595         
596         var response = Roo.decode(xhr.responseText);
597           
598         Roo.log(response);
599         
600         this.arrange();
601     },
602     
603     process : function(file)
604     {
605         Roo.log('process...');
606         Roo.log(file);
607         
608         if(this.editable && file.type.indexOf('image') != -1){
609             this.fireEvent('edit', this, file);
610             return;
611         }
612         
613         
614         
615         return;
616     },
617     
618     uploadStart : function(file, crop)
619     {
620         var xhr = new XMLHttpRequest();
621         
622         if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
623             this.arrange();
624             return;
625         }
626         
627         file.xhr = xhr;
628             
629         this.managerEl.createChild({
630             tag : 'div',
631             cls : 'roo-document-manager-loading',
632             cn : [
633                 {
634                     tag : 'div',
635                     tooltip : file.name,
636                     cls : 'roo-document-manager-thumb',
637                     html : '<i class="fa fa-spinner fa-pulse"></i>'
638                 }
639             ]
640
641         });
642
643         xhr.open(this.method, this.url, true);
644         
645         var headers = {
646             "Accept": "application/json",
647             "Cache-Control": "no-cache",
648             "X-Requested-With": "XMLHttpRequest"
649         };
650         
651         for (var headerName in headers) {
652             var headerValue = headers[headerName];
653             if (headerValue) {
654                 xhr.setRequestHeader(headerName, headerValue);
655             }
656         }
657         
658         var _this = this;
659         
660         xhr.onload = function()
661         {
662             _this.xhrOnLoad(xhr);
663         }
664         
665         xhr.onerror = function()
666         {
667             _this.xhrOnError(xhr);
668         }
669         
670         var formData = new FormData();
671
672         formData.append('returnHTML', 'NO');
673         
674         if(crop){
675             formData.append('crop', crop);
676         }
677         
678         formData.append(this.paramName, file, file.name);
679         
680         if(this.fireEvent('prepare', this, formData) != false){
681             xhr.send(formData);
682         };
683     }
684     
685 });