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 : [
220                 {
221                     name  :'cancel',
222                     weight : 'danger',
223                     html : 'Cancel'
224                 }
225             ], 
226             listeners : { 
227                 btnclick : function() { 
228                      this.hide();
229                 }
230             }
231         });
232          
233         this.progressDialog.render(Roo.get(document.body));
234          
235         this.progress = new Roo.bootstrap.Progress({
236             cls : 'roo-document-manager-progress',
237             active : true,
238             striped : true,
239         });
240         
241         this.progress.render(this.progressDialog.getChildContainer());
242         
243         this.progressBar = new Roo.bootstrap.ProgressBar({
244             cls : 'roo-document-manager-progress-bar',
245             aria_valuenow : 0,
246             aria_valuemin : 0,
247             aria_valuemax : 12,
248             panel : 'success'
249         });
250         
251         this.progressBar.render(this.progress.getChildContainer());
252     },
253     
254     updateProgressDialog : function()
255     {
256         
257     },
258     
259     onUploaderClick : function(e)
260     {
261         e.preventDefault();
262         this.selectorEl.dom.click();
263     },
264     
265     onFileSelected : function(e)
266     {
267         e.preventDefault();
268         
269         if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
270             return;
271         }
272         
273         Roo.each(this.selectorEl.dom.files, function(file){
274             if(this.fireEvent('inspect', this, file) != false){
275                 this.files.push(file);
276             }
277         }, this);
278         
279         this.queue();
280         
281     },
282     
283     queue : function()
284     {
285         this.selectorEl.dom.value = '';
286         
287         if(!this.files.length){
288             return;
289         }
290         
291         if(this.files.length > this.boxes){
292             this.files = this.files.slice(0, this.boxes);
293         }
294         
295         this.uploader.show();
296         
297         if(this.files.length > this.boxes - 1){
298             this.uploader.hide();
299         }
300         
301         var _this = this;
302         
303         var files = [];
304         
305         Roo.each(this.files, function(file){
306             
307             if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
308                 files.push(file);
309                 return;
310             }
311             
312             this.delegates.push(
313                 (function(){
314                     _this.process(file);
315                 }).createDelegate(this)
316             );
317             
318         }, this);
319         
320         this.files = files;
321         
322         if(!this.delegates.length){
323             this.refresh();
324             return;
325         }
326         
327         this.progressBar.aria_valuemax = this.delegates.length;
328         
329         this.arrange();
330         
331         return;
332     },
333     
334     arrange : function()
335     {
336         if(!this.delegates.length){
337             this.progressDialog.hide();
338             this.refresh();
339             return;
340         }
341         
342         var delegate = this.delegates.shift();
343         
344         this.progressDialog.show();
345         
346         this.progressDialog.setTitle((this.progressBar.aria_valuemax - this.delegates.length) + ' / ' + this.progressBar.aria_valuemax);
347         
348         this.progressBar.update(this.progressBar.aria_valuemax - this.delegates.length);
349         
350         delegate();
351     },
352     
353     refresh : function()
354     {
355         this.uploader.show();
356         
357         if(this.files.length > this.boxes - 1){
358             this.uploader.hide();
359         }
360         
361         Roo.isTouch ? this.closable(false) : this.closable(true);
362         
363         this.fireEvent('refresh', this);
364     },
365     
366     onRemove : function(e, el, o)
367     {
368         e.preventDefault();
369         
370         this.fireEvent('remove', this, o);
371         
372     },
373     
374     remove : function(o)
375     {
376         var files = [];
377         
378         Roo.each(this.files, function(file){
379             if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
380                 files.push(file);
381                 return;
382             }
383
384             o.target.remove();
385
386         }, this);
387         
388         this.files = files;
389         
390         this.refresh();
391     },
392     
393     onClick : function(e, el, o)
394     {
395         e.preventDefault();
396         
397         this.fireEvent('click', this, o);
398         
399     },
400     
401     closable : function(closable)
402     {
403         Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
404             
405             el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
406             
407             if(closable){
408                 el.show();
409                 return;
410             }
411             
412             el.hide();
413             
414         }, this);
415     },
416     
417     xhrOnLoad : function(xhr)
418     {
419         Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
420             el.remove();
421         }, this);
422         
423         if (xhr.readyState !== 4) {
424             this.arrange();
425             this.fireEvent('exception', this, xhr);
426             return;
427         }
428
429         var response = Roo.decode(xhr.responseText);
430         
431         if(!response.success){
432             this.arrange();
433             this.fireEvent('exception', this, xhr);
434             return;
435         }
436         
437         var previewEl = this.managerEl.createChild({
438             tag : 'div',
439             cls : 'roo-document-manager-preview',
440             cn : [
441                 {
442                     tag : 'div',
443                     tooltip : response.data.filename,
444                     cls : 'roo-document-manager-thumb',
445                     html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + response.data.id + '/' + response.data.filename + '">'
446                 },
447                 {
448                     tag : 'button',
449                     cls : 'close',
450                     html : 'x'
451                 }
452             ]
453         });
454
455         var close = previewEl.select('button.close', true).first();
456
457         close.on('click', this.onRemove, this, response.data);
458
459         response.data.target = previewEl;
460
461         var image = previewEl.select('img', true).first();
462
463         image.on('click', this.onClick, this, response.data);
464         
465         this.files.push(response.data);
466         
467         this.arrange();
468         
469     },
470     
471     xhrOnError : function()
472     {
473         Roo.log('xhr on error');
474         
475         var response = Roo.decode(xhr.responseText);
476           
477         Roo.log(response);
478         
479         this.arrange();
480     },
481     
482     process : function(file)
483     {
484         if(this.editable && file.type.indexOf('image') != -1){
485             this.fireEvent('edit', this, file);
486             return;
487         }
488         
489         this.uploadStart(file, false);
490         
491         return;
492     },
493     
494     uploadStart : function(file, crop)
495     {
496         this.xhr = new XMLHttpRequest();
497         
498         if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
499             this.arrange();
500             return;
501         }
502         
503         file.xhr = this.xhr;
504             
505         this.managerEl.createChild({
506             tag : 'div',
507             cls : 'roo-document-manager-loading',
508             cn : [
509                 {
510                     tag : 'div',
511                     tooltip : file.name,
512                     cls : 'roo-document-manager-thumb',
513                     html : '<i class="fa fa-circle-o-notch fa-spin"></i>'
514                 }
515             ]
516
517         });
518
519         this.xhr.open(this.method, this.url, true);
520         
521         var headers = {
522             "Accept": "application/json",
523             "Cache-Control": "no-cache",
524             "X-Requested-With": "XMLHttpRequest"
525         };
526         
527         for (var headerName in headers) {
528             var headerValue = headers[headerName];
529             if (headerValue) {
530                 this.xhr.setRequestHeader(headerName, headerValue);
531             }
532         }
533         
534         var _this = this;
535         
536         this.xhr.onload = function()
537         {
538             _this.xhrOnLoad(_this.xhr);
539         }
540         
541         this.xhr.onerror = function()
542         {
543             _this.xhrOnError(_this.xhr);
544         }
545         
546         var formData = new FormData();
547
548         formData.append('returnHTML', 'NO');
549         
550         if(crop){
551             formData.append('crop', crop);
552         }
553         
554         formData.append(this.paramName, file, file.name);
555         
556         if(this.fireEvent('prepare', this, formData) != false){
557             this.xhr.send(formData);
558         };
559     }
560     
561 });