docs/default.css
[roojs1] / roojs-bootstrap-debug.js
index 5473f06..0041048 100644 (file)
@@ -989,6 +989,7 @@ Roo.extend(Roo.bootstrap.Column, Roo.bootstrap.Component,  {
  * @cfg {String} icon (info-sign|check|...) glyphicon name
  * @cfg {Boolean} hidden (true|false) hide the element
  * @cfg {Boolean} expandable (true|false) default false
+ * @cfg {Boolean} expanded (true|false) default true
  * @cfg {String} rheader contet on the right of header
 
  *     
@@ -1116,15 +1117,16 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
                     
                     h.push({
                         tag: 'i',
-                        cls: 'fa fa-minus'
+                        cls: (this.expanded ? 'fa fa-minus' : 'fa fa-plus') 
                     });
+                    
                 }
                 
                 h.push(
                     {
                         tag: 'span',
                         cls : 'panel-title',
-                        html : this.header
+                        html : (this.expandable ? ' ' : '') + this.header
                     },
                     {
                         tag: 'span',
@@ -1135,6 +1137,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
                 
                 cfg.cn.push({
                     cls : 'panel-heading',
+                    style : this.expandable ? 'cursor: pointer' : '',
                     cn : h
                 });
                 
@@ -1142,7 +1145,7 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             body = false;
             cfg.cn.push({
-                cls : 'panel-body',
+                cls : 'panel-body' + (this.expanded ? '' : ' hide'),
                 html : this.html
             });
             
@@ -1214,8 +1217,10 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             this.expanded = true;
             
-            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
-        
+            //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).show();
+            
+            this.el.select('.panel-body',true).first().removeClass('hide');
+            
             var toggleEl = this.toggleEl();
 
             if(!toggleEl){
@@ -1233,7 +1238,8 @@ Roo.extend(Roo.bootstrap.Container, Roo.bootstrap.Component,  {
             
             this.expanded = false;
             
-            this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+            //this.el.select('.panel-body',true).first().setVisibilityMode(Roo.Element.DISPLAY).hide();
+            this.el.select('.panel-body',true).first().addClass('hide');
         
             var toggleEl = this.toggleEl();
 
@@ -2421,7 +2427,7 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
     
         if (this.buttons.length) {
             Roo.each(this.buttons, function(bb) {
-                b = Roo.apply({}, bb);
+                var b = Roo.apply({}, bb);
                 b.xns = b.xns || Roo.bootstrap;
                 b.xtype = b.xtype || 'Button';
                 if (typeof(b.listeners) == 'undefined') {
@@ -2542,8 +2548,18 @@ Roo.extend(Roo.bootstrap.Modal, Roo.bootstrap.Component,  {
         if (this.allow_close) {
             this.closeEl.on('click', this.hide, this);
         }
+        
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.resize(); } );
 
     },
+    
+    resize : function()
+    {
+        this.maskEl.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
+    },
+    
     show : function() {
         
         if (!this.rendered) {
@@ -7462,6 +7478,7 @@ Roo.form.VTypes = function(){
  * @cfg {String} autocomplete - default is new-password see: https://developers.google.com/web/fundamentals/input/form/label-and-name-inputs?hl=en
 
  * @cfg {String} align (left|center|right) Default left
+ * @cfg {Boolean} forceFeedback (true|false) Default false
  * 
  * 
  * 
@@ -7657,6 +7674,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
     readOnly : false,
     align : false,
     formatedValue : false,
+    forceFeedback : false,
     
     parentLabelAlign : function()
     {
@@ -7877,7 +7895,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
         this.inputEl().on("blur", this.onBlur,  this);
         
         this.inputEl().relayEvent('keyup', this);
-
         // reference to original value for reset
         this.originalValue = this.getValue();
         //Roo.form.TextField.superclass.initEvents.call(this);
@@ -8194,7 +8212,7 @@ Roo.extend(Roo.bootstrap.Input, Roo.bootstrap.Component,  {
             if(feedback){
                 this.el.select('.form-control-feedback', true).first().removeClass([this.invalidFeedbackClass, this.validFeedbackClass]);
                 
-                if(this.getValue().length){
+                if(this.getValue().length || this.forceFeedback){
                     this.el.select('.form-control-feedback', true).first().addClass([this.invalidFeedbackClass]);
                 }
                 
@@ -13368,6 +13386,8 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
 
             this.hideTouchView();
             
+            this.fireEvent('select', this, r, rowIndex);
+            
             return;
         }
         
@@ -13381,8 +13401,6 @@ Roo.extend(Roo.bootstrap.ComboBox, Roo.bootstrap.TriggerField, {
         this.addItem(r.data);
         this.tickItems.push(r.data);
         
-        
-        
     }
     
 
@@ -23937,8 +23955,11 @@ Roo.extend(Roo.bootstrap.Alert, Roo.bootstrap.Component,  {
  * @extends Roo.bootstrap.Component
  * Bootstrap UploadCropbox class
  * @cfg {String} emptyText show when image has been loaded
+ * @cfg {String} rotateNotify show when image too small to rotate
+ * @cfg {Number} errorTimeout default 3000
  * @cfg {Number} minWidth default 300
  * @cfg {Number} minHeight default 300
+ * @cfg {Array} buttons default ['rotateLeft', 'pictureBtn', 'rotateRight']
  * 
  * @constructor
  * Create a new UploadCropbox
@@ -23950,7 +23971,7 @@ Roo.bootstrap.UploadCropbox = function(config){
     
     this.addEvents({
         /**
-         * @event beforeSelectFile
+         * @event beforeselectfile
          * Fire before select file
          * @param {Roo.bootstrap.UploadCropbox} this
          */
@@ -23965,7 +23986,7 @@ Roo.bootstrap.UploadCropbox = function(config){
          * @event crop
          * Fire after initEvent
          * @param {Roo.bootstrap.UploadCropbox} this
-         * @param {String} imageData
+         * @param {String} data
          */
         "crop" : true,
         /**
@@ -23974,14 +23995,57 @@ Roo.bootstrap.UploadCropbox = function(config){
          * @param {Roo.bootstrap.UploadCropbox} this
          * @param {Object} file
          */
-        "prepare" : true
+        "prepare" : true,
+        /**
+         * @event exception
+         * Fire when get exception
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {Object} options
+         */
+        "exception" : true,
+        /**
+         * @event beforeloadcanvas
+         * Fire before load the canvas
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} src
+         */
+        "beforeloadcanvas" : true,
+        /**
+         * @event trash
+         * Fire when trash image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "trash" : true,
+        /**
+         * @event download
+         * Fire when download the image
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "download" : true,
+        /**
+         * @event footerbuttonclick
+         * Fire when footerbuttonclick
+         * @param {Roo.bootstrap.UploadCropbox} this
+         * @param {String} type
+         */
+        "footerbuttonclick" : true,
+        /**
+         * @event resize
+         * Fire when resize
+         * @param {Roo.bootstrap.UploadCropbox} this
+         */
+        "resize" : true
         
     });
+    
+    this.buttons = this.buttons || Roo.bootstrap.UploadCropbox.footer.STANDARD;
 };
 
 Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
     
     emptyText : 'Click to upload image',
+    rotateNotify : 'Image is too small to rotate',
+    errorTimeout : 3000,
     scale : 0,
     baseScale : 1,
     rotate : 0,
@@ -23989,11 +24053,15 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
     pinching : false,
     mouseX : 0,
     mouseY : 0,
-    cropImageData : false,
-    cropType : 'image/png',
+    cropData : false,
     minWidth : 300,
     minHeight : 300,
     file : false,
+    exif : {},
+    baseRotate : 1,
+    cropType : 'image/jpeg',
+    buttons : false,
+    canvasLoaded : false,
     
     getAutoCreate : function()
     {
@@ -24003,17 +24071,12 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
             cn : [
                 {
                     tag : 'div',
-                    cls : 'roo-upload-cropbox-image-section',
+                    cls : 'roo-upload-cropbox-body',
+                    style : 'cursor:pointer',
                     cn : [
                         {
                             tag : 'div',
-                            cls : 'roo-upload-cropbox-canvas',
-                            cn : [
-                                {
-                                    tag : 'img',
-                                    cls : 'roo-upload-cropbox-image'
-                                }
-                            ]
+                            cls : 'roo-upload-cropbox-preview'
                         },
                         {
                             tag : 'div',
@@ -24023,50 +24086,21 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
                             tag : 'div',
                             cls : 'roo-upload-cropbox-empty-notify',
                             html : this.emptyText
+                        },
+                        {
+                            tag : 'div',
+                            cls : 'roo-upload-cropbox-error-notify alert alert-danger',
+                            html : this.rotateNotify
                         }
                     ]
                 },
                 {
                     tag : 'div',
-                    cls : 'roo-upload-cropbox-footer-section',
+                    cls : 'roo-upload-cropbox-footer',
                     cn : {
                         tag : 'div',
                         cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group',
-                        cn : [
-                            {
-                                tag : 'div',
-                                cls : 'btn-group',
-                                cn : [
-                                    {
-                                        tag : 'button',
-                                        cls : 'btn btn-default roo-upload-cropbox-rotate-left',
-                                        html : '<i class="fa fa-undo"></i>'
-                                    }
-                                ]
-                            },
-                            {
-                                tag : 'div',
-                                cls : 'btn-group',
-                                cn : [
-                                    {
-                                        tag : 'button',
-                                        cls : 'btn btn-default roo-upload-cropbox-picture',
-                                        html : '<i class="fa fa-picture-o"></i>'
-                                    }
-                                ]
-                            },
-                            {
-                                tag : 'div',
-                                cls : 'btn-group',
-                                cn : [
-                                    {
-                                        tag : 'button',
-                                        cls : 'btn btn-default roo-upload-cropbox-rotate-right',
-                                        html : '<i class="fa fa-repeat"></i>'
-                                    }
-                                ]
-                            }
-                        ]
+                        cn : []
                     }
                 }
             ]
@@ -24075,73 +24109,79 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
         return cfg;
     },
     
-    initEvents : function()
+    onRender : function(ct, position)
     {
-        this.imageSection = this.el.select('.roo-upload-cropbox-image-section', true).first();
-        this.imageSection.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-        
-        this.imageCanvas = this.el.select('.roo-upload-cropbox-canvas', true).first();
-        this.imageCanvas.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        Roo.bootstrap.UploadCropbox.superclass.onRender.call(this, ct, position);
         
-        this.image = this.el.select('.roo-upload-cropbox-image', true).first();
-        this.image.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-        
-        this.thumb = this.el.select('.roo-upload-cropbox-thumb', true).first();
-        this.thumb.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-        this.thumb.hide();
+        if (this.buttons.length) {
+            
+            Roo.each(this.buttons, function(bb) {
+                
+                var btn = this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb);
+                
+                btn.on('click', this.onFooterButtonClick.createDelegate(this, [bb.action], true));
+                
+            }, this);
+        }
+    },
+    
+    initEvents : function()
+    {
+        this.urlAPI = (window.createObjectURL && window) || 
+                                (window.URL && URL.revokeObjectURL && URL) || 
+                                (window.webkitURL && webkitURL);
+                        
+        this.bodyEl = this.el.select('.roo-upload-cropbox-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.emptyNotify = this.el.select('.roo-upload-cropbox-empty-notify', true).first();
-        this.emptyNotify.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first();
+        this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.footerSection = this.el.select('.roo-upload-cropbox-footer-section', true).first();
-        this.footerSection.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
-        this.footerSection.hide();
+        this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.thumbEl.hide();
         
-        this.rotateLeft = this.el.select('.roo-upload-cropbox-rotate-left', true).first();
-        this.rotateLeft.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first();
+        this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
         
-        this.pictureBtn = this.el.select('.roo-upload-cropbox-picture', true).first();
-        this.pictureBtn.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.errorEl = this.el.select('.roo-upload-cropbox-error-notify', true).first();
+        this.errorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.errorEl.hide();
         
-        this.rotateRight = this.el.select('.roo-upload-cropbox-rotate-right', true).first();
-        this.rotateRight.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.footerEl.hide();
         
-        this.calcThumbBoxSize();
+        this.setThumbBoxSize();
         
         this.bind();
         
+        this.resize();
+        
         this.fireEvent('initial', this);
     },
 
     bind : function()
     {
-        this.image.on('load', this.onLoadCanvasImage, this);
+        var _this = this;
         
-        if(!this.imageSectionHasOnClickEvent){
-            this.imageSection.on('click', this.beforeSelectFile, this);
-            this.imageSectionHasOnClickEvent = true;
-        }
+        window.addEventListener("resize", function() { _this.resize(); } );
+        
+        this.bodyEl.on('click', this.beforeSelectFile, this);
         
         if(Roo.isTouch){
-            this.imageSection.on('touchstart', this.onTouchStart, this);
-            this.imageSection.on('touchmove', this.onTouchMove, this);
-            this.imageSection.on('touchend', this.onTouchEnd, this);
+            this.bodyEl.on('touchstart', this.onTouchStart, this);
+            this.bodyEl.on('touchmove', this.onTouchMove, this);
+            this.bodyEl.on('touchend', this.onTouchEnd, this);
         }
         
         if(!Roo.isTouch){
-            this.imageSection.on('mousedown', this.onMouseDown, this);
-            this.imageSection.on('mousemove', this.onMouseMove, this);
+            this.bodyEl.on('mousedown', this.onMouseDown, this);
+            this.bodyEl.on('mousemove', this.onMouseMove, this);
             var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel';
-            this.imageSection.on(mousewheel, this.onMouseWheel, this);
+            this.bodyEl.on(mousewheel, this.onMouseWheel, this);
             Roo.get(document).on('mouseup', this.onMouseUp, this);
         }
-        
-        this.pictureBtn.on('click', this.beforeSelectFile, this);
-        
-        this.rotateLeft.on('click', this.onRotateLeft, this);
-        
-        this.rotateRight.on('click', this.onRotateRight, this);
-        
     },
     
     reset : function()
@@ -24149,68 +24189,118 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
         this.scale = 0;
         this.baseScale = 1;
         this.rotate = 0;
+        this.baseRotate = 1;
         this.dragable = false;
         this.pinching = false;
         this.mouseX = 0;
         this.mouseY = 0;
-        this.cropImageData = false;
-        
-        this.imageCanvas.dom.removeAttribute('style');
-        this.image.dom.removeAttribute('style');
-        this.image.attr('src', '');
+        this.cropData = false;
+        this.notifyEl.dom.innerHTML = this.emptyText;
         
-        if(!this.imageSectionHasOnClickEvent){
-            this.imageSection.on('click', this.beforeSelectFile, this);
-            this.imageSectionHasOnClickEvent = true;
+    },
+    
+    resize : function()
+    {
+        if(this.fireEvent('resize', this) != false){
+            this.setThumbBoxPosition();
+            this.setCanvasPosition();
+        }
+    },
+    
+    onFooterButtonClick : function(e, el, o, type)
+    {
+        switch (type) {
+            case 'rotate-left' :
+                this.onRotateLeft(e);
+                break;
+            case 'rotate-right' :
+                this.onRotateRight(e);
+                break;
+            case 'picture' :
+                this.beforeSelectFile(e);
+                break;
+            case 'trash' :
+                this.trash(e);
+                break;
+            case 'crop' :
+                this.crop(e);
+                break;
+            case 'download' :
+                this.download(e);
+                break;
+            default :
+                break;
         }
         
+        this.fireEvent('footerbuttonclick', this, type);
     },
     
     beforeSelectFile : function(e)
     {
-        e.preventDefault();
-        
         this.fireEvent('beforeselectfile', this);
     },
     
-    loadCanvasImage : function(src)
+    trash : function(e)
+    {
+        this.fireEvent('trash', this);
+    },
+    
+    download : function(e)
+    {
+        this.fireEvent('download', this);
+    },
+    
+    loadCanvas : function(src)
     {   
-        this.reset();
-        
-        this.image.attr('src', src);
+        if(this.fireEvent('beforeloadcanvas', this, src) != false){
+            
+            this.reset();
+            
+            this.imageEl = document.createElement('img');
+            
+            var _this = this;
+            
+            this.imageEl.addEventListener("load", function(){ _this.onLoadCanvas(); });
+            
+            this.imageEl.src = src;
+        }
     },
     
-    onLoadCanvasImage : function(src)
+    onLoadCanvas : function()
     {   
-        this.emptyNotify.hide();
-        this.thumb.show();
-        this.footerSection.show();
+        this.bodyEl.un('click', this.beforeSelectFile, this);
         
-        this.placeThumbBox();
+        this.notifyEl.hide();
+        this.thumbEl.show();
+        this.footerEl.show();
         
-        if(this.imageSectionHasOnClickEvent){
-            this.imageSection.un('click', this.beforeSelectFile, this);
-            this.imageSectionHasOnClickEvent = false;
-        }
+        this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width;
+        this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height;
+        
+        this.setThumbBoxPosition();
+        this.baseRotateLevel();
+        this.baseScaleLevel();
         
-        this.image.OriginWidth = this.image.getWidth();
-        this.image.OriginHeight = this.image.getHeight();
+        this.draw();
         
-        this.fitThumbBox();
+        this.resize();
         
-        this.image.setWidth(Math.ceil(this.image.OriginWidth * this.getScaleLevel(false)));
-        this.image.setHeight(Math.ceil(this.image.OriginHeight * this.getScaleLevel(false)));
+        this.canvasLoaded = true;
         
-        this.setCanvasPosition();
     },
     
     setCanvasPosition : function()
     {   
-        var pw = Math.ceil((this.imageSection.getWidth() - this.image.getWidth()) / 2);
-        var ph = Math.ceil((this.imageSection.getHeight() - this.image.getHeight()) / 2);
+        if(!this.canvasEl){
+            return;
+        }
+        
+        var pw = Math.ceil((this.bodyEl.getWidth() - this.canvasEl.width) / 2);
+        var ph = Math.ceil((this.bodyEl.getHeight() - this.canvasEl.height) / 2);
+        
+        this.previewEl.setLeft(pw);
+        this.previewEl.setTop(ph);
         
-        this.imageCanvas.setLeft(pw);
-        this.imageCanvas.setTop(ph);
     },
     
     onMouseDown : function(e)
@@ -24229,23 +24319,19 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
     {   
         e.stopEvent();
         
-        if (!this.dragable){
+        if(!this.canvasLoaded){
             return;
         }
         
-        var minX = Math.ceil(this.thumb.getLeft(true));
-        var minY = Math.ceil(this.thumb.getTop(true));
+        if (!this.dragable){
+            return;
+        }
         
-        var maxX = Math.ceil(minX + this.thumb.getWidth() - this.image.getWidth());
-        var maxY = Math.ceil(minY + this.thumb.getHeight() - this.image.getHeight());
+        var minX = Math.ceil(this.thumbEl.getLeft(true));
+        var minY = Math.ceil(this.thumbEl.getTop(true));
         
-        if(this.rotate == 90 || this.rotate == 270){
-            minX = Math.ceil(this.thumb.getLeft(true) - (this.image.getWidth() - this.image.getHeight()) / 2);
-            minY = Math.ceil(this.thumb.getTop(true) + (this.image.getWidth() - this.image.getHeight()) / 2);
-            
-            maxX = Math.ceil(minX + this.thumb.getWidth() - this.image.getHeight());
-            maxY = Math.ceil(minY + this.thumb.getHeight() - this.image.getWidth());
-        }
+        var maxX = Math.ceil(minX + this.thumbEl.getWidth() - this.canvasEl.width);
+        var maxY = Math.ceil(minY + this.thumbEl.getHeight() - this.canvasEl.height);
         
         var x = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
         var y = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
@@ -24253,14 +24339,14 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
         x = x - this.mouseX;
         y = y - this.mouseY;
         
-        var bgX = Math.ceil(x + this.imageCanvas.getLeft(true));
-        var bgY = Math.ceil(y + this.imageCanvas.getTop(true));
+        var bgX = Math.ceil(x + this.previewEl.getLeft(true));
+        var bgY = Math.ceil(y + this.previewEl.getTop(true));
         
         bgX = (minX < bgX) ? minX : ((maxX > bgX) ? maxX : bgX);
         bgY = (minY < bgY) ? minY : ((maxY > bgY) ? maxY : bgY);
         
-        this.imageCanvas.setLeft(bgX);
-        this.imageCanvas.setTop(bgY);
+        this.previewEl.setLeft(bgX);
+        this.previewEl.setTop(bgY);
         
         this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX();
         this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY();
@@ -24277,258 +24363,289 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
     {   
         e.stopEvent();
         
-        this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1);
+        this.startScale = this.scale;
         
-        var width = Math.ceil(this.image.OriginWidth * this.getScaleLevel(false));
-        var height = Math.ceil(this.image.OriginHeight * this.getScaleLevel(false));
+        this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1);
         
-        if(
-                e.getWheelDelta() == -1 &&
-                (
-                    (
-                        (this.rotate == 0 || this.rotate == 180) && (width < this.thumb.getWidth() || height < this.thumb.getHeight())
-                    )
-                    ||
-                    (
-                        (this.rotate == 90 || this.rotate == 270) && (height < this.thumb.getWidth() || width < this.thumb.getHeight())
-                    )
-                )
-        ){
-            this.scale = (e.getWheelDelta() == 1) ? (this.scale - 1) : (this.scale + 1);
+        if(!this.zoomable()){
+            this.scale = this.startScale;
             return;
         }
         
-        this.image.setWidth(width);
-        this.image.setHeight(height);
-        
-        this.setCanvasPosition();
+        this.draw();
         
+        return;
     },
     
-    onRotateLeft : function(e)
+    zoomable : function()
     {
-        e.stopEvent();
+        var minScale = this.thumbEl.getWidth() / this.minWidth;
+        
+        var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel());
+        var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel());
         
         if(
+                (this.rotate == 0 || this.rotate == 180) && 
                 (
-                    (this.rotate == 0 || this.rotate == 180) 
-                    &&
-                    (this.image.getHeight() < this.thumb.getWidth() || this.image.getWidth() < this.thumb.getHeight())
-                )
-                ||
-                (
-                    (this.rotate == 90 || this.rotate == 270) 
-                    &&
-                    (this.image.getWidth() < this.thumb.getWidth() || this.image.getHeight() < this.thumb.getHeight())
+                    width / minScale < this.minWidth || 
+                    width / minScale > this.imageEl.OriginWidth || 
+                    height / minScale < this.minHeight || 
+                    height / minScale > this.imageEl.OriginHeight
                 )
-                
         ){
-            return;
+            return false;
         }
         
-        this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
-
-        this.imageCanvas.setStyle({
-            '-ms-transform' : 'rotate(' + this.rotate + 'deg)',
-            '-webkit-transform' : 'rotate(' + this.rotate + 'deg)',
-            'transform' : 'rotate(' + this.rotate + 'deg)'
-        });
-
-        this.setCanvasPosition();
-        
-    },
-    
-    onRotateRight : function(e)
-    {
-        e.stopEvent();
-        
         if(
+                (this.rotate == 90 || this.rotate == 270) && 
                 (
-                    (this.rotate == 0 || this.rotate == 180) 
-                    &&
-                    (this.image.getHeight() < this.thumb.getWidth() || this.image.getWidth() < this.thumb.getHeight())
-                )
-                ||
-                (
-                    (this.rotate == 90 || this.rotate == 270) 
-                    &&
-                    (this.image.getWidth() < this.thumb.getWidth() || this.image.getHeight() < this.thumb.getHeight())
+                    width / minScale < this.minHeight || 
+                    width / minScale > this.imageEl.OriginWidth || 
+                    height / minScale < this.minWidth || 
+                    height / minScale > this.imageEl.OriginHeight
                 )
-                
         ){
             return false;
         }
         
-        this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
-
-        this.imageCanvas.setStyle({
-            '-ms-transform' : 'rotate(' + this.rotate + 'deg)',
-            '-webkit-transform' : 'rotate(' + this.rotate + 'deg)',
-            'transform' : 'rotate(' + this.rotate + 'deg)'
-        });
-
-        this.setCanvasPosition();
-        
+        return true;
         
     },
     
-    crop : function()
-    {
-        var canvas = document.createElement("canvas");
-        
-        var context = canvas.getContext("2d");
-        
-        canvas.width = this.minWidth;
-        canvas.height = this.minHeight;
-        
-        var centerX = this.minWidth / 2;
-        var centerY = this.minHeight / 2;
-        
-        var cropWidth = this.thumb.getWidth() * this.getScaleLevel(true);
-        var cropHeight = this.thumb.getHeight() * this.getScaleLevel(true);
-        
-        var thumbX = Math.ceil(this.thumb.getLeft(true));
-        var thumbY = Math.ceil(this.thumb.getTop(true));
-        
-        var x = (thumbX - this.imageCanvas.getLeft(true)) * this.getScaleLevel(true);
-        var y = (thumbY - this.imageCanvas.getTop(true)) * this.getScaleLevel(true);
+    onRotateLeft : function(e)
+    {   
+        var minScale = this.thumbEl.getWidth() / this.minWidth;
         
-        if(this.rotate == 90){
+        if(this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight()){
             
-            x = thumbY + (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getTop(true);
-            y = this.image.getHeight() - this.thumb.getWidth() - (thumbX - (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getLeft(true));
+            var bw = this.canvasEl.width / this.getScaleLevel();
+            var bh = this.canvasEl.height / this.getScaleLevel();
             
-            x = x * this.getScaleLevel(true);
-            y = y * this.getScaleLevel(true);
+            this.startScale = this.scale;
             
-            if(this.image.OriginWidth - cropHeight < x){
-                x = this.image.OriginWidth - cropHeight;
-            }
+            while (this.getScaleLevel() < minScale){
+            
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        bw * this.getScaleLevel() < this.thumbEl.getHeight() ||
+                        bh * this.getScaleLevel() < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
 
-            if(this.image.OriginHeight - cropWidth < y){
-                y = this.image.OriginHeight - cropWidth;
+                this.draw();
+                
+                return;
             }
             
-            x = x < 0 ? 0 : x;
-            y = y < 0 ? 0 : y;
+            this.scale = this.startScale;
             
-            cropWidth = this.thumb.getHeight() * this.getScaleLevel(true);
-            cropHeight = this.thumb.getWidth() * this.getScaleLevel(true);
+            this.onRotateFail();
             
-            canvas.width = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
-            canvas.height = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
+            return false;
+        }
+        
+        this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90;
 
-            centerX = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
-            centerY = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
-            
-            context.translate(centerX, centerY);
-            context.rotate(this.rotate * Math.PI / 180);
-            
-            context.drawImage(this.image.dom, x, y, cropWidth, cropHeight, centerX * -1, centerY * -1, this.minHeight, this.minWidth);
+        this.draw();
         
-            var canvas2 = document.createElement("canvas");
-            var context2 = canvas2.getContext("2d");
-            
-            canvas2.width = this.minWidth;
-            canvas2.height = this.minHeight;
-            
-            context2.drawImage(canvas, Math.abs(this.minWidth - this.minHeight), 0, this.minWidth, this.minHeight, 0, 0, this.minWidth, this.minHeight);
+    },
     
-            this.cropImageData = canvas2.toDataURL(this.cropType);
-            
-            this.fireEvent('crop', this, this.cropImageData);
-            
-            return;
-        }
+    onRotateRight : function(e)
+    {
+        var minScale = this.thumbEl.getWidth() / this.minWidth;
         
-        if(this.rotate == 270){
-            
-            x = thumbY + (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getTop(true);
-            y = thumbX - (this.image.getWidth() - this.image.getHeight()) / 2 - this.imageCanvas.getLeft(true);
+        if(this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight()){
             
-            x = (this.image.getWidth() - this.thumb.getHeight() - x) * this.getScaleLevel(true);
-            y = y * this.getScaleLevel(true);
+            var bw = this.canvasEl.width / this.getScaleLevel();
+            var bh = this.canvasEl.height / this.getScaleLevel();
             
-            if(this.image.OriginWidth - cropHeight < x){
-                x = this.image.OriginWidth - cropHeight;
-            }
-
-            if(this.image.OriginHeight - cropWidth < y){
-                y = this.image.OriginHeight - cropWidth;
-            }
-
-            x = x < 0 ? 0 : x;
-            y = y < 0 ? 0 : y;
+            this.startScale = this.scale;
             
-            cropWidth = this.thumb.getHeight() * this.getScaleLevel(true);
-            cropHeight = this.thumb.getWidth() * this.getScaleLevel(true);
+            while (this.getScaleLevel() < minScale){
             
-            canvas.width = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
-            canvas.height = this.minWidth > this.minHeight ? this.minWidth : this.minHeight;
+                this.scale = this.scale + 1;
+                
+                if(!this.zoomable()){
+                    break;
+                }
+                
+                if(
+                        bw * this.getScaleLevel() < this.thumbEl.getHeight() ||
+                        bh * this.getScaleLevel() < this.thumbEl.getWidth()
+                ){
+                    continue;
+                }
+                
+                this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
 
-            centerX = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
-            centerY = this.minWidth > this.minHeight ? (this.minWidth / 2) : (this.minHeight / 2);
-            
-            context.translate(centerX, centerY);
-            context.rotate(this.rotate * Math.PI / 180);
-            
-            context.drawImage(this.image.dom, x, y, cropWidth, cropHeight, centerX * -1, centerY * -1, this.minHeight, this.minWidth);
-        
-            var canvas2 = document.createElement("canvas");
-            var context2 = canvas2.getContext("2d");
-            
-            canvas2.width = this.minWidth;
-            canvas2.height = this.minHeight;
+                this.draw();
+                
+                return;
+            }
             
-            context2.drawImage(canvas, 0, 0, this.minWidth, this.minHeight, 0, 0, this.minWidth, this.minHeight);
-    
-            this.cropImageData = canvas2.toDataURL(this.cropType);
+            this.scale = this.startScale;
             
-            this.fireEvent('crop', this, this.cropImageData);
+            this.onRotateFail();
             
-            return;
+            return false;
         }
         
-        if(this.rotate == 180){
-            x = this.image.OriginWidth - this.thumb.getWidth() * this.getScaleLevel(true) - x;
-            y = this.image.OriginHeight - this.thumb.getHeight() * this.getScaleLevel(true) - y;
+        this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90;
+
+        this.draw();
+    },
+    
+    onRotateFail : function()
+    {
+        this.errorEl.show(true);
+        
+        var _this = this;
+        
+        (function() { _this.errorEl.hide(true); }).defer(this.errorTimeout);
+    },
+    
+    draw : function()
+    {
+        this.previewEl.dom.innerHTML = '';
+        
+        var canvasEl = document.createElement("canvas");
+        
+        var contextEl = canvasEl.getContext("2d");
+        
+        canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+        canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        var center = this.imageEl.OriginWidth / 2;
+        
+        if(this.imageEl.OriginWidth < this.imageEl.OriginHeight){
+            canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+            canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+            center = this.imageEl.OriginHeight / 2;
+        }
+        
+        contextEl.scale(this.getScaleLevel(), this.getScaleLevel());
+        
+        contextEl.translate(center, center);
+        contextEl.rotate(this.rotate * Math.PI / 180);
+
+        contextEl.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight);
+        
+        this.canvasEl = document.createElement("canvas");
+        
+        this.contextEl = this.canvasEl.getContext("2d");
+        
+        switch (this.rotate) {
+            case 0 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 90 : 
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 180 :
+                
+                this.canvasEl.width = this.imageEl.OriginWidth * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginHeight * this.getScaleLevel();
+                
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, Math.abs(this.canvasEl.width - this.canvasEl.height), 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            case 270 :
+                
+                this.canvasEl.width = this.imageEl.OriginHeight * this.getScaleLevel();
+                this.canvasEl.height = this.imageEl.OriginWidth * this.getScaleLevel();
+        
+                if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                    this.contextEl.drawImage(canvasEl, 0, 0, this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                    break;
+                }
+                
+                this.contextEl.drawImage(canvasEl, 0, Math.abs(this.canvasEl.width - this.canvasEl.height), this.canvasEl.width, this.canvasEl.height, 0, 0, this.canvasEl.width, this.canvasEl.height);
+                
+                break;
+            default : 
+                break;
         }
         
-        if(this.image.OriginWidth - cropWidth < x){
-            x = this.image.OriginWidth - cropWidth;
+        this.previewEl.appendChild(this.canvasEl);
+        
+        this.setCanvasPosition();
+    },
+    
+    crop : function()
+    {
+        if(!this.canvasLoaded){
+            return;
+        }
+        var canvas = document.createElement("canvas");
+        
+        var context = canvas.getContext("2d");
+        
+        canvas.width = this.minWidth;
+        canvas.height = this.minHeight;
+        
+        var cropWidth = this.thumbEl.getWidth();
+        var cropHeight = this.thumbEl.getHeight();
+        
+        var x = this.thumbEl.getLeft(true) - this.previewEl.getLeft(true);
+        var y = this.thumbEl.getTop(true) - this.previewEl.getTop(true);
+        
+        if(this.canvasEl.width - cropWidth < x){
+            x = this.canvasEl.width - cropWidth;
         }
         
-        if(this.image.OriginHeight - cropHeight < y){
-            y = this.image.OriginHeight - cropHeight;
+        if(this.canvasEl.height - cropHeight < y){
+            y = this.canvasEl.height - cropHeight;
         }
         
         x = x < 0 ? 0 : x;
         y = y < 0 ? 0 : y;
         
-        context.translate(centerX, centerY);
-
-        context.rotate(this.rotate * Math.PI / 180);
+        context.drawImage(this.canvasEl, x, y, cropWidth, cropHeight, 0, 0, canvas.width, canvas.height);
         
-        context.drawImage(this.image.dom, x, y, cropWidth, cropHeight, centerX * -1, centerY * -1, canvas.width, canvas.height);
+        this.cropData = canvas.toDataURL(this.cropType);
         
-        this.cropImageData = canvas.toDataURL(this.cropType);
+        this.fireEvent('crop', this, this.cropData);
         
-        this.fireEvent('crop', this, this.cropImageData);
     },
     
-    calcThumbBoxSize : function()
+    setThumbBoxSize : function()
     {
-        var width, height;
-        
-        height = 300;
-        width = Math.ceil(this.minWidth * height / this.minHeight);
+        var height = 300;
+        var width = Math.ceil(this.minWidth * height / this.minHeight);
         
         if(this.minWidth > this.minHeight){
             width = 300;
             height = Math.ceil(this.minHeight * width / this.minWidth);
         }
         
-        this.thumb.setStyle({
+        this.thumbEl.setStyle({
             width : width + 'px',
             height : height + 'px'
         });
@@ -24537,45 +24654,94 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
             
     },
     
-    placeThumbBox : function()
+    setThumbBoxPosition : function()
+    {
+        var x = Math.ceil((this.bodyEl.getWidth() - this.thumbEl.getWidth()) / 2 );
+        var y = Math.ceil((this.bodyEl.getHeight() - this.thumbEl.getHeight()) / 2);
+        
+        this.thumbEl.setLeft(x);
+        this.thumbEl.setTop(y);
+        
+    },
+    
+    baseRotateLevel : function()
     {
-        var x = Math.ceil((this.imageSection.getWidth() - this.thumb.getWidth()) / 2 );
-        var y = Math.ceil((this.imageSection.getHeight() - this.thumb.getHeight()) / 2);
+        this.baseRotate = 1;
+        
+        if(
+                typeof(this.exif) != 'undefined' &&
+                typeof(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != 'undefined' &&
+                [1, 3, 6, 8].indexOf(this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']]) != -1
+        ){
+            this.baseRotate = this.exif[Roo.bootstrap.UploadCropbox['tags']['Orientation']];
+        }
         
-        this.thumb.setLeft(x);
-        this.thumb.setTop(y);
+        this.rotate = Roo.bootstrap.UploadCropbox['Orientation'][this.baseRotate];
         
     },
     
-    fitThumbBox : function()
+    baseScaleLevel : function()
     {
-        var width = this.thumb.getWidth();
-        var height = this.image.OriginHeight * width / this.image.OriginWidth;
+        var width, height;
+        
+        if(this.baseRotate == 6 || this.baseRotate == 8){
+            
+            width = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getWidth()){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+            }
+            
+            if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+                height = this.thumbEl.getWidth();
+                this.baseScale = height / this.imageEl.OriginHeight;
+                
+                if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getHeight()){
+                    width = this.thumbEl.getHeight();
+                    this.baseScale = width / this.imageEl.OriginWidth;
+                }
+            }
+            
+            return;
+        }
+        
+        width = this.thumbEl.getWidth();
+        this.baseScale = width / this.imageEl.OriginWidth;
+        
+        if(this.imageEl.OriginHeight * this.baseScale < this.thumbEl.getHeight()){
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+        }
         
-        this.baseScale = width / this.image.OriginWidth;
         
-        if(this.image.OriginWidth > this.image.OriginHeight){
-            height = this.thumb.getHeight();
-            width = this.image.OriginWidth * height / this.image.OriginHeight;
+        if(this.imageEl.OriginWidth > this.imageEl.OriginHeight){
+            
+            height = this.thumbEl.getHeight();
+            this.baseScale = height / this.imageEl.OriginHeight;
+            
+            if(this.imageEl.OriginWidth * this.baseScale < this.thumbEl.getWidth()){
+                width = this.thumbEl.getWidth();
+                this.baseScale = width / this.imageEl.OriginWidth;
+            }
             
-            this.baseScale = height / this.image.OriginHeight;
         }
         
         return;
     },
     
-    getScaleLevel : function(reverse)
+    getScaleLevel : function()
     {
-        if(reverse){
-            return Math.pow(1.1, this.scale * -1) / this.baseScale;
-        }
-        
         return this.baseScale * Math.pow(1.1, this.scale);
     },
     
     onTouchStart : function(e)
     {
-        e.stopEvent();
+        if(!this.canvasLoaded){
+            this.beforeSelectFile(e);
+            return;
+        }
         
         var touches = e.browserEvent.touches;
         
@@ -24601,7 +24767,7 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
         var x = Math.pow(coords[0] - coords[2], 2);
         var y = Math.pow(coords[1] - coords[3], 2);
         
-        this.startDistance =  Math.sqrt(x + y);
+        this.startDistance = Math.sqrt(x + y);
         
         this.startScale = this.scale;
         
@@ -24612,8 +24778,6 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
     
     onTouchMove : function(e)
     {
-        e.stopEvent();
-        
         if(!this.pinching && !this.dragable){
             return;
         }
@@ -24638,57 +24802,1046 @@ Roo.extend(Roo.bootstrap.UploadCropbox, Roo.bootstrap.Component,  {
         var x = Math.pow(coords[0] - coords[2], 2);
         var y = Math.pow(coords[1] - coords[3], 2);
         
-        this.endDistance =  Math.sqrt(x + y);
+        this.endDistance = Math.sqrt(x + y);
         
-        var scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1));
+        this.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1));
         
-        var width = Math.ceil(this.image.OriginWidth * this.baseScale * Math.pow(1.1, scale));
-        var height = Math.ceil(this.image.OriginHeight * this.baseScale * Math.pow(1.1, scale));
-        
-        if(
-                this.endDistance / this.startDistance < 1 &&
-                (
-                    (
-                        (this.rotate == 0 || this.rotate == 180) && (width < this.thumb.getWidth() || height < this.thumb.getHeight())
-                    )
-                    ||
-                    (
-                        (this.rotate == 90 || this.rotate == 270) && (height < this.thumb.getWidth() || width < this.thumb.getHeight())
-                    )
-                )
-        ){
+        if(!this.zoomable()){
+            this.scale = this.startScale;
             return;
         }
         
-        this.scale = scale;
-        
-        this.image.setWidth(width);
-        this.image.setHeight(height);
-        
-        this.setCanvasPosition();
-        
+        this.draw();
         
     },
     
     onTouchEnd : function(e)
     {
-        e.stopEvent();
-        
         this.pinching = false;
         this.dragable = false;
         
     },
     
     prepare : function(input)
-    {
-        if(!input.files || !input.files[0]){
+    {        
+        this.file = false;
+        this.exif = {};
+        
+        if(typeof(input) === 'string'){
+            this.loadCanvas(input);
+            return;
+        }
+        
+        if(!input.files || !input.files[0] || !this.urlAPI){
             return;
         }
         
         this.file = input.files[0];
+        this.cropType = this.file.type;
+        
+        var _this = this;
         
         if(this.fireEvent('prepare', this, this.file) != false){
-            Roo.log(this.file);
+            
+            var reader = new FileReader();
+            
+            reader.onload = function (e) {
+                if (e.target.error) {
+                    Roo.log(e.target.error);
+                    return;
+                }
+                
+                var buffer = e.target.result,
+                    dataView = new DataView(buffer),
+                    offset = 2,
+                    maxOffset = dataView.byteLength - 4,
+                    markerBytes,
+                    markerLength;
+                
+                if (dataView.getUint16(0) === 0xffd8) {
+                    while (offset < maxOffset) {
+                        markerBytes = dataView.getUint16(offset);
+                        
+                        if ((markerBytes >= 0xffe0 && markerBytes <= 0xffef) || markerBytes === 0xfffe) {
+                            markerLength = dataView.getUint16(offset + 2) + 2;
+                            if (offset + markerLength > dataView.byteLength) {
+                                Roo.log('Invalid meta data: Invalid segment size.');
+                                break;
+                            }
+                            
+                            if(markerBytes == 0xffe1){
+                                _this.parseExifData(
+                                    dataView,
+                                    offset,
+                                    markerLength
+                                );
+                            }
+                            
+                            offset += markerLength;
+                            
+                            continue;
+                        }
+                        
+                        break;
+                    }
+                    
+                }
+                
+                var url = _this.urlAPI.createObjectURL(_this.file);
+                
+                _this.loadCanvas(url);
+                
+                return;
+            }
+            
+            reader.readAsArrayBuffer(this.file);
+            
+        }
+        
+    },
+    
+    parseExifData : function(dataView, offset, length)
+    {
+        var tiffOffset = offset + 10,
+            littleEndian,
+            dirOffset;
+    
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
+        }
+        
+        // Check for the ASCII code for "Exif" (0x45786966):
+        if (dataView.getUint32(offset + 4) !== 0x45786966) {
+            // No Exif data, might be XMP data instead
+            return;
+        }
+        if (tiffOffset + 8 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid segment size.');
+            return;
+        }
+        // Check for the two null bytes:
+        if (dataView.getUint16(offset + 8) !== 0x0000) {
+            Roo.log('Invalid Exif data: Missing byte alignment offset.');
+            return;
+        }
+        // Check the byte alignment:
+        switch (dataView.getUint16(tiffOffset)) {
+        case 0x4949:
+            littleEndian = true;
+            break;
+        case 0x4D4D:
+            littleEndian = false;
+            break;
+        default:
+            Roo.log('Invalid Exif data: Invalid byte alignment marker.');
+            return;
+        }
+        // Check for the TIFF tag marker (0x002A):
+        if (dataView.getUint16(tiffOffset + 2, littleEndian) !== 0x002A) {
+            Roo.log('Invalid Exif data: Missing TIFF marker.');
+            return;
+        }
+        // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:
+        dirOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
+        
+        this.parseExifTags(
+            dataView,
+            tiffOffset,
+            tiffOffset + dirOffset,
+            littleEndian
+        );
+    },
+    
+    parseExifTags : function(dataView, tiffOffset, dirOffset, littleEndian)
+    {
+        var tagsNumber,
+            dirEndOffset,
+            i;
+        if (dirOffset + 6 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory offset.');
+            return;
+        }
+        tagsNumber = dataView.getUint16(dirOffset, littleEndian);
+        dirEndOffset = dirOffset + 2 + 12 * tagsNumber;
+        if (dirEndOffset + 4 > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid directory size.');
+            return;
+        }
+        for (i = 0; i < tagsNumber; i += 1) {
+            this.parseExifTag(
+                dataView,
+                tiffOffset,
+                dirOffset + 2 + 12 * i, // tag offset
+                littleEndian
+            );
+        }
+        // Return the offset to the next directory:
+        return dataView.getUint32(dirEndOffset, littleEndian);
+    },
+    
+    parseExifTag : function (dataView, tiffOffset, offset, littleEndian) 
+    {
+        var tag = dataView.getUint16(offset, littleEndian);
+        
+        this.exif[tag] = this.getExifValue(
+            dataView,
+            tiffOffset,
+            offset,
+            dataView.getUint16(offset + 2, littleEndian), // tag type
+            dataView.getUint32(offset + 4, littleEndian), // tag length
+            littleEndian
+        );
+    },
+    
+    getExifValue : function (dataView, tiffOffset, offset, type, length, littleEndian)
+    {
+        var tagType = Roo.bootstrap.UploadCropbox.exifTagTypes[type],
+            tagSize,
+            dataOffset,
+            values,
+            i,
+            str,
+            c;
+    
+        if (!tagType) {
+            Roo.log('Invalid Exif data: Invalid tag type.');
+            return;
+        }
+        
+        tagSize = tagType.size * length;
+        // Determine if the value is contained in the dataOffset bytes,
+        // or if the value at the dataOffset is a pointer to the actual data:
+        dataOffset = tagSize > 4 ?
+                tiffOffset + dataView.getUint32(offset + 8, littleEndian) : (offset + 8);
+        if (dataOffset + tagSize > dataView.byteLength) {
+            Roo.log('Invalid Exif data: Invalid data offset.');
+            return;
+        }
+        if (length === 1) {
+            return tagType.getValue(dataView, dataOffset, littleEndian);
+        }
+        values = [];
+        for (i = 0; i < length; i += 1) {
+            values[i] = tagType.getValue(dataView, dataOffset + i * tagType.size, littleEndian);
+        }
+        
+        if (tagType.ascii) {
+            str = '';
+            // Concatenate the chars:
+            for (i = 0; i < values.length; i += 1) {
+                c = values[i];
+                // Ignore the terminating NULL byte(s):
+                if (c === '\u0000') {
+                    break;
+                }
+                str += c;
+            }
+            return str;
         }
+        return values;
     }
+    
+});
+
+Roo.apply(Roo.bootstrap.UploadCropbox, {
+    tags : {
+        'Orientation': 0x0112
+    },
+    
+    Orientation: {
+            1: 0, //'top-left',
+//            2: 'top-right',
+            3: 180, //'bottom-right',
+//            4: 'bottom-left',
+//            5: 'left-top',
+            6: 90, //'right-top',
+//            7: 'right-bottom',
+            8: 270 //'left-bottom'
+    },
+    
+    exifTagTypes : {
+        // byte, 8-bit unsigned int:
+        1: {
+            getValue: function (dataView, dataOffset) {
+                return dataView.getUint8(dataOffset);
+            },
+            size: 1
+        },
+        // ascii, 8-bit byte:
+        2: {
+            getValue: function (dataView, dataOffset) {
+                return String.fromCharCode(dataView.getUint8(dataOffset));
+            },
+            size: 1,
+            ascii: true
+        },
+        // short, 16 bit int:
+        3: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint16(dataOffset, littleEndian);
+            },
+            size: 2
+        },
+        // long, 32 bit int:
+        4: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // rational = two long values, first is numerator, second is denominator:
+        5: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getUint32(dataOffset, littleEndian) /
+                    dataView.getUint32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        },
+        // slong, 32 bit signed int:
+        9: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian);
+            },
+            size: 4
+        },
+        // srational, two slongs, first is numerator, second is denominator:
+        10: {
+            getValue: function (dataView, dataOffset, littleEndian) {
+                return dataView.getInt32(dataOffset, littleEndian) /
+                    dataView.getInt32(dataOffset + 4, littleEndian);
+            },
+            size: 8
+        }
+    },
+    
+    footer : {
+        STANDARD : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-picture',
+                action : 'picture',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-picture-o"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ],
+        DOCUMENT : [
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-left',
+                action : 'rotate-left',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-undo"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-download',
+                action : 'download',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-download"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-crop',
+                action : 'crop',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-crop"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-trash',
+                action : 'trash',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-trash"></i>'
+                    }
+                ]
+            },
+            {
+                tag : 'div',
+                cls : 'btn-group roo-upload-cropbox-rotate-right',
+                action : 'rotate-right',
+                cn : [
+                    {
+                        tag : 'button',
+                        cls : 'btn btn-default',
+                        html : '<i class="fa fa-repeat"></i>'
+                    }
+                ]
+            }
+        ]
+    }
+});
+
+/*
+* Licence: LGPL
+*/
+
+/**
+ * @class Roo.bootstrap.DocumentManager
+ * @extends Roo.bootstrap.Component
+ * Bootstrap DocumentManager class
+ * @cfg {String} paramName default 'imageUpload'
+ * @cfg {String} method default POST
+ * @cfg {String} url action url
+ * @cfg {Number} boxes number of boxes default 12
+ * @cfg {Boolean} multiple multiple upload default true
+ * @cfg {Number} minWidth default 300
+ * @cfg {Number} minHeight default 300
+ * @cfg {Number} thumbSize default 300
+ * @cfg {String} fieldLabel
+ * @cfg {Number} labelWidth default 4
+ * @cfg {String} labelAlign (left|top) default left
+ * 
+ * @constructor
+ * Create a new DocumentManager
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.DocumentManager = function(config){
+    Roo.bootstrap.DocumentManager.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        /**
+         * @event initial
+         * Fire when initial the DocumentManager
+         * @param {Roo.bootstrap.DocumentManager} this
+         */
+        "initial" : true,
+        /**
+         * @event inspect
+         * inspect selected file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {File} file
+         */
+        "inspect" : true,
+        /**
+         * @event exception
+         * Fire when xhr load exception
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {XMLHttpRequest} xhr
+         */
+        "exception" : true,
+        /**
+         * @event prepare
+         * prepare the form data
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} formData
+         */
+        "prepare" : true,
+        /**
+         * @event remove
+         * Fire when remove the file
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
+         */
+        "remove" : true,
+        /**
+         * @event refresh
+         * Fire after refresh the file
+         * @param {Roo.bootstrap.DocumentManager} this
+         */
+        "refresh" : true,
+        /**
+         * @event click
+         * Fire after click the image
+         * @param {Roo.bootstrap.DocumentManager} this
+         * @param {Object} file
+         */
+        "click" : true
+        
+    });
+};
+
+Roo.extend(Roo.bootstrap.DocumentManager, Roo.bootstrap.Component,  {
+    
+    boxes : 12,
+    inputName : '',
+    minWidth : 300,
+    minHeight : 300,
+    thumbSize : 300,
+    multiple : true,
+    files : [],
+    method : 'POST',
+    url : '',
+    paramName : 'imageUpload',
+    fieldLabel : '',
+    labelWidth : 4,
+    labelAlign : 'left',
+    
+    getAutoCreate : function()
+    {   
+        var managerWidget = {
+            tag : 'div',
+            cls : 'roo-document-manager',
+            cn : [
+                {
+                    tag : 'input',
+                    cls : 'roo-document-manager-selector',
+                    type : 'file'
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-document-manager-uploader',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-document-manager-upload-btn',
+                            html : '<i class="fa fa-plus"></i>'
+                        }
+                    ]
+                    
+                }
+            ]
+        };
+        
+        var content = [
+            {
+                tag : 'div',
+                cls : 'column col-md-12',
+                cn : managerWidget
+            }
+        ];
+        
+        if(this.fieldLabel.length){
+            
+            content = [
+                {
+                    tag : 'div',
+                    cls : 'column col-md-12',
+                    html : this.fieldLabel
+                },
+                {
+                    tag : 'div',
+                    cls : 'column col-md-12',
+                    cn : managerWidget
+                }
+            ];
+
+            if(this.labelAlign == 'left'){
+                content = [
+                    {
+                        tag : 'div',
+                        cls : 'column col-md-' + this.labelWidth,
+                        html : this.fieldLabel
+                    },
+                    {
+                        tag : 'div',
+                        cls : 'column col-md-' + (12 - this.labelWidth),
+                        cn : managerWidget
+                    }
+                ];
+                
+            }
+        }
+        
+        var cfg = {
+            tag : 'div',
+            cls : 'row clearfix',
+            cn : content
+        };
+        
+        return cfg;
+        
+    },
+    
+    initEvents : function()
+    {
+        this.managerEl = this.el.select('.roo-document-manager', true).first();
+        this.managerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.selectorEl = this.el.select('.roo-document-manager-selector', true).first();
+        this.selectorEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        this.selectorEl.hide();
+        
+        if(this.multiple){
+            this.selectorEl.attr('multiple', 'multiple');
+        }
+        
+        this.selectorEl.on('change', this.onSelect, this);
+        
+        this.uploader = this.el.select('.roo-document-manager-uploader', true).first();
+        this.uploader.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.uploader.on('click', this.onUpload, this);
+        
+        var _this = this;
+        
+        window.addEventListener("resize", function() { _this.refresh(); } );
+        
+        this.fireEvent('initial', this);
+    },
+    
+    onUpload : function(e)
+    {
+        e.preventDefault();
+        
+        this.selectorEl.dom.click();
+        
+    },
+    
+    onSelect : function(e)
+    {
+        e.preventDefault();
+        
+        if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){
+            return;
+        }
+        
+        Roo.each(this.selectorEl.dom.files, function(file){
+            if(this.fireEvent('inspect', this, file) != false){
+                this.files.push(file);
+            }
+        }, this);
+        
+        this.process();
+        
+    },
+    
+    process : function()
+    {
+        this.selectorEl.dom.value = '';
+        
+        if(!this.files.length){
+            return;
+        }
+        
+        if(this.files.length > this.boxes){
+            this.files = this.files.slice(0, this.boxes);
+        }
+        
+        var xhr = new XMLHttpRequest();
+        
+        Roo.each(this.files, function(file, index){
+            if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+                return;
+            }
+            
+            file.xhr = xhr;
+            
+            this.managerEl.createChild({
+                tag : 'div',
+                cls : 'roo-document-manager-loading',
+                cn : [
+                    {
+                        tag : 'div',
+                        tooltip : file.name,
+                        cls : 'roo-document-manager-thumb',
+                        html : '<i class="fa fa-spinner fa-pulse"></i>'
+                    }
+                ]
+
+            });
+            
+        }, this);
+        
+        if(this.files.length > this.boxes - 1 ){
+            this.uploader.hide();
+        }
+        
+        var headers = {
+            "Accept": "application/json",
+            "Cache-Control": "no-cache",
+            "X-Requested-With": "XMLHttpRequest"
+        };
+        
+        xhr.open(this.method, this.url, true);
+        
+        for (var headerName in headers) {
+            var headerValue = headers[headerName];
+            if (headerValue) {
+                xhr.setRequestHeader(headerName, headerValue);
+            }
+        }
+        
+        var _this = this;
+        
+        xhr.onload = function()
+        {
+            _this.xhrOnLoad(xhr);
+        }
+        
+        xhr.onerror = function()
+        {
+            _this.xhrOnError(xhr);
+        }
+        
+        var formData = new FormData();
+
+        formData.append('returnHTML', 'NO');
+        
+        Roo.each(this.files, function(file, index){
+            
+            if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+                return;
+            }
+            
+            formData.append(this.getParamName(index), file, file.name);
+            
+        }, this);
+        
+        if(this.fireEvent('prepare', this, formData) != false){
+            xhr.send(formData);
+        };
+        
+    },
+    
+    getParamName : function(i)
+    {
+        if(!this.multiple){
+            return this.paramName;
+        }
+        
+        return this.paramName + "_" + i;
+    },
+    
+    refresh : function()
+    {
+        Roo.each(this.managerEl.select('.roo-document-manager-loading', true).elements, function(el){
+            el.remove();
+        }, this);
+        
+        
+        var files = [];
+        
+        Roo.each(this.files, function(file){
+            
+            if(typeof(file.id) == 'undefined' || file.id * 1 < 1){
+                return;
+            }
+            
+            if(file.target){
+                files.push(file);
+                return;
+            }
+            
+            var previewEl = this.managerEl.createChild({
+                tag : 'div',
+                cls : 'roo-document-manager-preview',
+                cn : [
+                    {
+                        tag : 'div',
+                        tooltip : file.filename,
+                        cls : 'roo-document-manager-thumb',
+                        html : '<img src="' + baseURL +'/Images/Thumb/' + this.thumbSize + '/' + file.id + '/' + file.filename + '">'
+                    },
+                    {
+                        tag : 'button',
+                        cls : 'close',
+                        html : 'x'
+                    }
+                ]
+            });
+            
+            var close = previewEl.select('button.close', true).first();
+            
+            close.on('click', this.onRemove, this, file);
+            
+            file.target = previewEl;
+            
+            var image = previewEl.select('img', true).first();
+            
+            image.on('click', this.onClick, this, file);
+            
+            files.push(file);
+            
+            return;
+            
+        }, this);
+        
+        this.files = files;
+        
+        this.uploader.show();
+        
+        if(this.files.length > this.boxes - 1){
+            this.uploader.hide();
+        }
+        
+        Roo.isTouch ? this.closable(false) : this.closable(true);
+        
+        this.fireEvent('refresh', this);
+    },
+    
+    onRemove : function(e, el, o)
+    {
+        e.preventDefault();
+        
+        this.fireEvent('remove', this, o);
+        
+    },
+    
+    remove : function(o)
+    {
+        var files = [];
+        
+        Roo.each(this.files, function(file){
+            if(typeof(file.id) == 'undefined' || file.id * 1 < 1 || file.id != o.id){
+                files.push(file);
+                return;
+            }
+
+            o.target.remove();
+
+        }, this);
+        
+        this.files = files;
+        
+        this.refresh();
+    },
+    
+    onClick : function(e, el, o)
+    {
+        e.preventDefault();
+        
+        this.fireEvent('click', this, o);
+        
+    },
+    
+    closable : function(closable)
+    {
+        Roo.each(this.managerEl.select('.roo-document-manager-preview > button.close', true).elements, function(el){
+            
+            el.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+            
+            if(closable){
+                el.show();
+                return;
+            }
+            
+            el.hide();
+            
+        }, this);
+    },
+    
+    xhrOnLoad : function(xhr)
+    {
+        if (xhr.readyState !== 4) {
+            this.refresh();
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
+
+        var response = Roo.decode(xhr.responseText);
+        
+        if(!response.success){
+            this.refresh();
+            this.fireEvent('exception', this, xhr);
+            return;
+        }
+        
+        var i = 0;
+        
+        Roo.each(this.files, function(file, index){
+            
+            if(typeof(file.id) != 'undefined' && file.id * 1 > 0){
+                return;
+            }
+            
+            this.files[index] = response.data[i];
+            i++;
+            
+            return;
+            
+        }, this);
+        
+        this.refresh();
+        
+    },
+    
+    xhrOnError : function()
+    {
+        Roo.log('xhr on error');
+        
+        var response = Roo.decode(xhr.responseText);
+          
+        Roo.log(response);
+    }
+    
+    
+    
+});
+/*
+* Licence: LGPL
+*/
+
+/**
+ * @class Roo.bootstrap.DocumentViewer
+ * @extends Roo.bootstrap.Component
+ * Bootstrap DocumentViewer class
+ * 
+ * @constructor
+ * Create a new DocumentViewer
+ * @param {Object} config The config object
+ */
+
+Roo.bootstrap.DocumentViewer = function(config){
+    Roo.bootstrap.DocumentViewer.superclass.constructor.call(this, config);
+    
+    this.addEvents({
+        /**
+         * @event initial
+         * Fire after initEvent
+         * @param {Roo.bootstrap.DocumentViewer} this
+         */
+        "initial" : true,
+        /**
+         * @event click
+         * Fire after click
+         * @param {Roo.bootstrap.DocumentViewer} this
+         */
+        "click" : true,
+        /**
+         * @event trash
+         * Fire after trash button
+         * @param {Roo.bootstrap.DocumentViewer} this
+         */
+        "trash" : true
+        
+    });
+};
+
+Roo.extend(Roo.bootstrap.DocumentViewer, Roo.bootstrap.Component,  {
+    
+    getAutoCreate : function()
+    {
+        var cfg = {
+            tag : 'div',
+            cls : 'roo-document-viewer',
+            cn : [
+                {
+                    tag : 'div',
+                    cls : 'roo-document-viewer-body',
+                    cn : [
+                        {
+                            tag : 'div',
+                            cls : 'roo-document-viewer-thumb',
+                            cn : [
+                                {
+                                    tag : 'img',
+                                    cls : 'roo-document-viewer-image'
+                                }
+                            ]
+                        }
+                    ]
+                },
+                {
+                    tag : 'div',
+                    cls : 'roo-document-viewer-footer',
+                    cn : {
+                        tag : 'div',
+                        cls : 'btn-group btn-group-justified roo-document-viewer-btn-group',
+                        cn : [
+                            {
+                                tag : 'div',
+                                cls : 'btn-group',
+                                cn : [
+                                    {
+                                        tag : 'button',
+                                        cls : 'btn btn-default roo-document-viewer-trash',
+                                        html : '<i class="fa fa-trash"></i>'
+                                    }
+                                ]
+                            }
+                        ]
+                    }
+                }
+            ]
+        };
+        
+        return cfg;
+    },
+    
+    initEvents : function()
+    {
+        
+        this.bodyEl = this.el.select('.roo-document-viewer-body', true).first();
+        this.bodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.thumbEl = this.el.select('.roo-document-viewer-thumb', true).first();
+        this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.imageEl = this.el.select('.roo-document-viewer-image', true).first();
+        this.imageEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.footerEl = this.el.select('.roo-document-viewer-footer', true).first();
+        this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.trashBtn = this.el.select('.roo-document-viewer-trash', true).first();
+        this.trashBtn.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+        
+        this.bodyEl.on('click', this.onClick, this);
+        
+        this.trashBtn.on('click', this.onTrash, this);
+        
+    },
+    
+    initial : function()
+    {
+//        this.thumbEl.setStyle('line-height', this.thumbEl.getHeight(true) + 'px');
+        
+        
+        this.fireEvent('initial', this);
+        
+    },
+    
+    onClick : function(e)
+    {
+        e.preventDefault();
+        
+        this.fireEvent('click', this);
+    },
+    
+    onTrash : function(e)
+    {
+        e.preventDefault();
+        
+        this.fireEvent('trash', this);
+    }
+    
 });