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                 var f = this.renderPreview(file);
307                 files.push(f);
308                 return;
309             }
310             
311             this.delegates.push(
312                 (function(){
313                     _this.process(file);
314                 }).createDelegate(this)
315             );
316             
317         }, this);
318         
319         this.files = files;
320         
321         if(!this.delegates.length){
322             this.refresh();
323             return;
324         }
325         
326         this.progressBar.aria_valuemax = this.delegates.length;
327         
328         this.arrange();
329         
330         return;
331     },
332     
333     arrange : function()
334     {
335         if(!this.delegates.length){
336             this.progressDialog.hide();
337             this.refresh();
338             return;
339         }
340         
341         var delegate = this.delegates.shift();
342         
343         this.progressDialog.show();
344         
345         this.progressDialog.setTitle((this.progressBar.aria_valuemax - this.delegates.length) + ' / ' + this.progressBar.aria_valuemax);
346         
347         this.progressBar.update(this.progressBar.aria_valuemax - this.delegates.length);
348         
349         delegate();
350     },
351     
352     refresh : function()
353     {
354         this.uploader.show();
355         
356         if(this.files.length > this.boxes - 1){
357             this.uploader.hide();
358         }
359         
360         Roo.isTouch ? this.closable(false) : this.closable(true);
361         
362         this.fireEvent('refresh', this);
363     },
364     
365     onRemove : function(e, el, o)
366     {
367         e.preventDefault();
368         
369         this.fireEvent('remove', this, o);
370         
371     },
372     
373     remove : function(o)
374     {
375         var files = [];
376         
377         Roo.each(this.files, function(file){
378             if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
379                 files.push(file);
380                 return;
381             }
382
383             o.target.remove();
384
385         }, this);
386         
387         this.files = files;
388         
389         this.refresh();
390     },
391     
392     onClick : function(e, el, o)
393     {
394         e.preventDefault();
395         
396         this.fireEvent('click', this, o);
397         
398     },
399     
400     closable : function(closable)
401     {
402         Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
403             
404             el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
405             
406             if(closable){
407                 el.show();
408                 return;
409             }
410             
411             el.hide();
412             
413         }, this);
414     },
415     
416     xhrOnLoad : function(xhr)
417     {
418         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
419             el.remove();
420         }, this);
421         
422         if (xhr.readyState !== 4) {
423             this.arrange();
424             this.fireEvent('exception', this, xhr);
425             return;
426         }
427
428         var response = Roo.decode(xhr.responseText);
429         
430         if(!response.success){
431             this.arrange();
432             this.fireEvent('exception', this, xhr);
433             return;
434         }
435         
436         var file = this.renderPreview(response.data);
437         
438         this.files.push(file);
439         
440         this.arrange();
441         
442     },
443     
444     xhrOnError : function()
445     {
446         Roo.log('xhr on error');
447         
448         var response = Roo.decode(xhr.responseText);
449           
450         Roo.log(response);
451         
452         this.arrange();
453     },
454     
455     process : function(file)
456     {
457         if(this.editable && file.type.indexOf('image') != -1){
458             this.fireEvent('edit', this, file);
459             return;
460         }
461         
462         this.uploadStart(file, false);
463         
464         return;
465     },
466     
467     uploadStart : function(file, crop)
468     {
469         this.xhr = new XMLHttpRequest();
470         
471         if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
472             this.arrange();
473             return;
474         }
475         
476         file.xhr = this.xhr;
477             
478         this.managerEl.createChild({
479             tag : 'div',
480             cls : 'roo-document-manager-loading',
481             cn : [
482                 {
483                     tag : 'div',
484                     tooltip : file.name,
485                     cls : 'roo-document-manager-thumb',
486                     html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
487                 }
488             ]
489
490         });
491
492         this.xhr.open(this.method, this.url, true);
493         
494         var headers = {
495             "Accept": "application/json",
496             "Cache-Control": "no-cache",
497             "X-Requested-With": "XMLHttpRequest"
498         };
499         
500         for (var headerName in headers) {
501             var headerValue = headers[headerName];
502             if (headerValue) {
503                 this.xhr.setRequestHeader(headerName, headerValue);
504             }
505         }
506         
507         var _this = this;
508         
509         this.xhr.onload = function()
510         {
511             _this.xhrOnLoad(_this.xhr);
512         }
513         
514         this.xhr.onerror = function()
515         {
516             _this.xhrOnError(_this.xhr);
517         }
518         
519         var formData = new FormData();
520
521         formData.append('returnHTML', 'NO');
522         
523         if(crop){
524             formData.append('crop', crop);
525         }
526         
527         formData.append(this.paramName, file, file.name);
528         
529         if(this.fireEvent('prepare', this, formData) != false){
530             this.xhr.send(formData);
531         };
532     },
533     
534     uploadCancel : function()
535     {
536         this.xhr.abort();
537         
538         this.delegates = [];
539         
540         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
541             el.remove();
542         }, this);
543         
544         this.arrange();
545     },
546     
547     renderPreview : function(file)
548     {
549         if(typeof(file.target) != 'undefined' && file.target){
550             return file;
551         }
552         
553         var previewEl = this.managerEl.createChild({
554             tag : 'div',
555             cls : 'roo-document-manager-preview',
556             cn : [
557                 {
558                     tag : 'div',
559                     tooltip : file.filename,
560                     cls : 'roo-document-manager-thumb',
561                     html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
562                 },
563                 {
564                     tag : 'button',
565                     cls : 'close',
566                     html : '<i class="fa fa-times-circle"></i>'
567                 }
568             ]
569         });
570
571         var close = previewEl.select('button.close', true).first();
572
573         close.on('click', this.onRemove, this, file);
574
575         file.target = previewEl;
576
577         var image = previewEl.select('img', true).first();
578         
579         var _this = this;
580         
581         image.dom.addEventListener("load", function(){ _this.onPreviewLoad(file, image); });
582         
583         image.on('click', this.onClick, this, file);
584         
585         return file;
586         
587     },
588     
589     onPreviewLoad : function(file, image)
590     {
591         if(typeof(file.target) == 'undefined' || !file.target){
592             return;
593         }
594         
595         var width = image.dom.naturalWidth || image.dom.width;
596         var height = image.dom.naturalHeight || image.dom.height;
597         
598         if(width > height){
599             file.target.addClass('wide');
600             return;
601         }
602         
603         file.target.addClass('tall');
604         return;
605         
606     }
607 });