From bd5dfe63c89d60a55237c6b717256c8e131e6eaa Mon Sep 17 00:00:00 2001 From: leon Date: Mon, 27 Jun 2022 10:50:54 +0800 Subject: [PATCH] image editing dialog --- -core.js roojs-ui.js > roojs-all.js | 6983 +++++++++++++++++++++++++ Roo/Component.js | 1 - Roo/dialog/UploadCropbox.js | 39 +- Roo/dialog/namespace.js | 1 + Roo/util/Observable.js | 1 - buildSDK/dependancy_ui.txt | 3 + examples/dialog/test-2.js | 34 +- examples/dialog/test.html | 2 +- roojs-all.js | 28 +- roojs-debug.js | 39 +- roojs-ui-debug.js | 39 +- roojs-ui.js | 28 +- 12 files changed, 7117 insertions(+), 81 deletions(-) create mode 100644 -core.js roojs-ui.js > roojs-all.js create mode 100644 Roo/dialog/namespace.js diff --git a/-core.js roojs-ui.js > roojs-all.js b/-core.js roojs-ui.js > roojs-all.js new file mode 100644 index 0000000000..e07924d2fc --- /dev/null +++ b/-core.js roojs-ui.js > roojs-all.js @@ -0,0 +1,6983 @@ +diff --git a/Roo/ContentPanel.js b/Roo/ContentPanel.js +index 0984532b54..cc1b9d0ce5 100644 +--- a/Roo/ContentPanel.js ++++ b/Roo/ContentPanel.js +@@ -41,7 +41,6 @@ + */ + Roo.ContentPanel = function(el, config, content){ +  +-  + /* + if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory + config = el; +@@ -425,6 +424,14 @@ layout.addxtype({ + */ +  + addxtype : function(cfg) { ++ if(cfg.xtype.match(/^UploadCropbox$/)) { ++ ++ this.cropbox = new Roo.factory(cfg); ++ ++ this.cropbox.render(this.el); ++ ++ return this.cropbox; ++ } + // add form.. + if (cfg.xtype.match(/^Form$/)) { +  +diff --git a/Roo/dialog/UploadCropbox.js b/Roo/dialog/UploadCropbox.js +new file mode 100644 +index 0000000000..8cf986b2e5 +--- /dev/null ++++ b/Roo/dialog/UploadCropbox.js +@@ -0,0 +1,1791 @@ ++ ++/* ++* Licence: LGPL ++*/ ++ ++/** ++ * @class Roo.dialog.UploadCropbox ++ * @extends Roo.BoxComponent ++ * Dialog 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'] ++ * @cfg {Boolean} isDocument (true|false) default false ++ * @cfg {String} url action url ++ * @cfg {String} paramName default 'imageUpload' ++ * @cfg {String} method default POST ++ * @cfg {Boolean} loadMask (true|false) default true ++ * @cfg {Boolean} loadingText default 'Loading...' ++ *  ++ * @constructor ++ * Create a new UploadCropbox ++ * @param {Object} config The config object ++ */ ++ ++ Roo.dialog.UploadCropbox = function(config){ ++ Roo.dialog.UploadCropbox.superclass.constructor.call(this, config); ++  ++ this.addEvents({ ++ /** ++ * @event beforeselectfile ++ * Fire before select file ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "beforeselectfile" : true, ++ /** ++ * @event initial ++ * Fire after initEvent ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "initial" : true, ++ /** ++ * @event crop ++ * Fire after initEvent ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} data ++ */ ++ "crop" : true, ++ /** ++ * @event prepare ++ * Fire when preparing the file data ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} file ++ */ ++ "prepare" : true, ++ /** ++ * @event exception ++ * Fire when get exception ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {XMLHttpRequest} xhr ++ */ ++ "exception" : true, ++ /** ++ * @event beforeloadcanvas ++ * Fire before load the canvas ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} src ++ */ ++ "beforeloadcanvas" : true, ++ /** ++ * @event trash ++ * Fire when trash image ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "trash" : true, ++ /** ++ * @event download ++ * Fire when download the image ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "download" : true, ++ /** ++ * @event footerbuttonclick ++ * Fire when footerbuttonclick ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} type ++ */ ++ "footerbuttonclick" : true, ++ /** ++ * @event resize ++ * Fire when resize ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "resize" : true, ++ /** ++ * @event rotate ++ * Fire when rotate the image ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} pos ++ */ ++ "rotate" : true, ++ /** ++ * @event inspect ++ * Fire when inspect the file ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} file ++ */ ++ "inspect" : true, ++ /** ++ * @event upload ++ * Fire when xhr upload the file ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} data ++ */ ++ "upload" : true, ++ /** ++ * @event arrange ++ * Fire when arrange the file data ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} formData ++ */ ++ "arrange" : true, ++ /** ++ * @event loadcanvas ++ * Fire after load the canvas ++ * @param {Roo.dialog.UploadCropbox} ++ * @param {Object} imgEl ++ */ ++ "loadcanvas" : true ++ }); ++  ++ this.buttons = this.buttons || Roo.dialog.UploadCropbox.footer.STANDARD; ++}; ++ ++Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { ++  ++ emptyText : 'Click to upload image', ++ rotateNotify : 'Image is too small to rotate', ++ errorTimeout : 3000, ++ scale : 0, ++ baseScale : 1, ++ rotate : 0, ++ dragable : false, ++ pinching : false, ++ mouseX : 0, ++ mouseY : 0, ++ cropData : false, ++ minWidth : 300, ++ minHeight : 300, ++ file : false, ++ exif : {}, ++ baseRotate : 1, ++ cropType : 'image/jpeg', ++ buttons : false, ++ canvasLoaded : false, ++ isDocument : false, ++ method : 'POST', ++ paramName : 'imageUpload', ++ loadMask : true, ++ loadingText : 'Loading...', ++ maskEl : false, ++  ++ getAutoCreate : function() ++ { ++ var cfg = { ++ tag : 'div', ++ cls : 'roo-upload-cropbox', ++ cn : [ ++ { ++ tag : 'input', ++ cls : 'roo-upload-cropbox-selector', ++ type : 'file' ++ }, ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-body', ++ style : 'cursor:pointer', ++ cn : [ ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-preview' ++ }, ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-thumb' ++ }, ++ { ++ 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', ++ cn : { ++ tag : 'div', ++ cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group', ++ cn : [] ++ } ++ } ++ ] ++ }; ++  ++ return cfg; ++ }, ++  ++ onRender : function(ct, position) ++ { ++ console.log("On Render"); ++ console.log(this); ++ Roo.dialog.UploadCropbox.superclass.onRender.call(this, ct, position); ++ ++ if(this.el){ ++ if (this.el.attr('xtype')) { ++ this.el.attr('xtypex', this.el.attr('xtype')); ++ this.el.dom.removeAttribute('xtype'); ++  ++ this.initEvents(); ++ } ++ } ++ else { ++ var cfg = Roo.apply({}, this.getAutoCreate()); ++  ++ cfg.id = this.id || Roo.id(); ++  ++ if (this.cls) { ++ cfg.cls = (typeof(cfg.cls) == 'undefined' ? this.cls : cfg.cls) + ' ' + this.cls; ++ } ++  ++ if (this.style) { // fixme needs to support more complex style data. ++ cfg.style = (typeof(cfg.style) == 'undefined' ? this.style : cfg.style) + '; ' + this.style; ++ } ++  ++ this.el = ct.createChild(cfg, position); ++  ++ this.initEvents(); ++ } ++  ++ 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); ++ } ++  ++ if(this.loadMask){ ++ this.maskEl = this.el; ++ } ++ }, ++  ++ 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.selectorEl = this.el.select('.roo-upload-cropbox-selector', true).first(); ++ this.selectorEl.hide(); ++  ++ this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first(); ++ this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++  ++ this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first(); ++ this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++ this.thumbEl.hide(); ++  ++ this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first(); ++ this.notifyEl.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.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first(); ++ this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++ this.footerEl.hide(); ++  ++ this.setThumbBoxSize(); ++  ++ this.bind(); ++  ++ this.resize(); ++  ++ this.fireEvent('initial', this); ++ }, ++ ++ bind : function() ++ { ++ var _this = this; ++  ++ window.addEventListener("resize", function() { _this.resize(); } ); ++  ++ this.bodyEl.on('click', this.beforeSelectFile, this); ++  ++ if(Roo.isTouch){ ++ 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.bodyEl.on('mousedown', this.onMouseDown, this); ++ this.bodyEl.on('mousemove', this.onMouseMove, this); ++ var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel'; ++ this.bodyEl.on(mousewheel, this.onMouseWheel, this); ++ Roo.get(document).on('mouseup', this.onMouseUp, this); ++ } ++  ++ this.selectorEl.on('change', this.onFileSelected, this); ++ }, ++  ++ reset : function() ++ {  ++ 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.cropData = false; ++ this.notifyEl.dom.innerHTML = this.emptyText; ++  ++ // this.selectorEl.dom.value = ''; ++  ++ }, ++  ++ 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(); ++  ++ if(this.fireEvent('beforeselectfile', this) != false){ ++ this.selectorEl.dom.click(); ++ } ++ }, ++  ++ onFileSelected : function(e) ++ { ++ e.preventDefault(); ++  ++ if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){ ++ return; ++ } ++  ++ var file = this.selectorEl.dom.files[0]; ++  ++ if(this.fireEvent('inspect', this, file) != false){ ++ this.prepare(file); ++ } ++  ++ }, ++  ++ trash : function(e) ++ { ++ this.fireEvent('trash', this); ++ }, ++  ++ download : function(e) ++ { ++ this.fireEvent('download', this); ++ }, ++  ++ loadCanvas : function(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; ++ } ++ }, ++  ++ onLoadCanvas : function() ++ {  ++ this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width; ++ this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height; ++ ++ if(this.fireEvent('loadcanvas', this, this.imageEl) != false){ ++  ++ this.bodyEl.un('click', this.beforeSelectFile, this); ++  ++ this.notifyEl.hide(); ++ this.thumbEl.show(); ++ this.footerEl.show(); ++  ++ this.baseRotateLevel(); ++  ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ } ++  ++ this.setThumbBoxPosition(); ++  ++ this.baseScaleLevel(); ++  ++ this.draw(); ++  ++ this.resize(); ++  ++ this.canvasLoaded = true; ++  ++ } ++  ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ }, ++  ++ setCanvasPosition : function() ++ {  ++ 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); ++  ++ }, ++  ++ onMouseDown : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.dragable = true; ++ this.pinching = false; ++  ++ if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){ ++ this.dragable = false; ++ return; ++ } ++  ++ this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX(); ++ this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY(); ++  ++ }, ++  ++ onMouseMove : function(e) ++ {  ++ e.stopEvent(); ++  ++ if(!this.canvasLoaded){ ++ return; ++ } ++  ++ if (!this.dragable){ ++ return; ++ } ++  ++ var minX = Math.ceil(this.thumbEl.getLeft(true)); ++ var minY = Math.ceil(this.thumbEl.getTop(true)); ++  ++ 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(); ++  ++ x = x - this.mouseX; ++ y = y - this.mouseY; ++  ++ 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.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(); ++ }, ++  ++ onMouseUp : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.dragable = false; ++ }, ++  ++ onMouseWheel : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.startScale = this.scale; ++  ++ this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1); ++  ++ if(!this.zoomable()){ ++ this.scale = this.startScale; ++ return; ++ } ++  ++ this.draw(); ++  ++ return; ++ }, ++  ++ zoomable : function() ++ { ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ if(this.minWidth < this.minHeight){ ++ minScale = this.thumbEl.getHeight() / this.minHeight; ++ } ++  ++ var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale); ++ var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale); ++  ++ if( ++ this.isDocument && ++ (this.rotate == 0 || this.rotate == 180) &&  ++ ( ++ width > this.imageEl.OriginWidth ||  ++ height > this.imageEl.OriginHeight || ++ (width < this.minWidth && height < this.minHeight) ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ this.isDocument && ++ (this.rotate == 90 || this.rotate == 270) &&  ++ ( ++ width > this.imageEl.OriginWidth ||  ++ height > this.imageEl.OriginHeight || ++ (width < this.minHeight && height < this.minWidth) ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ !this.isDocument && ++ (this.rotate == 0 || this.rotate == 180) &&  ++ ( ++ width < this.minWidth ||  ++ width > this.imageEl.OriginWidth ||  ++ height < this.minHeight ||  ++ height > this.imageEl.OriginHeight ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ !this.isDocument && ++ (this.rotate == 90 || this.rotate == 270) &&  ++ ( ++ width < this.minHeight ||  ++ width > this.imageEl.OriginWidth ||  ++ height < this.minWidth ||  ++ height > this.imageEl.OriginHeight ++ ) ++ ){ ++ return false; ++ } ++  ++ return true; ++  ++ }, ++  ++ onRotateLeft : function(e) ++ {  ++ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){ ++  ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel()); ++ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel()); ++  ++ this.startScale = this.scale; ++  ++ while (this.getScaleLevel() < minScale){ ++  ++ this.scale = this.scale + 1; ++  ++ if(!this.zoomable()){ ++ break; ++ } ++  ++ if( ++ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() || ++ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth() ++ ){ ++ continue; ++ } ++  ++ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90; ++ ++ this.draw(); ++  ++ return; ++ } ++  ++ this.scale = this.startScale; ++  ++ this.onRotateFail(); ++  ++ return false; ++ } ++  ++ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90; ++ ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ this.setThumbBoxPosition(); ++ this.setCanvasPosition(); ++ } ++  ++ this.draw(); ++  ++ this.fireEvent('rotate', this, 'left'); ++  ++ }, ++  ++ onRotateRight : function(e) ++ { ++ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){ ++  ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel()); ++ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel()); ++  ++ this.startScale = this.scale; ++  ++ while (this.getScaleLevel() < minScale){ ++  ++ this.scale = this.scale + 1; ++  ++ if(!this.zoomable()){ ++ break; ++ } ++  ++ if( ++ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() || ++ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth() ++ ){ ++ continue; ++ } ++  ++ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90; ++ ++ this.draw(); ++  ++ return; ++ } ++  ++ this.scale = this.startScale; ++  ++ this.onRotateFail(); ++  ++ return false; ++ } ++  ++ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90; ++ ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ this.setThumbBoxPosition(); ++ this.setCanvasPosition(); ++ } ++  ++ this.draw(); ++  ++ this.fireEvent('rotate', this, 'right'); ++ }, ++  ++ 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; ++ } ++  ++ this.previewEl.appendChild(this.canvasEl); ++  ++ this.setCanvasPosition(); ++ }, ++  ++ crop : function() ++ { ++ if(!this.canvasLoaded){ ++ return; ++ } ++  ++ var imageCanvas = document.createElement("canvas"); ++  ++ var imageContext = imageCanvas.getContext("2d"); ++  ++ imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight; ++ imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight; ++  ++ var center = imageCanvas.width / 2; ++  ++ imageContext.translate(center, center); ++  ++ imageContext.rotate(this.rotate * Math.PI / 180); ++  ++ imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight); ++  ++ var canvas = document.createElement("canvas"); ++  ++ var context = canvas.getContext("2d"); ++  ++ canvas.width = this.minWidth; ++ canvas.height = this.minHeight; ++ ++ switch (this.rotate) { ++ case 0 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++ ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 90 :  ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++  ++ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0; ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 180 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++ ++ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight); ++ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0; ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 270 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++  ++ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight); ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ default :  ++ break; ++ } ++  ++ this.cropData = canvas.toDataURL(this.cropType); ++  ++ if(this.fireEvent('crop', this, this.cropData) !== false){ ++ this.process(this.file, this.cropData); ++ } ++  ++ return; ++  ++ }, ++  ++ setThumbBoxSize : function() ++ { ++ var width, height; ++  ++ if(this.isDocument && typeof(this.imageEl) != 'undefined'){ ++ width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight); ++ height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight); ++  ++ this.minWidth = width; ++ this.minHeight = height; ++  ++ if(this.rotate == 90 || this.rotate == 270){ ++ this.minWidth = height; ++ this.minHeight = width; ++ } ++ } ++  ++ height = 300; ++ width = Math.ceil(this.minWidth * height / this.minHeight); ++  ++ if(this.minWidth > this.minHeight){ ++ width = 300; ++ height = Math.ceil(this.minHeight * width / this.minWidth); ++ } ++  ++ this.thumbEl.setStyle({ ++ width : width + 'px', ++ height : height + 'px' ++ }); ++ ++ return; ++  ++ }, ++  ++ 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() ++ { ++ this.baseRotate = 1; ++  ++ if( ++ typeof(this.exif) != 'undefined' && ++ typeof(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]) != 'undefined' && ++ [1, 3, 6, 8].indexOf(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]) != -1 ++ ){ ++ this.baseRotate = this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]; ++ } ++  ++ this.rotate = Roo.dialog.UploadCropbox['Orientation'][this.baseRotate]; ++  ++ }, ++  ++ baseScaleLevel : function() ++ { ++ var width, height; ++  ++ if(this.isDocument){ ++  ++ if(this.baseRotate == 6 || this.baseRotate == 8){ ++  ++ height = this.thumbEl.getHeight(); ++ this.baseScale = height / this.imageEl.OriginWidth; ++ ++ if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){ ++ width = this.thumbEl.getWidth(); ++ this.baseScale = width / this.imageEl.OriginHeight; ++ } ++ ++ return; ++ } ++ ++ 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; ++ } ++ ++ return; ++ } ++  ++ if(this.baseRotate == 6 || this.baseRotate == 8){ ++  ++ width = this.thumbEl.getHeight(); ++ this.baseScale = width / 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; ++ } ++  ++ 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; ++ } ++  ++ } ++  ++ return; ++ }, ++  ++ getScaleLevel : function() ++ { ++ return this.baseScale * Math.pow(1.1, this.scale); ++ }, ++  ++ onTouchStart : function(e) ++ { ++ if(!this.canvasLoaded){ ++ this.beforeSelectFile(e); ++ return; ++ } ++  ++ var touches = e.browserEvent.touches; ++  ++ if(!touches){ ++ return; ++ } ++  ++ if(touches.length == 1){ ++ this.onMouseDown(e); ++ return; ++ } ++  ++ if(touches.length != 2){ ++ return; ++ } ++  ++ var coords = []; ++  ++ for(var i = 0, finger; finger = touches[i]; i++){ ++ coords.push(finger.pageX, finger.pageY); ++ } ++  ++ 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.startScale = this.scale; ++  ++ this.pinching = true; ++ this.dragable = false; ++  ++ }, ++  ++ onTouchMove : function(e) ++ { ++ if(!this.pinching && !this.dragable){ ++ return; ++ } ++  ++ var touches = e.browserEvent.touches; ++  ++ if(!touches){ ++ return; ++ } ++  ++ if(this.dragable){ ++ this.onMouseMove(e); ++ return; ++ } ++  ++ var coords = []; ++  ++ for(var i = 0, finger; finger = touches[i]; i++){ ++ coords.push(finger.pageX, finger.pageY); ++ } ++  ++ 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.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1)); ++  ++ if(!this.zoomable()){ ++ this.scale = this.startScale; ++ return; ++ } ++  ++ this.draw(); ++  ++ }, ++  ++ onTouchEnd : function(e) ++ { ++ this.pinching = false; ++ this.dragable = false; ++  ++ }, ++  ++ process : function(file, crop) ++ { ++ if(this.loadMask){ ++ this.maskEl.mask(this.loadingText); ++ } ++  ++ this.xhr = new XMLHttpRequest(); ++  ++ file.xhr = this.xhr; ++ ++ this.xhr.open(this.method, this.url, true); ++  ++ var headers = { ++ "Accept": "application/json", ++ "Cache-Control": "no-cache", ++ "X-Requested-With": "XMLHttpRequest" ++ }; ++  ++ for (var headerName in headers) { ++ var headerValue = headers[headerName]; ++ if (headerValue) { ++ this.xhr.setRequestHeader(headerName, headerValue); ++ } ++ } ++  ++ var _this = this; ++  ++ this.xhr.onload = function() ++ { ++ _this.xhrOnLoad(_this.xhr); ++ } ++  ++ this.xhr.onerror = function() ++ { ++ _this.xhrOnError(_this.xhr); ++ } ++  ++ var formData = new FormData(); ++ ++ formData.append('returnHTML', 'NO'); ++  ++ if(crop){ ++ formData.append('crop', crop); ++ } ++  ++ if(typeof(file) != 'undefined' && (typeof(file.id) == 'undefined' || file.id * 1 < 1)){ ++ formData.append(this.paramName, file, file.name); ++ } ++  ++ if(typeof(file.filename) != 'undefined'){ ++ formData.append('filename', file.filename); ++ } ++  ++ if(typeof(file.mimetype) != 'undefined'){ ++ formData.append('mimetype', file.mimetype); ++ } ++  ++ if(this.fireEvent('arrange', this, formData) != false){ ++ this.xhr.send(formData); ++ }; ++ }, ++  ++ xhrOnLoad : function(xhr) ++ { ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ if (xhr.readyState !== 4) { ++ this.fireEvent('exception', this, xhr); ++ return; ++ } ++ ++ var response = Roo.decode(xhr.responseText); ++  ++ if(!response.success){ ++ this.fireEvent('exception', this, xhr); ++ return; ++ } ++  ++ var response = Roo.decode(xhr.responseText); ++  ++ this.fireEvent('upload', this, response); ++  ++ }, ++  ++ xhrOnError : function() ++ { ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ Roo.log('xhr on error'); ++  ++ var response = Roo.decode(xhr.responseText); ++  ++ Roo.log(response); ++  ++ }, ++  ++ prepare : function(file) ++ {  ++ if(this.loadMask){ ++ this.maskEl.mask(this.loadingText); ++ } ++  ++ this.file = false; ++ this.exif = {}; ++  ++ if(typeof(file) === 'string'){ ++ this.loadCanvas(file); ++ return; ++ } ++  ++ if(!file || !this.urlAPI){ ++ return; ++ } ++  ++ this.file = file; ++ this.cropType = file.type; ++  ++ var _this = this; ++  ++ if(this.fireEvent('prepare', this, this.file) != false){ ++  ++ 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.dialog.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.dialog.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 : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-picture', ++ action : 'picture', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ], ++ DOCUMENT : [ ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-left', ++ action : 'rotate-left', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-download', ++ action : 'download', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-crop', ++ action : 'crop', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-trash', ++ action : 'trash', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ], ++ ROTATOR : [ ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-left', ++ action : 'rotate-left', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ] ++ } ++}); +diff --git a/buildSDK/dependancy_ui.txt b/buildSDK/dependancy_ui.txt +index 5a8e5a9ac5..f89656e412 100644 +--- a/buildSDK/dependancy_ui.txt ++++ b/buildSDK/dependancy_ui.txt +@@ -197,3 +197,6 @@ Roo.XTemplate +  + // is this ready yet? - is it used? + // Roo.Login ++ ++Roo.dialog.namespace ++Roo.dialog.UploadCropbox +diff --git a/css/alert.css b/css/alert.css +new file mode 100644 +index 0000000000..0cc7751f02 +--- /dev/null ++++ b/css/alert.css +@@ -0,0 +1,75 @@ ++.alert { ++ padding: 15px; ++ margin-bottom: 20px; ++ border: 1px solid transparent; ++ border-radius: 4px; ++} ++.alert h4 { ++ margin-top: 0; ++ color: inherit; ++} ++.alert .alert-link { ++ font-weight: bold; ++} ++.alert > p, ++.alert > ul { ++ margin-bottom: 0; ++} ++.alert > p + p { ++ margin-top: 5px; ++} ++.alert-dismissable, ++.alert-dismissible { ++ padding-right: 35px; ++} ++.alert-dismissable .close, ++.alert-dismissible .close { ++ position: relative; ++ top: -2px; ++ right: -21px; ++ color: inherit; ++} ++.alert-success { ++ background-color: #dff0d8; ++ border-color: #d6e9c6; ++ color: #3c763d; ++} ++.alert-success hr { ++ border-top-color: #c9e2b3; ++} ++.alert-success .alert-link { ++ color: #2b542c; ++} ++.alert-info { ++ background-color: #d9edf7; ++ border-color: #bce8f1; ++ color: #31708f; ++} ++.alert-info hr { ++ border-top-color: #a6e1ec; ++} ++.alert-info .alert-link { ++ color: #245269; ++} ++.alert-warning { ++ background-color: #fcf8e3; ++ border-color: #faebcc; ++ color: #8a6d3b; ++} ++.alert-warning hr { ++ border-top-color: #f7e1b5; ++} ++.alert-warning .alert-link { ++ color: #66512c; ++} ++.alert-danger { ++ background-color: #f2dede; ++ border-color: #ebccd1; ++ color: #a94442; ++} ++.alert-danger hr { ++ border-top-color: #e4b9c0; ++} ++.alert-danger .alert-link { ++ color: #843534; ++} +\ No newline at end of file +diff --git a/css/button-groups.css b/css/button-groups.css +new file mode 100644 +index 0000000000..b725faf99b +--- /dev/null ++++ b/css/button-groups.css +@@ -0,0 +1,171 @@ ++.btn-group, ++.btn-group-vertical { ++ position: relative; ++ display: inline-block; ++ vertical-align: middle; ++} ++.btn-group > .btn, ++.btn-group-vertical > .btn { ++ position: relative; ++ float: left; ++} ++.btn-group > .btn:hover, ++.btn-group-vertical > .btn:hover, ++.btn-group > .btn:focus, ++.btn-group-vertical > .btn:focus, ++.btn-group > .btn:active, ++.btn-group-vertical > .btn:active, ++.btn-group > .btn.active, ++.btn-group-vertical > .btn.active { ++ z-index: 2; ++} ++.btn-group .btn + .btn, ++.btn-group .btn + .btn-group, ++.btn-group .btn-group + .btn, ++.btn-group .btn-group + .btn-group { ++ margin-left: -1px; ++} ++.btn-toolbar { ++ margin-left: -5px; ++} ++.btn-toolbar .btn, ++.btn-toolbar .btn-group, ++.btn-toolbar .input-group { ++ float: left; ++} ++.btn-toolbar > .btn, ++.btn-toolbar > .btn-group, ++.btn-toolbar > .input-group { ++ margin-left: 5px; ++} ++.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { ++ border-radius: 0; ++} ++.btn-group > .btn:first-child { ++ margin-left: 0; ++} ++.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { ++ border-bottom-right-radius: 0; ++ border-top-right-radius: 0; ++} ++.btn-group > .btn:last-child:not(:first-child), ++.btn-group > .dropdown-toggle:not(:first-child) { ++ border-bottom-left-radius: 0; ++ border-top-left-radius: 0; ++} ++.btn-group > .btn-group { ++ float: left; ++} ++.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { ++ border-radius: 0; ++} ++.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, ++.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { ++ border-bottom-right-radius: 0; ++ border-top-right-radius: 0; ++} ++.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { ++ border-bottom-left-radius: 0; ++ border-top-left-radius: 0; ++} ++.btn-group .dropdown-toggle:active, ++.btn-group.open .dropdown-toggle { ++ outline: 0; ++} ++.btn-group > .btn + .dropdown-toggle { ++ padding-left: 8px; ++ padding-right: 8px; ++} ++.btn-group > .btn-lg + .dropdown-toggle { ++ padding-left: 12px; ++ padding-right: 12px; ++} ++.btn-group.open .dropdown-toggle { ++ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); ++ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); ++} ++.btn-group.open .dropdown-toggle.btn-link { ++ -webkit-box-shadow: none; ++ box-shadow: none; ++} ++.btn .caret { ++ margin-left: 0; ++} ++.btn-lg .caret { ++ border-width: 5px 5px 0; ++ border-bottom-width: 0; ++} ++.dropup .btn-lg .caret { ++ border-width: 0 5px 5px; ++} ++.btn-group-vertical > .btn, ++.btn-group-vertical > .btn-group, ++.btn-group-vertical > .btn-group > .btn { ++ display: block; ++ float: none; ++ width: 100%; ++ max-width: 100%; ++} ++.btn-group-vertical > .btn-group > .btn { ++ float: none; ++} ++.btn-group-vertical > .btn + .btn, ++.btn-group-vertical > .btn + .btn-group, ++.btn-group-vertical > .btn-group + .btn, ++.btn-group-vertical > .btn-group + .btn-group { ++ margin-top: -1px; ++ margin-left: 0; ++} ++.btn-group-vertical > .btn:not(:first-child):not(:last-child) { ++ border-radius: 0; ++} ++.btn-group-vertical > .btn:first-child:not(:last-child) { ++ border-top-right-radius: 4px; ++ border-top-left-radius: 4px; ++ border-bottom-right-radius: 0; ++ border-bottom-left-radius: 0; ++} ++.btn-group-vertical > .btn:last-child:not(:first-child) { ++ border-top-right-radius: 0; ++ border-top-left-radius: 0; ++ border-bottom-right-radius: 4px; ++ border-bottom-left-radius: 4px; ++} ++.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { ++ border-radius: 0; ++} ++.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, ++.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { ++ border-bottom-right-radius: 0; ++ border-bottom-left-radius: 0; ++} ++.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { ++ border-top-right-radius: 0; ++ border-top-left-radius: 0; ++} ++.btn-group-justified { ++ display: table; ++ width: 100%; ++ table-layout: fixed; ++ border-collapse: separate; ++} ++.btn-group-justified > .btn, ++.btn-group-justified > .btn-group { ++ float: none; ++ display: table-cell; ++ width: 1%; ++} ++.btn-group-justified > .btn-group .btn { ++ width: 100%; ++} ++.btn-group-justified > .btn-group .dropdown-menu { ++ left: auto; ++} ++[data-toggle="buttons"] > .btn input[type="radio"], ++[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], ++[data-toggle="buttons"] > .btn input[type="checkbox"], ++[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { ++ position: absolute; ++ clip: rect(0, 0, 0, 0); ++ pointer-events: none; ++} +\ No newline at end of file +diff --git a/css/buttons.css b/css/buttons.css +new file mode 100644 +index 0000000000..42ec098feb +--- /dev/null ++++ b/css/buttons.css +@@ -0,0 +1,463 @@ ++.btn { ++ display: inline-block; ++ margin-bottom: 0; ++ font-weight: normal; ++ text-align: center; ++ vertical-align: middle; ++ touch-action: manipulation; ++ cursor: pointer; ++ background-image: none; ++ border: 1px solid transparent; ++ white-space: nowrap; ++ padding: 6px 12px; ++ font-size: 14px; ++ line-height: 1.42857143; ++ border-radius: 4px; ++ -webkit-user-select: none; ++ -moz-user-select: none; ++ -ms-user-select: none; ++ user-select: none; ++} ++.btn:focus, ++.btn:active:focus, ++.btn.active:focus, ++.btn.focus, ++.btn:active.focus, ++.btn.active.focus { ++ outline: 5px auto -webkit-focus-ring-color; ++ outline-offset: -2px; ++} ++.btn:hover, ++.btn:focus, ++.btn.focus { ++ color: #333333; ++ text-decoration: none; ++} ++.btn:active, ++.btn.active { ++ outline: 0; ++ background-image: none; ++ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); ++ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); ++} ++.btn.disabled, ++.btn[disabled], ++fieldset[disabled] .btn { ++ cursor: not-allowed; ++ opacity: 0.65; ++ filter: alpha(opacity=65); ++ -webkit-box-shadow: none; ++ box-shadow: none; ++} ++a.btn.disabled, ++fieldset[disabled] a.btn { ++ pointer-events: none; ++} ++.btn-default { ++ color: #333333; ++ background-color: #ffffff; ++ border-color: #cccccc; ++} ++.btn-default:focus, ++.btn-default.focus { ++ color: #333333; ++ background-color: #e6e6e6; ++ border-color: #8c8c8c; ++} ++.btn-default:hover { ++ color: #333333; ++ background-color: #e6e6e6; ++ border-color: #adadad; ++} ++.btn-default:active, ++.btn-default.active, ++.open > .dropdown-toggle.btn-default { ++ color: #333333; ++ background-color: #e6e6e6; ++ border-color: #adadad; ++} ++.btn-default:active:hover, ++.btn-default.active:hover, ++.open > .dropdown-toggle.btn-default:hover, ++.btn-default:active:focus, ++.btn-default.active:focus, ++.open > .dropdown-toggle.btn-default:focus, ++.btn-default:active.focus, ++.btn-default.active.focus, ++.open > .dropdown-toggle.btn-default.focus { ++ color: #333333; ++ background-color: #d4d4d4; ++ border-color: #8c8c8c; ++} ++.btn-default:active, ++.btn-default.active, ++.open > .dropdown-toggle.btn-default { ++ background-image: none; ++} ++.btn-default.disabled:hover, ++.btn-default[disabled]:hover, ++fieldset[disabled] .btn-default:hover, ++.btn-default.disabled:focus, ++.btn-default[disabled]:focus, ++fieldset[disabled] .btn-default:focus, ++.btn-default.disabled.focus, ++.btn-default[disabled].focus, ++fieldset[disabled] .btn-default.focus { ++ background-color: #ffffff; ++ border-color: #cccccc; ++} ++.btn-default .badge { ++ color: #ffffff; ++ background-color: #333333; ++} ++.btn-primary { ++ color: #ffffff; ++ background-color: #337ab7; ++ border-color: #2e6da4; ++} ++.btn-primary:focus, ++.btn-primary.focus { ++ color: #ffffff; ++ background-color: #286090; ++ border-color: #122b40; ++} ++.btn-primary:hover { ++ color: #ffffff; ++ background-color: #286090; ++ border-color: #204d74; ++} ++.btn-primary:active, ++.btn-primary.active, ++.open > .dropdown-toggle.btn-primary { ++ color: #ffffff; ++ background-color: #286090; ++ border-color: #204d74; ++} ++.btn-primary:active:hover, ++.btn-primary.active:hover, ++.open > .dropdown-toggle.btn-primary:hover, ++.btn-primary:active:focus, ++.btn-primary.active:focus, ++.open > .dropdown-toggle.btn-primary:focus, ++.btn-primary:active.focus, ++.btn-primary.active.focus, ++.open > .dropdown-toggle.btn-primary.focus { ++ color: #ffffff; ++ background-color: #204d74; ++ border-color: #122b40; ++} ++.btn-primary:active, ++.btn-primary.active, ++.open > .dropdown-toggle.btn-primary { ++ background-image: none; ++} ++.btn-primary.disabled:hover, ++.btn-primary[disabled]:hover, ++fieldset[disabled] .btn-primary:hover, ++.btn-primary.disabled:focus, ++.btn-primary[disabled]:focus, ++fieldset[disabled] .btn-primary:focus, ++.btn-primary.disabled.focus, ++.btn-primary[disabled].focus, ++fieldset[disabled] .btn-primary.focus { ++ background-color: #337ab7; ++ border-color: #2e6da4; ++} ++.btn-primary .badge { ++ color: #337ab7; ++ background-color: #ffffff; ++} ++.btn-success { ++ color: #ffffff; ++ background-color: #5cb85c; ++ border-color: #4cae4c; ++} ++.btn-success:focus, ++.btn-success.focus { ++ color: #ffffff; ++ background-color: #449d44; ++ border-color: #255625; ++} ++.btn-success:hover { ++ color: #ffffff; ++ background-color: #449d44; ++ border-color: #398439; ++} ++.btn-success:active, ++.btn-success.active, ++.open > .dropdown-toggle.btn-success { ++ color: #ffffff; ++ background-color: #449d44; ++ border-color: #398439; ++} ++.btn-success:active:hover, ++.btn-success.active:hover, ++.open > .dropdown-toggle.btn-success:hover, ++.btn-success:active:focus, ++.btn-success.active:focus, ++.open > .dropdown-toggle.btn-success:focus, ++.btn-success:active.focus, ++.btn-success.active.focus, ++.open > .dropdown-toggle.btn-success.focus { ++ color: #ffffff; ++ background-color: #398439; ++ border-color: #255625; ++} ++.btn-success:active, ++.btn-success.active, ++.open > .dropdown-toggle.btn-success { ++ background-image: none; ++} ++.btn-success.disabled:hover, ++.btn-success[disabled]:hover, ++fieldset[disabled] .btn-success:hover, ++.btn-success.disabled:focus, ++.btn-success[disabled]:focus, ++fieldset[disabled] .btn-success:focus, ++.btn-success.disabled.focus, ++.btn-success[disabled].focus, ++fieldset[disabled] .btn-success.focus { ++ background-color: #5cb85c; ++ border-color: #4cae4c; ++} ++.btn-success .badge { ++ color: #5cb85c; ++ background-color: #ffffff; ++} ++.btn-info { ++ color: #ffffff; ++ background-color: #5bc0de; ++ border-color: #46b8da; ++} ++.btn-info:focus, ++.btn-info.focus { ++ color: #ffffff; ++ background-color: #31b0d5; ++ border-color: #1b6d85; ++} ++.btn-info:hover { ++ color: #ffffff; ++ background-color: #31b0d5; ++ border-color: #269abc; ++} ++.btn-info:active, ++.btn-info.active, ++.open > .dropdown-toggle.btn-info { ++ color: #ffffff; ++ background-color: #31b0d5; ++ border-color: #269abc; ++} ++.btn-info:active:hover, ++.btn-info.active:hover, ++.open > .dropdown-toggle.btn-info:hover, ++.btn-info:active:focus, ++.btn-info.active:focus, ++.open > .dropdown-toggle.btn-info:focus, ++.btn-info:active.focus, ++.btn-info.active.focus, ++.open > .dropdown-toggle.btn-info.focus { ++ color: #ffffff; ++ background-color: #269abc; ++ border-color: #1b6d85; ++} ++.btn-info:active, ++.btn-info.active, ++.open > .dropdown-toggle.btn-info { ++ background-image: none; ++} ++.btn-info.disabled:hover, ++.btn-info[disabled]:hover, ++fieldset[disabled] .btn-info:hover, ++.btn-info.disabled:focus, ++.btn-info[disabled]:focus, ++fieldset[disabled] .btn-info:focus, ++.btn-info.disabled.focus, ++.btn-info[disabled].focus, ++fieldset[disabled] .btn-info.focus { ++ background-color: #5bc0de; ++ border-color: #46b8da; ++} ++.btn-info .badge { ++ color: #5bc0de; ++ background-color: #ffffff; ++} ++.btn-warning { ++ color: #ffffff; ++ background-color: #f0ad4e; ++ border-color: #eea236; ++} ++.btn-warning:focus, ++.btn-warning.focus { ++ color: #ffffff; ++ background-color: #ec971f; ++ border-color: #985f0d; ++} ++.btn-warning:hover { ++ color: #ffffff; ++ background-color: #ec971f; ++ border-color: #d58512; ++} ++.btn-warning:active, ++.btn-warning.active, ++.open > .dropdown-toggle.btn-warning { ++ color: #ffffff; ++ background-color: #ec971f; ++ border-color: #d58512; ++} ++.btn-warning:active:hover, ++.btn-warning.active:hover, ++.open > .dropdown-toggle.btn-warning:hover, ++.btn-warning:active:focus, ++.btn-warning.active:focus, ++.open > .dropdown-toggle.btn-warning:focus, ++.btn-warning:active.focus, ++.btn-warning.active.focus, ++.open > .dropdown-toggle.btn-warning.focus { ++ color: #ffffff; ++ background-color: #d58512; ++ border-color: #985f0d; ++} ++.btn-warning:active, ++.btn-warning.active, ++.open > .dropdown-toggle.btn-warning { ++ background-image: none; ++} ++.btn-warning.disabled:hover, ++.btn-warning[disabled]:hover, ++fieldset[disabled] .btn-warning:hover, ++.btn-warning.disabled:focus, ++.btn-warning[disabled]:focus, ++fieldset[disabled] .btn-warning:focus, ++.btn-warning.disabled.focus, ++.btn-warning[disabled].focus, ++fieldset[disabled] .btn-warning.focus { ++ background-color: #f0ad4e; ++ border-color: #eea236; ++} ++.btn-warning .badge { ++ color: #f0ad4e; ++ background-color: #ffffff; ++} ++.btn-danger { ++ color: #ffffff; ++ background-color: #d9534f; ++ border-color: #d43f3a; ++} ++.btn-danger:focus, ++.btn-danger.focus { ++ color: #ffffff; ++ background-color: #c9302c; ++ border-color: #761c19; ++} ++.btn-danger:hover { ++ color: #ffffff; ++ background-color: #c9302c; ++ border-color: #ac2925; ++} ++.btn-danger:active, ++.btn-danger.active, ++.open > .dropdown-toggle.btn-danger { ++ color: #ffffff; ++ background-color: #c9302c; ++ border-color: #ac2925; ++} ++.btn-danger:active:hover, ++.btn-danger.active:hover, ++.open > .dropdown-toggle.btn-danger:hover, ++.btn-danger:active:focus, ++.btn-danger.active:focus, ++.open > .dropdown-toggle.btn-danger:focus, ++.btn-danger:active.focus, ++.btn-danger.active.focus, ++.open > .dropdown-toggle.btn-danger.focus { ++ color: #ffffff; ++ background-color: #ac2925; ++ border-color: #761c19; ++} ++.btn-danger:active, ++.btn-danger.active, ++.open > .dropdown-toggle.btn-danger { ++ background-image: none; ++} ++.btn-danger.disabled:hover, ++.btn-danger[disabled]:hover, ++fieldset[disabled] .btn-danger:hover, ++.btn-danger.disabled:focus, ++.btn-danger[disabled]:focus, ++fieldset[disabled] .btn-danger:focus, ++.btn-danger.disabled.focus, ++.btn-danger[disabled].focus, ++fieldset[disabled] .btn-danger.focus { ++ background-color: #d9534f; ++ border-color: #d43f3a; ++} ++.btn-danger .badge { ++ color: #d9534f; ++ background-color: #ffffff; ++} ++.btn-link { ++ color: #337ab7; ++ font-weight: normal; ++ border-radius: 0; ++} ++.btn-link, ++.btn-link:active, ++.btn-link.active, ++.btn-link[disabled], ++fieldset[disabled] .btn-link { ++ background-color: transparent; ++ -webkit-box-shadow: none; ++ box-shadow: none; ++} ++.btn-link, ++.btn-link:hover, ++.btn-link:focus, ++.btn-link:active { ++ border-color: transparent; ++} ++.btn-link:hover, ++.btn-link:focus { ++ color: #23527c; ++ text-decoration: underline; ++ background-color: transparent; ++} ++.btn-link[disabled]:hover, ++fieldset[disabled] .btn-link:hover, ++.btn-link[disabled]:focus, ++fieldset[disabled] .btn-link:focus { ++ color: #777777; ++ text-decoration: none; ++} ++.btn-lg, ++.btn-group-lg > .btn { ++ padding: 10px 16px; ++ font-size: 18px; ++ line-height: 1.3333333; ++ border-radius: 6px; ++} ++.btn-sm, ++.btn-group-sm > .btn { ++ padding: 5px 10px; ++ font-size: 12px; ++ line-height: 1.5; ++ border-radius: 3px; ++} ++.btn-xs, ++.btn-group-xs > .btn { ++ padding: 1px 5px; ++ font-size: 12px; ++ line-height: 1.5; ++ border-radius: 3px; ++} ++.btn-block { ++ display: block; ++ width: 100%; ++} ++.btn-block + .btn-block { ++ margin-top: 5px; ++} ++input[type="submit"].btn-block, ++input[type="reset"].btn-block, ++input[type="button"].btn-block { ++ width: 100%; ++} +\ No newline at end of file +diff --git a/css/upload-cropbox.css b/css/upload-cropbox.css +new file mode 100644 +index 0000000000..f8500935aa +--- /dev/null ++++ b/css/upload-cropbox.css +@@ -0,0 +1,62 @@ ++.roo-upload-cropbox-selector { ++ visibility: hidden; ++ height: 0px; ++} ++.roo-upload-cropbox-dialog .modal-header, ++.roo-upload-cropbox-dialog .modal-footer { ++ padding-top: 5px; ++ padding-bottom: 5px; ++} ++.roo-upload-cropbox-body { ++ background-color: #ffffff; ++ border: 1px solid #777777; ++ width: 100%; ++ height: 450px; ++ max-height: 450px; ++ position: relative; ++ overflow: hidden; ++ cursor: move; ++} ++.roo-upload-cropbox-preview { ++ position: absolute; ++ top: 0px; ++ left: 0px; ++ text-align: center; ++ margin: 0px; ++ padding: 0px; ++ border: none; ++} ++.roo-upload-cropbox-body .roo-upload-cropbox-thumb { ++ position: absolute; ++ /* top: 50%; ++ left: 50%; ++ transform: translate(-50%, -50%);*/ ++ box-sizing: border-box; ++ border: 1px solid #777777; ++ box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.5); ++ background: none repeat scroll 0% 0% transparent; ++} ++.roo-upload-cropbox-body .roo-upload-cropbox-empty-notify { ++ height: 100%; ++ background-color: rgba(0, 0, 0, 0.5); ++ color: #ffffff; ++ font-weight: bold; ++ font-size: 24px; ++ text-align: center; ++ padding-top: 50px; ++ font-style: italic; ++} ++.roo-upload-cropbox-btn-group button { ++ background-color: #000000; ++ color: #ffffff; ++ border-color: #333333; ++} ++.roo-upload-cropbox-error-notify { ++ border-radius: 0px; ++ text-align: center; ++ padding: 0px !important; ++ margin: 0px !important; ++ position: absolute; ++ top: 0; ++ left: 0; ++} +\ No newline at end of file +diff --git a/examples/dialog/hello.html b/examples/dialog/hello.html +index ab43ed9999..ec001bf313 100644 +--- a/examples/dialog/hello.html ++++ b/examples/dialog/hello.html +@@ -1,27 +1,27 @@ +- +- +- +- +-Hello World Dialog Example ++ ++ ++ ++ ++Hello World Dialog Example +  +  +  +  +-  +-  +-  +- +- +- +- +- +- +-

Hello World Dialog

 +-

This example shows how to create a very simple modal BasicDialog with "autoTabs".

 +-

 ++  ++  ++  ++ ++ ++ ++ ++ ++ ++

Hello World Dialog

 ++

This example shows how to create a very simple modal BasicDialog with "autoTabs".

 ++

 +

Note that the js is not minified so it is readable. See  +-for the full source code.

 +-Here's snapshot of the code that creates the dialog: ++for the full source code.

 ++Here's snapshot of the code that creates the dialog: +
Roo.BLANK_IMAGE_URL  = "../../images/default/s.gif";
+ 
+ 
+@@ -121,29 +121,29 @@ Roo.onReady(function() {
+     Roo.get('show-dialog-btn').on('click',function () {
+         HelloWorld.show({ _el : this});
+     });
+-});
+-
 +- +-  +-  +- +- +- ++}); ++ ++ ++  ++  ++ ++ ++ +diff --git a/examples/dialog/test-2.html b/examples/dialog/test-2.html +new file mode 100644 +index 0000000000..e26d6ee586 +--- /dev/null ++++ b/examples/dialog/test-2.html +@@ -0,0 +1,30 @@ ++ ++ ++ ++  ++ Upload Cropbox Dialog Example ++ ++  ++  ++  ++  ++  ++  ++  ++ ++   ++  ++  ++ ++ ++ ++ ++

Upload Cropbox Dialog

 ++

This example shows how to create a very simple BasicDialog with "UploadCropbox".

 ++

 ++

Note that the js is not minified so it is readable. See  ++for the full source code.

 ++ ++ ++ ++ +diff --git a/examples/dialog/test-2.js b/examples/dialog/test-2.js +new file mode 100644 +index 0000000000..c4dcdedd7e +--- /dev/null ++++ b/examples/dialog/test-2.js +@@ -0,0 +1,171 @@ ++var uploadCropbox = { ++ dialog : false, ++ callback : false, ++ ++ show : function(data, cb) ++ { ++ if (!this.dialog) { ++ this.create(); ++ } ++ ++ this.callback = cb; ++ this.data = data; ++ this.dialog.show(); ++ }, ++ ++ create : function() ++ { ++ var _this = this; ++ this.dialog = Roo.factory({ ++ xns : Roo, ++ xtype : 'LayoutDialog', ++ width : 800, ++ height : 600, ++ center : { ++ xns : Roo, ++ xtype : 'LayoutRegion' ++ }, ++ items : [ ++ { ++ xtype: 'ContentPanel', ++ xns: Roo, ++ region : "center", ++ items : [ ++ { ++ xtype : 'UploadCropbox', ++ xns : Roo.dialog, ++ minWidth : 720, ++ minHeight: 480, ++ buttons: [], ++ listeners : { ++ render : function (_self) ++ { ++ _this.cropbox = _self; ++ }, ++ loadcanvas : function (_self, imageEl) ++ { ++ if(imageEl.OriginWidth < 720) { ++ Roo.Msg.show({ ++ title: 'Error', ++ msg: "Image width should be at least 720", ++ buttons: {ok : true}, ++ fn: function(res) { ++ _this.cropbox.selectorEl.dom.click(); ++ } ++ }); ++ return false; ++ } ++ } ++ } ++ } ++ ] ++ } ++ ], ++ buttons : [ ++ { ++ xtype : 'Button', ++ xns : Roo, ++ text : 'Save', ++ listeners : { ++ click : function () { ++ }  ++ } ++ }, ++ { ++ xtype : 'Button', ++ xns : Roo, ++ text : 'Cancel', ++ listeners : { ++ click : function () { ++ _this.dialog.hide() ++ }  ++ } ++ } ++ ] ++ }); ++ } ++} ++ ++var test = { ++ ++ dialog : false, ++ callback : false, ++ ++ show : function(data, cb) ++ { ++ if (!this.dialog) { ++ this.create(); ++ } ++ ++ this.callback = cb; ++ this.data = data; ++ this.dialog.show(); ++ }, ++ ++ create : function() ++ { ++ var _this = this; ++ this.dialog = Roo.factory({ ++ xns : Roo, ++ xtype : 'LayoutDialog', ++ width : 600, ++ height : 450, ++ center : { ++ xns : Roo, ++ xtype : 'LayoutRegion' ++ }, ++ items : [ ++ { ++ xns : Roo, ++ xtype: 'GridPanel', ++ region : "center", ++ grid : { ++ xns : Roo.grid, ++ xtype : 'Grid', ++ cm : [ ++ { ++ xns : Roo.grid, ++ xtype : 'ColumnModel', ++ header : 'test' ++ } ++ ], ++ ds : { ++ xns: Roo.data, ++ xtype: 'Store' ++ }, ++ toolbar : { ++ xns: Roo, ++ xtype: 'Toolbar', ++ items : [ ++ {  ++ xtype : 'Button', ++ text : 'Add', ++ listeners : { ++ click : function () { ++ uploadCropbox.show(); ++ document.body.onfocus = function(e) { ++ document.body.onfocus = null; ++ if(!uploadCropbox.cropbox.selectorEl.dom.files.length) { ++ uploadCropbox.dialog.hide(); ++ } ++ } ++ uploadCropbox.cropbox.selectorEl.dom.click(); ++ } ++ } ++ } ++ ] ++ } ++ } ++ } ++ ], ++ }); ++ } ++} ++ ++Roo.onReady(function() { ++  ++ Roo.get('show-dialog-btn').on('click',function () { ++ test.show({}); ++ console.log(test); ++ }); ++}); +\ No newline at end of file +diff --git a/examples/dialog/test.html b/examples/dialog/test.html +new file mode 100644 +index 0000000000..ecb2a0afa3 +--- /dev/null ++++ b/examples/dialog/test.html +@@ -0,0 +1,29 @@ ++ ++ ++ ++  ++ Upload Cropbox Dialog Example ++ ++  ++  ++  ++  ++  ++ ++   ++   ++  ++  ++ ++ ++ ++ ++

Upload Cropbox Bootstrap

 ++

This example shows how to create a very simple modal BasicDialog with "autoTabs".

 ++

 ++

Note that the js is not minified so it is readable. See  ++for the full source code.

 ++ ++ ++ ++ +diff --git a/examples/dialog/test.js b/examples/dialog/test.js +new file mode 100644 +index 0000000000..f08db909f3 +--- /dev/null ++++ b/examples/dialog/test.js +@@ -0,0 +1,94 @@ ++var test = { ++ ++ dialog : false, ++ callback : false, ++ ++ show : function(data, cb) ++ { ++ if (!this.dialog) { ++ this.create(); ++ } ++ ++ this.callback = cb; ++ this.data = data; ++ this.dialog.show(); ++ }, ++ ++ create : function() ++ { ++ var _this = this; ++ this.dialog = Roo.factory({ ++ xtype : 'Modal', ++ xns : Roo.bootstrap, ++ title : 'Upload an Image', ++ buttons : Roo.bootstrap.Modal.OKCANCEL, ++ items: [ ++ { ++ xtype : 'Row', ++ xns : Roo.bootstrap, ++ items: [ ++ { ++ xtype : 'Column', ++ xns : Roo.bootstrap, ++ items: [ ++ { ++ xtype : 'UploadCropbox', ++ xns : Roo.bootstrap, ++ minWidth : 720, ++ minHeight: 480, ++ listeners : { ++ arrange : function (_self, formData) ++ { ++ console.log("ARRANGE"); ++ console.log(formData); ++ }, ++ crop : function (_self, data) ++ { ++ console.log("CROP"); ++ console.log(data); ++ }, ++ resize : function (_self) ++ { ++ console.log("RESIZE"); ++ }, ++ rotate : function (_self) ++ { ++ console.log("ROTATE"); ++ }, ++ render : function (_self) ++ { ++ console.log("RENDER"); ++ console.log(_self); ++ _this.cropbox = _self; ++ } ++  ++ } ++ } ++ ] ++ } ++ ] ++ } ++ ], ++ listeners : { ++ btnclick : function (e) ++ { ++ console.log(e); ++ if(e == 'cancel') { ++ _this.dialog.hide(); ++ return; ++ } ++ ++ _this.cropbox.crop(); ++ } ++ } ++ }); ++ } ++} ++ ++Roo.onReady(function() { ++  ++ Roo.get('show-dialog-btn').on('click',function () { ++ test.show({}); ++ console.log(test); ++ }); ++}); +\ No newline at end of file +diff --git a/roojs-all.js b/roojs-all.js +index 9d9fc1f28f..f98434e789 100644 +--- a/roojs-all.js ++++ b/roojs-all.js +@@ -2544,9 +2544,9 @@ return this.el.getUpdateManager();},_handleRefresh:function(A,B,C){if(!C||!this. + te.setWidth(A);}if(this.adjustments){A+=this.adjustments[0];B+=this.adjustments[1];}return {"width":A,"height":B};},setSize:function(A,B){if(this.fitToFrame&&!this.ignoreResize(A,B)){if(this.fitContainer&&this.resizeEl!=this.el){this.el.setSize(A,B);}var C=this.adjustForComponents(A,B); + this.resizeEl.setSize(this.autoWidth?"auto":C.width,this.autoHeight?"auto":C.height);this.fireEvent('resize',this,C.width,C.height);}},getTitle:function(){return this.title;},setTitle:function(A){this.title=A;if(this.region){this.region.updatePanelTitle(this,A); + }},isClosable:function(){return this.closable;},beforeSlide:function(){this.el.clip();this.resizeEl.clip();},afterSlide:function(){this.el.unclip();this.resizeEl.unclip();},refresh:function(){if(this.refreshDelegate){this.loaded=false;this.refreshDelegate(); +-}},destroy:function(){this.el.removeAllListeners();var A=document.createElement("span");A.appendChild(this.el.dom);A.innerHTML="";this.el.remove();this.el=null;},form:false,view:false,addxtype:function(A){if(A.xtype.match(/^Form$/)){var el;el=this.el.createChild(); +-this.form=new Roo.form.Form(A);if(this.form.allItems.length){this.form.render(el.dom);}return this.form;}if(['View','JsonView','DatePicker'].indexOf(A.xtype)>-1){A.el=this.el.appendChild(document.createElement("div"));var B=new Roo.factory(A);B.render&&B.render(false,''); +-this.view=B;return B;}return false;}}); ++}},destroy:function(){this.el.removeAllListeners();var A=document.createElement("span");A.appendChild(this.el.dom);A.innerHTML="";this.el.remove();this.el=null;},form:false,view:false,addxtype:function(A){if(A.xtype.match(/^UploadCropbox$/)){this.cropbox=new Roo.factory(A); ++this.cropbox.render(this.el);return this.cropbox;}if(A.xtype.match(/^Form$/)){var el;el=this.el.createChild();this.form=new Roo.form.Form(A);if(this.form.allItems.length){this.form.render(el.dom);}return this.form;}if(['View','JsonView','DatePicker'].indexOf(A.xtype)>-1){A.el=this.el.appendChild(document.createElement("div")); ++var B=new Roo.factory(A);B.render&&B.render(false,'');this.view=B;return B;}return false;}}); + // Roo/GridPanel.js + Roo.GridPanel=function(A,B){if(typeof(A.grid)!='undefined'){B=A;A=B.grid;}this.wrapper=Roo.DomHelper.append(document.body,{tag:"div",cls:"x-layout-grid-wrapper x-layout-inactive-content"},true);this.wrapper.dom.appendChild(A.getGridEl().dom);Roo.GridPanel.superclass.constructor.call(this,this.wrapper,B); + if(this.toolbar){this.toolbar.el.insertBefore(this.wrapper.dom.firstChild);}if(this.footer&&!this.footer.el&&this.footer.xtype){this.footer.container=this.grid.getView().getFooterPanel(true);this.footer.dataSource=this.grid.dataSource;this.footer=Roo.factory(this.footer,Roo); +@@ -2875,3 +2875,103 @@ F.push("(typeof("+G+") == 'undefined')");});var H='(('+F.join(" || ")+") ? undef + }return "'"+A+H+C+")"+A+"'";};var B;if(Roo.isGecko){B="tpl.compiled = function(values, parent){ with(values) { return '"+tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn)+"';};};";}else{B=["tpl.compiled = function(values, parent){ with (values) { return ['"]; + B.push(tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn));B.push("'].join('');};};");B=B.join('');}Roo.debug&&Roo.log(B.replace(/\\n/,'\n'));eval(B);return this;},applyTemplate:function(A){return this.master.compiled.call(this,A,{} + );},apply:function(){return this.applyTemplate.apply(this,arguments);}});Roo.XTemplate.from=function(el){el=Roo.getDom(el);return new Roo.XTemplate(el.value||el.innerHTML);}; ++// Roo/dialog/namespace.js ++Roo.dialog={}; ++// Roo/dialog/UploadCropbox.js ++Roo.dialog.UploadCropbox=function(A){console.log("Dialog UploadCropbox Constructor");Roo.dialog.UploadCropbox.superclass.constructor.call(this,A);this.addEvents({"beforeselectfile":true,"initial":true,"crop":true,"prepare":true,"exception":true,"beforeloadcanvas":true,"trash":true,"download":true,"footerbuttonclick":true,"resize":true,"rotate":true,"inspect":true,"upload":true,"arrange":true,"loadcanvas":true} ++);this.buttons=this.buttons||Roo.dialog.UploadCropbox.footer.STANDARD;};Roo.extend(Roo.dialog.UploadCropbox,Roo.Component,{emptyText:'Click to upload image',rotateNotify:'Image is too small to rotate',errorTimeout:3000,scale:0,baseScale:1,rotate:0,dragable:false,pinching:false,mouseX:0,mouseY:0,cropData:false,minWidth:300,minHeight:300,file:false,exif:{} ++,baseRotate:1,cropType:'image/jpeg',buttons:false,canvasLoaded:false,isDocument:false,method:'POST',paramName:'imageUpload',loadMask:true,loadingText:'Loading...',maskEl:false,getAutoCreate:function(){var A={tag:'div',cls:'roo-upload-cropbox',cn:[{tag:'input',cls:'roo-upload-cropbox-selector',type:'file'} ++,{tag:'div',cls:'roo-upload-cropbox-body',style:'cursor:pointer',cn:[{tag:'div',cls:'roo-upload-cropbox-preview'},{tag:'div',cls:'roo-upload-cropbox-thumb'},{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',cn:{tag:'div',cls:'btn-group btn-group-justified roo-upload-cropbox-btn-group',cn:[]}}]};return A;},onRender:function(ct,A){console.log("On Render");console.log(this);Roo.dialog.UploadCropbox.superclass.onRender.call(this,ct,A); ++if(this.el){if(this.el.attr('xtype')){this.el.attr('xtypex',this.el.attr('xtype'));this.el.dom.removeAttribute('xtype');this.initEvents();}}else{var B=Roo.apply({},this.getAutoCreate());B.id=this.id||Roo.id();if(this.cls){B.cls=(typeof(B.cls)=='undefined'?this.cls:B.cls)+' '+this.cls; ++}if(this.style){B.style=(typeof(B.style)=='undefined'?this.style:B.style)+'; '+this.style;}this.el=ct.createChild(B,A);this.initEvents();}if(this.buttons.length){Roo.each(this.buttons,function(bb){var C=this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb); ++C.on('click',this.onFooterButtonClick.createDelegate(this,[bb.action],true));},this);}if(this.loadMask){this.maskEl=this.el;}},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.selectorEl=this.el.select('.roo-upload-cropbox-selector',true).first();this.selectorEl.hide();this.previewEl=this.el.select('.roo-upload-cropbox-preview',true).first(); ++this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.thumbEl=this.el.select('.roo-upload-cropbox-thumb',true).first();this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.thumbEl.hide();this.notifyEl=this.el.select('.roo-upload-cropbox-empty-notify',true).first(); ++this.notifyEl.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.footerEl=this.el.select('.roo-upload-cropbox-footer',true).first(); ++this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.footerEl.hide();this.setThumbBoxSize();this.bind();this.resize();this.fireEvent('initial',this);},bind:function(){var A=this;window.addEventListener("resize",function(){A.resize(); ++});this.bodyEl.on('click',this.beforeSelectFile,this);if(Roo.isTouch){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.bodyEl.on('mousedown',this.onMouseDown,this); ++this.bodyEl.on('mousemove',this.onMouseMove,this);var B=(/Firefox/i.test(navigator.userAgent))?'DOMMouseScroll':'mousewheel';this.bodyEl.on(B,this.onMouseWheel,this);Roo.get(document).on('mouseup',this.onMouseUp,this);}this.selectorEl.on('change',this.onFileSelected,this); ++},reset:function(){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.cropData=false;this.notifyEl.dom.innerHTML=this.emptyText;},resize:function(){if(this.fireEvent('resize',this)!=false){this.setThumbBoxPosition(); ++this.setCanvasPosition();}},onFooterButtonClick:function(e,el,o,A){switch(A){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,A);},beforeSelectFile:function(e){e.preventDefault();if(this.fireEvent('beforeselectfile',this)!=false){this.selectorEl.dom.click();}},onFileSelected:function(e){e.preventDefault(); ++if(typeof(this.selectorEl.dom.files)=='undefined'||!this.selectorEl.dom.files.length){return;}var A=this.selectorEl.dom.files[0];if(this.fireEvent('inspect',this,A)!=false){this.prepare(A);}},trash:function(e){this.fireEvent('trash',this);},download:function(e){this.fireEvent('download',this); ++},loadCanvas:function(A){if(this.fireEvent('beforeloadcanvas',this,A)!=false){this.reset();this.imageEl=document.createElement('img');var B=this;this.imageEl.addEventListener("load",function(){B.onLoadCanvas();});this.imageEl.src=A;}},onLoadCanvas:function(){this.imageEl.OriginWidth=this.imageEl.naturalWidth||this.imageEl.width; ++this.imageEl.OriginHeight=this.imageEl.naturalHeight||this.imageEl.height;if(this.fireEvent('loadcanvas',this,this.imageEl)!=false){this.bodyEl.un('click',this.beforeSelectFile,this);this.notifyEl.hide();this.thumbEl.show();this.footerEl.show();this.baseRotateLevel(); ++if(this.isDocument){this.setThumbBoxSize();}this.setThumbBoxPosition();this.baseScaleLevel();this.draw();this.resize();this.canvasLoaded=true;}if(this.loadMask){this.maskEl.unmask();}},setCanvasPosition:function(){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);},onMouseDown:function(e){e.stopEvent();this.dragable=true;this.pinching=false;if(this.isDocument&&(this.canvasEl.widthE)?C:E);F=(BF)?D:F);this.previewEl.setLeft(E);this.previewEl.setTop(F);this.mouseX=Roo.isTouch?e.browserEvent.touches[0].pageX:e.getPageX(); ++this.mouseY=Roo.isTouch?e.browserEvent.touches[0].pageY:e.getPageY();},onMouseUp:function(e){e.stopEvent();this.dragable=false;},onMouseWheel:function(e){e.stopEvent();this.startScale=this.scale;this.scale=(e.getWheelDelta()==1)?(this.scale+1):(this.scale-1); ++if(!this.zoomable()){this.scale=this.startScale;return;}this.draw();return;},zoomable:function(){var A=this.thumbEl.getWidth()/this.minWidth;if(this.minWidththis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false;}if(!this.isDocument&&(this.rotate==90||this.rotate==270)&&(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false; ++}return true;},onRotateLeft:function(e){if(!this.isDocument&&(this.canvasEl.height180)?0:this.rotate+90;this.draw();return;}this.scale=this.startScale;this.onRotateFail();return false;}this.rotate=(this.rotate>180)?0:this.rotate+90;if(this.isDocument){this.setThumbBoxSize();this.setThumbBoxPosition();this.setCanvasPosition(); ++}this.draw();this.fireEvent('rotate',this,'right');},onRotateFail:function(){this.errorEl.show(true);var A=this;(function(){A.errorEl.hide(true);}).defer(this.errorTimeout);},draw:function(){this.previewEl.dom.innerHTML='';var A=document.createElement("canvas"); ++var B=A.getContext("2d");A.width=this.imageEl.OriginWidth*this.getScaleLevel();A.height=this.imageEl.OriginWidth*this.getScaleLevel();var C=this.imageEl.OriginWidth/2;if(this.imageEl.OriginWidththis.imageEl.OriginHeight){this.contextEl.drawImage(A,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(A,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(A,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(A,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(A,0,0,this.canvasEl.width,this.canvasEl.height,0,0,this.canvasEl.width,this.canvasEl.height); ++break;}this.contextEl.drawImage(A,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;}this.previewEl.appendChild(this.canvasEl);this.setCanvasPosition(); ++},crop:function(){if(!this.canvasLoaded){return;}var A=document.createElement("canvas");var B=A.getContext("2d");A.width=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?this.imageEl.OriginWidth:this.imageEl.OriginHeight;A.height=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?this.imageEl.OriginWidth:this.imageEl.OriginHeight; ++var C=A.width/2;B.translate(C,C);B.rotate(this.rotate*Math.PI/180);B.drawImage(this.imageEl,0,0,this.imageEl.OriginWidth,this.imageEl.OriginHeight,C*-1,C*-1,this.imageEl.OriginWidth,this.imageEl.OriginHeight);var D=document.createElement("canvas");var E=D.getContext("2d"); ++D.width=this.minWidth;D.height=this.minHeight;switch(this.rotate){case 0:var F=(this.thumbEl.getWidth()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getWidth()/this.getScaleLevel());var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getHeight()/this.getScaleLevel()); ++var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel());var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel()); ++var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G;}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getWidth()/this.getScaleLevel()); ++var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getHeight()/this.getScaleLevel());var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel()); ++var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel());var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G; ++}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight):0;E.drawImage(A,sx,sy,F,G,x,y,F,G);break;case 180:var F=(this.thumbEl.getWidth()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getWidth()/this.getScaleLevel()); ++var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getHeight()/this.getScaleLevel());var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel()); ++var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel());var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G; ++}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?0:Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight);sy+=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight):0; ++E.drawImage(A,sx,sy,F,G,x,y,F,G);break;case 270:var F=(this.thumbEl.getWidth()/this.getScaleLevel()>this.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getWidth()/this.getScaleLevel());var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getHeight()/this.getScaleLevel()); ++var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel());var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel()); ++var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G;}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?0:Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight); ++E.drawImage(A,sx,sy,F,G,x,y,F,G);break;default:break;}this.cropData=D.toDataURL(this.cropType);if(this.fireEvent('crop',this,this.cropData)!==false){this.process(this.file,this.cropData);}return;},setThumbBoxSize:function(){var A,B;if(this.isDocument&&typeof(this.imageEl)!='undefined'){A=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?Math.max(this.minWidth,this.minHeight):Math.min(this.minWidth,this.minHeight); ++B=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?Math.min(this.minWidth,this.minHeight):Math.max(this.minWidth,this.minHeight);this.minWidth=A;this.minHeight=B;if(this.rotate==90||this.rotate==270){this.minWidth=B;this.minHeight=A;}}B=300;A=Math.ceil(this.minWidth*B/this.minHeight); ++if(this.minWidth>this.minHeight){A=300;B=Math.ceil(this.minHeight*A/this.minWidth);}this.thumbEl.setStyle({width:A+'px',height:B+'px'});return;},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(){this.baseRotate=1;if(typeof(this.exif)!='undefined'&&typeof(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']])!='undefined'&&[1,3,6,8].indexOf(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']])!=-1){this.baseRotate=this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]; ++}this.rotate=Roo.dialog.UploadCropbox['Orientation'][this.baseRotate];},baseScaleLevel:function(){var A,B;if(this.isDocument){if(this.baseRotate==6||this.baseRotate==8){B=this.thumbEl.getHeight();this.baseScale=B/this.imageEl.OriginWidth;if(this.imageEl.OriginHeight*this.baseScale>this.thumbEl.getWidth()){A=this.thumbEl.getWidth(); ++this.baseScale=A/this.imageEl.OriginHeight;}return;}B=this.thumbEl.getHeight();this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScale>this.thumbEl.getWidth()){A=this.thumbEl.getWidth();this.baseScale=A/this.imageEl.OriginWidth; ++}return;}if(this.baseRotate==6||this.baseRotate==8){A=this.thumbEl.getHeight();this.baseScale=A/this.imageEl.OriginHeight;if(this.imageEl.OriginHeight*this.baseScalethis.imageEl.OriginHeight){B=this.thumbEl.getWidth();this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScalethis.imageEl.OriginHeight){B=this.thumbEl.getHeight(); ++this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScale=0xffe0&&H<=0xffef)||H===0xfffe){I=E.getUint16(F+2)+2;if(F+I>E.byteLength){Roo.log('Invalid meta data: Invalid segment size.'); ++break;}if(H==0xffe1){B.parseExifData(E,F,I);}F+=I;continue;}break;}}var J=B.urlAPI.createObjectURL(B.file);B.loadCanvas(J);return;};C.readAsArrayBuffer(this.file);}},parseExifData:function(A,B,C){var D=B+10,E,F;if(A.getUint32(B+4)!==0x45786966){return;}if(A.getUint32(B+4)!==0x45786966){return; ++}if(D+8>A.byteLength){Roo.log('Invalid Exif data: Invalid segment size.');return;}if(A.getUint16(B+8)!==0x0000){Roo.log('Invalid Exif data: Missing byte alignment offset.');return;}switch(A.getUint16(D)){case 0x4949:E=true;break;case 0x4D4D:E=false;break; ++default:Roo.log('Invalid Exif data: Invalid byte alignment marker.');return;}if(A.getUint16(D+2,E)!==0x002A){Roo.log('Invalid Exif data: Missing TIFF marker.');return;}F=A.getUint32(D+4,E);this.parseExifTags(A,D,D+F,E);},parseExifTags:function(A,B,C,D){var E,F,i; ++if(C+6>A.byteLength){Roo.log('Invalid Exif data: Invalid directory offset.');return;}E=A.getUint16(C,D);F=C+2+12*E;if(F+4>A.byteLength){Roo.log('Invalid Exif data: Invalid directory size.');return;}for(i=0;i4?B+A.getUint32(C+8,F):(C+8);if(I+H>A.byteLength){Roo.log('Invalid Exif data: Invalid data offset.');return;}if(E===1){return G.getValue(A,I,F);}J=[];for(i=0;i'} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-picture',action:'picture',cn:[{tag:'button',cls:'btn btn-default',html:''}]},{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-right',action:'rotate-right',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]}],DOCUMENT:[{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-left',action:'rotate-left',cn:[{tag:'button',cls:'btn btn-default',html:''}]},{tag:'div',cls:'btn-group roo-upload-cropbox-download',action:'download',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-crop',action:'crop',cn:[{tag:'button',cls:'btn btn-default',html:''}]},{tag:'div',cls:'btn-group roo-upload-cropbox-trash',action:'trash',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-right',action:'rotate-right',cn:[{tag:'button',cls:'btn btn-default',html:''}]}],ROTATOR:[{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-left',action:'rotate-left',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-right',action:'rotate-right',cn:[{tag:'button',cls:'btn btn-default',html:''}]}]}}); +diff --git a/roojs-debug.js b/roojs-debug.js +index 5e539c7e68..d341c59730 100644 +--- a/roojs-debug.js ++++ b/roojs-debug.js +@@ -60414,7 +60414,6 @@ Roo.LayoutStateManager.prototype = { + */ + Roo.ContentPanel = function(el, config, content){ +  +-  + /* + if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory + config = el; +@@ -60798,6 +60797,14 @@ layout.addxtype({ + */ +  + addxtype : function(cfg) { ++ if(cfg.xtype.match(/^UploadCropbox$/)) { ++ ++ this.cropbox = new Roo.factory(cfg); ++ ++ this.cropbox.render(this.el); ++ ++ return this.cropbox; ++ } + // add form.. + if (cfg.xtype.match(/^Form$/)) { +  +@@ -68050,4 +68057,1795 @@ Roo.extend(Roo.XTemplate, Roo.Template, { + Roo.XTemplate.from = function(el){ + el = Roo.getDom(el); + return new Roo.XTemplate(el.value || el.innerHTML); +-}; +\ No newline at end of file ++};Roo.dialog = {}; ++/* ++* Licence: LGPL ++*/ ++ ++/** ++ * @class Roo.dialog.UploadCropbox ++ * @extends Roo.BoxComponent ++ * Dialog 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'] ++ * @cfg {Boolean} isDocument (true|false) default false ++ * @cfg {String} url action url ++ * @cfg {String} paramName default 'imageUpload' ++ * @cfg {String} method default POST ++ * @cfg {Boolean} loadMask (true|false) default true ++ * @cfg {Boolean} loadingText default 'Loading...' ++ *  ++ * @constructor ++ * Create a new UploadCropbox ++ * @param {Object} config The config object ++ */ ++ ++ Roo.dialog.UploadCropbox = function(config){ ++ console.log("Dialog UploadCropbox Constructor"); ++ Roo.dialog.UploadCropbox.superclass.constructor.call(this, config); ++  ++ this.addEvents({ ++ /** ++ * @event beforeselectfile ++ * Fire before select file ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "beforeselectfile" : true, ++ /** ++ * @event initial ++ * Fire after initEvent ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "initial" : true, ++ /** ++ * @event crop ++ * Fire after initEvent ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} data ++ */ ++ "crop" : true, ++ /** ++ * @event prepare ++ * Fire when preparing the file data ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} file ++ */ ++ "prepare" : true, ++ /** ++ * @event exception ++ * Fire when get exception ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {XMLHttpRequest} xhr ++ */ ++ "exception" : true, ++ /** ++ * @event beforeloadcanvas ++ * Fire before load the canvas ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} src ++ */ ++ "beforeloadcanvas" : true, ++ /** ++ * @event trash ++ * Fire when trash image ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "trash" : true, ++ /** ++ * @event download ++ * Fire when download the image ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "download" : true, ++ /** ++ * @event footerbuttonclick ++ * Fire when footerbuttonclick ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} type ++ */ ++ "footerbuttonclick" : true, ++ /** ++ * @event resize ++ * Fire when resize ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "resize" : true, ++ /** ++ * @event rotate ++ * Fire when rotate the image ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} pos ++ */ ++ "rotate" : true, ++ /** ++ * @event inspect ++ * Fire when inspect the file ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} file ++ */ ++ "inspect" : true, ++ /** ++ * @event upload ++ * Fire when xhr upload the file ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} data ++ */ ++ "upload" : true, ++ /** ++ * @event arrange ++ * Fire when arrange the file data ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} formData ++ */ ++ "arrange" : true, ++ /** ++ * @event loadcanvas ++ * Fire after load the canvas ++ * @param {Roo.dialog.UploadCropbox} ++ * @param {Object} imgEl ++ */ ++ "loadcanvas" : true ++ }); ++  ++ this.buttons = this.buttons || Roo.dialog.UploadCropbox.footer.STANDARD; ++}; ++ ++Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { ++  ++ emptyText : 'Click to upload image', ++ rotateNotify : 'Image is too small to rotate', ++ errorTimeout : 3000, ++ scale : 0, ++ baseScale : 1, ++ rotate : 0, ++ dragable : false, ++ pinching : false, ++ mouseX : 0, ++ mouseY : 0, ++ cropData : false, ++ minWidth : 300, ++ minHeight : 300, ++ file : false, ++ exif : {}, ++ baseRotate : 1, ++ cropType : 'image/jpeg', ++ buttons : false, ++ canvasLoaded : false, ++ isDocument : false, ++ method : 'POST', ++ paramName : 'imageUpload', ++ loadMask : true, ++ loadingText : 'Loading...', ++ maskEl : false, ++  ++ getAutoCreate : function() ++ { ++ var cfg = { ++ tag : 'div', ++ cls : 'roo-upload-cropbox', ++ cn : [ ++ { ++ tag : 'input', ++ cls : 'roo-upload-cropbox-selector', ++ type : 'file' ++ }, ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-body', ++ style : 'cursor:pointer', ++ cn : [ ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-preview' ++ }, ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-thumb' ++ }, ++ { ++ 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', ++ cn : { ++ tag : 'div', ++ cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group', ++ cn : [] ++ } ++ } ++ ] ++ }; ++  ++ return cfg; ++ }, ++  ++ onRender : function(ct, position) ++ { ++ console.log("On Render"); ++ console.log(this); ++ Roo.dialog.UploadCropbox.superclass.onRender.call(this, ct, position); ++ ++ if(this.el){ ++ if (this.el.attr('xtype')) { ++ this.el.attr('xtypex', this.el.attr('xtype')); ++ this.el.dom.removeAttribute('xtype'); ++  ++ this.initEvents(); ++ } ++ } ++ else { ++ var cfg = Roo.apply({}, this.getAutoCreate()); ++  ++ cfg.id = this.id || Roo.id(); ++  ++ if (this.cls) { ++ cfg.cls = (typeof(cfg.cls) == 'undefined' ? this.cls : cfg.cls) + ' ' + this.cls; ++ } ++  ++ if (this.style) { // fixme needs to support more complex style data. ++ cfg.style = (typeof(cfg.style) == 'undefined' ? this.style : cfg.style) + '; ' + this.style; ++ } ++  ++ this.el = ct.createChild(cfg, position); ++  ++ this.initEvents(); ++ } ++  ++ 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); ++ } ++  ++ if(this.loadMask){ ++ this.maskEl = this.el; ++ } ++ }, ++  ++ 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.selectorEl = this.el.select('.roo-upload-cropbox-selector', true).first(); ++ this.selectorEl.hide(); ++  ++ this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first(); ++ this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++  ++ this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first(); ++ this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++ this.thumbEl.hide(); ++  ++ this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first(); ++ this.notifyEl.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.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first(); ++ this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++ this.footerEl.hide(); ++  ++ this.setThumbBoxSize(); ++  ++ this.bind(); ++  ++ this.resize(); ++  ++ this.fireEvent('initial', this); ++ }, ++ ++ bind : function() ++ { ++ var _this = this; ++  ++ window.addEventListener("resize", function() { _this.resize(); } ); ++  ++ this.bodyEl.on('click', this.beforeSelectFile, this); ++  ++ if(Roo.isTouch){ ++ 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.bodyEl.on('mousedown', this.onMouseDown, this); ++ this.bodyEl.on('mousemove', this.onMouseMove, this); ++ var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel'; ++ this.bodyEl.on(mousewheel, this.onMouseWheel, this); ++ Roo.get(document).on('mouseup', this.onMouseUp, this); ++ } ++  ++ this.selectorEl.on('change', this.onFileSelected, this); ++ }, ++  ++ reset : function() ++ {  ++ 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.cropData = false; ++ this.notifyEl.dom.innerHTML = this.emptyText; ++  ++ // this.selectorEl.dom.value = ''; ++  ++ }, ++  ++ 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(); ++  ++ if(this.fireEvent('beforeselectfile', this) != false){ ++ this.selectorEl.dom.click(); ++ } ++ }, ++  ++ onFileSelected : function(e) ++ { ++ e.preventDefault(); ++  ++ if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){ ++ return; ++ } ++  ++ var file = this.selectorEl.dom.files[0]; ++  ++ if(this.fireEvent('inspect', this, file) != false){ ++ this.prepare(file); ++ } ++  ++ }, ++  ++ trash : function(e) ++ { ++ this.fireEvent('trash', this); ++ }, ++  ++ download : function(e) ++ { ++ this.fireEvent('download', this); ++ }, ++  ++ loadCanvas : function(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; ++ } ++ }, ++  ++ onLoadCanvas : function() ++ {  ++ this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width; ++ this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height; ++ ++ if(this.fireEvent('loadcanvas', this, this.imageEl) != false){ ++  ++ this.bodyEl.un('click', this.beforeSelectFile, this); ++  ++ this.notifyEl.hide(); ++ this.thumbEl.show(); ++ this.footerEl.show(); ++  ++ this.baseRotateLevel(); ++  ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ } ++  ++ this.setThumbBoxPosition(); ++  ++ this.baseScaleLevel(); ++  ++ this.draw(); ++  ++ this.resize(); ++  ++ this.canvasLoaded = true; ++  ++ } ++  ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ }, ++  ++ setCanvasPosition : function() ++ {  ++ 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); ++  ++ }, ++  ++ onMouseDown : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.dragable = true; ++ this.pinching = false; ++  ++ if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){ ++ this.dragable = false; ++ return; ++ } ++  ++ this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX(); ++ this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY(); ++  ++ }, ++  ++ onMouseMove : function(e) ++ {  ++ e.stopEvent(); ++  ++ if(!this.canvasLoaded){ ++ return; ++ } ++  ++ if (!this.dragable){ ++ return; ++ } ++  ++ var minX = Math.ceil(this.thumbEl.getLeft(true)); ++ var minY = Math.ceil(this.thumbEl.getTop(true)); ++  ++ 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(); ++  ++ x = x - this.mouseX; ++ y = y - this.mouseY; ++  ++ 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.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(); ++ }, ++  ++ onMouseUp : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.dragable = false; ++ }, ++  ++ onMouseWheel : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.startScale = this.scale; ++  ++ this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1); ++  ++ if(!this.zoomable()){ ++ this.scale = this.startScale; ++ return; ++ } ++  ++ this.draw(); ++  ++ return; ++ }, ++  ++ zoomable : function() ++ { ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ if(this.minWidth < this.minHeight){ ++ minScale = this.thumbEl.getHeight() / this.minHeight; ++ } ++  ++ var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale); ++ var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale); ++  ++ if( ++ this.isDocument && ++ (this.rotate == 0 || this.rotate == 180) &&  ++ ( ++ width > this.imageEl.OriginWidth ||  ++ height > this.imageEl.OriginHeight || ++ (width < this.minWidth && height < this.minHeight) ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ this.isDocument && ++ (this.rotate == 90 || this.rotate == 270) &&  ++ ( ++ width > this.imageEl.OriginWidth ||  ++ height > this.imageEl.OriginHeight || ++ (width < this.minHeight && height < this.minWidth) ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ !this.isDocument && ++ (this.rotate == 0 || this.rotate == 180) &&  ++ ( ++ width < this.minWidth ||  ++ width > this.imageEl.OriginWidth ||  ++ height < this.minHeight ||  ++ height > this.imageEl.OriginHeight ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ !this.isDocument && ++ (this.rotate == 90 || this.rotate == 270) &&  ++ ( ++ width < this.minHeight ||  ++ width > this.imageEl.OriginWidth ||  ++ height < this.minWidth ||  ++ height > this.imageEl.OriginHeight ++ ) ++ ){ ++ return false; ++ } ++  ++ return true; ++  ++ }, ++  ++ onRotateLeft : function(e) ++ {  ++ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){ ++  ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel()); ++ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel()); ++  ++ this.startScale = this.scale; ++  ++ while (this.getScaleLevel() < minScale){ ++  ++ this.scale = this.scale + 1; ++  ++ if(!this.zoomable()){ ++ break; ++ } ++  ++ if( ++ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() || ++ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth() ++ ){ ++ continue; ++ } ++  ++ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90; ++ ++ this.draw(); ++  ++ return; ++ } ++  ++ this.scale = this.startScale; ++  ++ this.onRotateFail(); ++  ++ return false; ++ } ++  ++ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90; ++ ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ this.setThumbBoxPosition(); ++ this.setCanvasPosition(); ++ } ++  ++ this.draw(); ++  ++ this.fireEvent('rotate', this, 'left'); ++  ++ }, ++  ++ onRotateRight : function(e) ++ { ++ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){ ++  ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel()); ++ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel()); ++  ++ this.startScale = this.scale; ++  ++ while (this.getScaleLevel() < minScale){ ++  ++ this.scale = this.scale + 1; ++  ++ if(!this.zoomable()){ ++ break; ++ } ++  ++ if( ++ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() || ++ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth() ++ ){ ++ continue; ++ } ++  ++ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90; ++ ++ this.draw(); ++  ++ return; ++ } ++  ++ this.scale = this.startScale; ++  ++ this.onRotateFail(); ++  ++ return false; ++ } ++  ++ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90; ++ ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ this.setThumbBoxPosition(); ++ this.setCanvasPosition(); ++ } ++  ++ this.draw(); ++  ++ this.fireEvent('rotate', this, 'right'); ++ }, ++  ++ 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; ++ } ++  ++ this.previewEl.appendChild(this.canvasEl); ++  ++ this.setCanvasPosition(); ++ }, ++  ++ crop : function() ++ { ++ if(!this.canvasLoaded){ ++ return; ++ } ++  ++ var imageCanvas = document.createElement("canvas"); ++  ++ var imageContext = imageCanvas.getContext("2d"); ++  ++ imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight; ++ imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight; ++  ++ var center = imageCanvas.width / 2; ++  ++ imageContext.translate(center, center); ++  ++ imageContext.rotate(this.rotate * Math.PI / 180); ++  ++ imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight); ++  ++ var canvas = document.createElement("canvas"); ++  ++ var context = canvas.getContext("2d"); ++  ++ canvas.width = this.minWidth; ++ canvas.height = this.minHeight; ++ ++ switch (this.rotate) { ++ case 0 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++ ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 90 :  ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++  ++ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0; ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 180 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++ ++ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight); ++ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0; ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 270 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++  ++ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight); ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ default :  ++ break; ++ } ++  ++ this.cropData = canvas.toDataURL(this.cropType); ++  ++ if(this.fireEvent('crop', this, this.cropData) !== false){ ++ this.process(this.file, this.cropData); ++ } ++  ++ return; ++  ++ }, ++  ++ setThumbBoxSize : function() ++ { ++ var width, height; ++  ++ if(this.isDocument && typeof(this.imageEl) != 'undefined'){ ++ width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight); ++ height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight); ++  ++ this.minWidth = width; ++ this.minHeight = height; ++  ++ if(this.rotate == 90 || this.rotate == 270){ ++ this.minWidth = height; ++ this.minHeight = width; ++ } ++ } ++  ++ height = 300; ++ width = Math.ceil(this.minWidth * height / this.minHeight); ++  ++ if(this.minWidth > this.minHeight){ ++ width = 300; ++ height = Math.ceil(this.minHeight * width / this.minWidth); ++ } ++  ++ this.thumbEl.setStyle({ ++ width : width + 'px', ++ height : height + 'px' ++ }); ++ ++ return; ++  ++ }, ++  ++ 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() ++ { ++ this.baseRotate = 1; ++  ++ if( ++ typeof(this.exif) != 'undefined' && ++ typeof(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]) != 'undefined' && ++ [1, 3, 6, 8].indexOf(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]) != -1 ++ ){ ++ this.baseRotate = this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]; ++ } ++  ++ this.rotate = Roo.dialog.UploadCropbox['Orientation'][this.baseRotate]; ++  ++ }, ++  ++ baseScaleLevel : function() ++ { ++ var width, height; ++  ++ if(this.isDocument){ ++  ++ if(this.baseRotate == 6 || this.baseRotate == 8){ ++  ++ height = this.thumbEl.getHeight(); ++ this.baseScale = height / this.imageEl.OriginWidth; ++ ++ if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){ ++ width = this.thumbEl.getWidth(); ++ this.baseScale = width / this.imageEl.OriginHeight; ++ } ++ ++ return; ++ } ++ ++ 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; ++ } ++ ++ return; ++ } ++  ++ if(this.baseRotate == 6 || this.baseRotate == 8){ ++  ++ width = this.thumbEl.getHeight(); ++ this.baseScale = width / 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; ++ } ++  ++ 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; ++ } ++  ++ } ++  ++ return; ++ }, ++  ++ getScaleLevel : function() ++ { ++ return this.baseScale * Math.pow(1.1, this.scale); ++ }, ++  ++ onTouchStart : function(e) ++ { ++ if(!this.canvasLoaded){ ++ this.beforeSelectFile(e); ++ return; ++ } ++  ++ var touches = e.browserEvent.touches; ++  ++ if(!touches){ ++ return; ++ } ++  ++ if(touches.length == 1){ ++ this.onMouseDown(e); ++ return; ++ } ++  ++ if(touches.length != 2){ ++ return; ++ } ++  ++ var coords = []; ++  ++ for(var i = 0, finger; finger = touches[i]; i++){ ++ coords.push(finger.pageX, finger.pageY); ++ } ++  ++ 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.startScale = this.scale; ++  ++ this.pinching = true; ++ this.dragable = false; ++  ++ }, ++  ++ onTouchMove : function(e) ++ { ++ if(!this.pinching && !this.dragable){ ++ return; ++ } ++  ++ var touches = e.browserEvent.touches; ++  ++ if(!touches){ ++ return; ++ } ++  ++ if(this.dragable){ ++ this.onMouseMove(e); ++ return; ++ } ++  ++ var coords = []; ++  ++ for(var i = 0, finger; finger = touches[i]; i++){ ++ coords.push(finger.pageX, finger.pageY); ++ } ++  ++ 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.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1)); ++  ++ if(!this.zoomable()){ ++ this.scale = this.startScale; ++ return; ++ } ++  ++ this.draw(); ++  ++ }, ++  ++ onTouchEnd : function(e) ++ { ++ this.pinching = false; ++ this.dragable = false; ++  ++ }, ++  ++ process : function(file, crop) ++ { ++ if(this.loadMask){ ++ this.maskEl.mask(this.loadingText); ++ } ++  ++ this.xhr = new XMLHttpRequest(); ++  ++ file.xhr = this.xhr; ++ ++ this.xhr.open(this.method, this.url, true); ++  ++ var headers = { ++ "Accept": "application/json", ++ "Cache-Control": "no-cache", ++ "X-Requested-With": "XMLHttpRequest" ++ }; ++  ++ for (var headerName in headers) { ++ var headerValue = headers[headerName]; ++ if (headerValue) { ++ this.xhr.setRequestHeader(headerName, headerValue); ++ } ++ } ++  ++ var _this = this; ++  ++ this.xhr.onload = function() ++ { ++ _this.xhrOnLoad(_this.xhr); ++ } ++  ++ this.xhr.onerror = function() ++ { ++ _this.xhrOnError(_this.xhr); ++ } ++  ++ var formData = new FormData(); ++ ++ formData.append('returnHTML', 'NO'); ++  ++ if(crop){ ++ formData.append('crop', crop); ++ } ++  ++ if(typeof(file) != 'undefined' && (typeof(file.id) == 'undefined' || file.id * 1 < 1)){ ++ formData.append(this.paramName, file, file.name); ++ } ++  ++ if(typeof(file.filename) != 'undefined'){ ++ formData.append('filename', file.filename); ++ } ++  ++ if(typeof(file.mimetype) != 'undefined'){ ++ formData.append('mimetype', file.mimetype); ++ } ++  ++ if(this.fireEvent('arrange', this, formData) != false){ ++ this.xhr.send(formData); ++ }; ++ }, ++  ++ xhrOnLoad : function(xhr) ++ { ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ if (xhr.readyState !== 4) { ++ this.fireEvent('exception', this, xhr); ++ return; ++ } ++ ++ var response = Roo.decode(xhr.responseText); ++  ++ if(!response.success){ ++ this.fireEvent('exception', this, xhr); ++ return; ++ } ++  ++ var response = Roo.decode(xhr.responseText); ++  ++ this.fireEvent('upload', this, response); ++  ++ }, ++  ++ xhrOnError : function() ++ { ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ Roo.log('xhr on error'); ++  ++ var response = Roo.decode(xhr.responseText); ++  ++ Roo.log(response); ++  ++ }, ++  ++ prepare : function(file) ++ {  ++ if(this.loadMask){ ++ this.maskEl.mask(this.loadingText); ++ } ++  ++ this.file = false; ++ this.exif = {}; ++  ++ if(typeof(file) === 'string'){ ++ this.loadCanvas(file); ++ return; ++ } ++  ++ if(!file || !this.urlAPI){ ++ return; ++ } ++  ++ this.file = file; ++ this.cropType = file.type; ++  ++ var _this = this; ++  ++ if(this.fireEvent('prepare', this, this.file) != false){ ++  ++ 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.dialog.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.dialog.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 : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-picture', ++ action : 'picture', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ], ++ DOCUMENT : [ ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-left', ++ action : 'rotate-left', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-download', ++ action : 'download', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-crop', ++ action : 'crop', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-trash', ++ action : 'trash', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ], ++ ROTATOR : [ ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-left', ++ action : 'rotate-left', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ] ++ } ++}); +diff --git a/roojs-ui-debug.js b/roojs-ui-debug.js +index 4458d38422..4cc277300f 100644 +--- a/roojs-ui-debug.js ++++ b/roojs-ui-debug.js +@@ -35922,7 +35922,6 @@ Roo.LayoutStateManager.prototype = { + */ + Roo.ContentPanel = function(el, config, content){ +  +-  + /* + if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory + config = el; +@@ -36306,6 +36305,14 @@ layout.addxtype({ + */ +  + addxtype : function(cfg) { ++ if(cfg.xtype.match(/^UploadCropbox$/)) { ++ ++ this.cropbox = new Roo.factory(cfg); ++ ++ this.cropbox.render(this.el); ++ ++ return this.cropbox; ++ } + // add form.. + if (cfg.xtype.match(/^Form$/)) { +  +@@ -43558,4 +43565,1795 @@ Roo.extend(Roo.XTemplate, Roo.Template, { + Roo.XTemplate.from = function(el){ + el = Roo.getDom(el); + return new Roo.XTemplate(el.value || el.innerHTML); +-}; +\ No newline at end of file ++};Roo.dialog = {}; ++/* ++* Licence: LGPL ++*/ ++ ++/** ++ * @class Roo.dialog.UploadCropbox ++ * @extends Roo.BoxComponent ++ * Dialog 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'] ++ * @cfg {Boolean} isDocument (true|false) default false ++ * @cfg {String} url action url ++ * @cfg {String} paramName default 'imageUpload' ++ * @cfg {String} method default POST ++ * @cfg {Boolean} loadMask (true|false) default true ++ * @cfg {Boolean} loadingText default 'Loading...' ++ *  ++ * @constructor ++ * Create a new UploadCropbox ++ * @param {Object} config The config object ++ */ ++ ++ Roo.dialog.UploadCropbox = function(config){ ++ console.log("Dialog UploadCropbox Constructor"); ++ Roo.dialog.UploadCropbox.superclass.constructor.call(this, config); ++  ++ this.addEvents({ ++ /** ++ * @event beforeselectfile ++ * Fire before select file ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "beforeselectfile" : true, ++ /** ++ * @event initial ++ * Fire after initEvent ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "initial" : true, ++ /** ++ * @event crop ++ * Fire after initEvent ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} data ++ */ ++ "crop" : true, ++ /** ++ * @event prepare ++ * Fire when preparing the file data ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} file ++ */ ++ "prepare" : true, ++ /** ++ * @event exception ++ * Fire when get exception ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {XMLHttpRequest} xhr ++ */ ++ "exception" : true, ++ /** ++ * @event beforeloadcanvas ++ * Fire before load the canvas ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} src ++ */ ++ "beforeloadcanvas" : true, ++ /** ++ * @event trash ++ * Fire when trash image ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "trash" : true, ++ /** ++ * @event download ++ * Fire when download the image ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "download" : true, ++ /** ++ * @event footerbuttonclick ++ * Fire when footerbuttonclick ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} type ++ */ ++ "footerbuttonclick" : true, ++ /** ++ * @event resize ++ * Fire when resize ++ * @param {Roo.dialog.UploadCropbox} this ++ */ ++ "resize" : true, ++ /** ++ * @event rotate ++ * Fire when rotate the image ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {String} pos ++ */ ++ "rotate" : true, ++ /** ++ * @event inspect ++ * Fire when inspect the file ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} file ++ */ ++ "inspect" : true, ++ /** ++ * @event upload ++ * Fire when xhr upload the file ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} data ++ */ ++ "upload" : true, ++ /** ++ * @event arrange ++ * Fire when arrange the file data ++ * @param {Roo.dialog.UploadCropbox} this ++ * @param {Object} formData ++ */ ++ "arrange" : true, ++ /** ++ * @event loadcanvas ++ * Fire after load the canvas ++ * @param {Roo.dialog.UploadCropbox} ++ * @param {Object} imgEl ++ */ ++ "loadcanvas" : true ++ }); ++  ++ this.buttons = this.buttons || Roo.dialog.UploadCropbox.footer.STANDARD; ++}; ++ ++Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { ++  ++ emptyText : 'Click to upload image', ++ rotateNotify : 'Image is too small to rotate', ++ errorTimeout : 3000, ++ scale : 0, ++ baseScale : 1, ++ rotate : 0, ++ dragable : false, ++ pinching : false, ++ mouseX : 0, ++ mouseY : 0, ++ cropData : false, ++ minWidth : 300, ++ minHeight : 300, ++ file : false, ++ exif : {}, ++ baseRotate : 1, ++ cropType : 'image/jpeg', ++ buttons : false, ++ canvasLoaded : false, ++ isDocument : false, ++ method : 'POST', ++ paramName : 'imageUpload', ++ loadMask : true, ++ loadingText : 'Loading...', ++ maskEl : false, ++  ++ getAutoCreate : function() ++ { ++ var cfg = { ++ tag : 'div', ++ cls : 'roo-upload-cropbox', ++ cn : [ ++ { ++ tag : 'input', ++ cls : 'roo-upload-cropbox-selector', ++ type : 'file' ++ }, ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-body', ++ style : 'cursor:pointer', ++ cn : [ ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-preview' ++ }, ++ { ++ tag : 'div', ++ cls : 'roo-upload-cropbox-thumb' ++ }, ++ { ++ 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', ++ cn : { ++ tag : 'div', ++ cls : 'btn-group btn-group-justified roo-upload-cropbox-btn-group', ++ cn : [] ++ } ++ } ++ ] ++ }; ++  ++ return cfg; ++ }, ++  ++ onRender : function(ct, position) ++ { ++ console.log("On Render"); ++ console.log(this); ++ Roo.dialog.UploadCropbox.superclass.onRender.call(this, ct, position); ++ ++ if(this.el){ ++ if (this.el.attr('xtype')) { ++ this.el.attr('xtypex', this.el.attr('xtype')); ++ this.el.dom.removeAttribute('xtype'); ++  ++ this.initEvents(); ++ } ++ } ++ else { ++ var cfg = Roo.apply({}, this.getAutoCreate()); ++  ++ cfg.id = this.id || Roo.id(); ++  ++ if (this.cls) { ++ cfg.cls = (typeof(cfg.cls) == 'undefined' ? this.cls : cfg.cls) + ' ' + this.cls; ++ } ++  ++ if (this.style) { // fixme needs to support more complex style data. ++ cfg.style = (typeof(cfg.style) == 'undefined' ? this.style : cfg.style) + '; ' + this.style; ++ } ++  ++ this.el = ct.createChild(cfg, position); ++  ++ this.initEvents(); ++ } ++  ++ 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); ++ } ++  ++ if(this.loadMask){ ++ this.maskEl = this.el; ++ } ++ }, ++  ++ 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.selectorEl = this.el.select('.roo-upload-cropbox-selector', true).first(); ++ this.selectorEl.hide(); ++  ++ this.previewEl = this.el.select('.roo-upload-cropbox-preview', true).first(); ++ this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++  ++ this.thumbEl = this.el.select('.roo-upload-cropbox-thumb', true).first(); ++ this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++ this.thumbEl.hide(); ++  ++ this.notifyEl = this.el.select('.roo-upload-cropbox-empty-notify', true).first(); ++ this.notifyEl.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.footerEl = this.el.select('.roo-upload-cropbox-footer', true).first(); ++ this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block'; ++ this.footerEl.hide(); ++  ++ this.setThumbBoxSize(); ++  ++ this.bind(); ++  ++ this.resize(); ++  ++ this.fireEvent('initial', this); ++ }, ++ ++ bind : function() ++ { ++ var _this = this; ++  ++ window.addEventListener("resize", function() { _this.resize(); } ); ++  ++ this.bodyEl.on('click', this.beforeSelectFile, this); ++  ++ if(Roo.isTouch){ ++ 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.bodyEl.on('mousedown', this.onMouseDown, this); ++ this.bodyEl.on('mousemove', this.onMouseMove, this); ++ var mousewheel = (/Firefox/i.test(navigator.userAgent))? 'DOMMouseScroll' : 'mousewheel'; ++ this.bodyEl.on(mousewheel, this.onMouseWheel, this); ++ Roo.get(document).on('mouseup', this.onMouseUp, this); ++ } ++  ++ this.selectorEl.on('change', this.onFileSelected, this); ++ }, ++  ++ reset : function() ++ {  ++ 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.cropData = false; ++ this.notifyEl.dom.innerHTML = this.emptyText; ++  ++ // this.selectorEl.dom.value = ''; ++  ++ }, ++  ++ 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(); ++  ++ if(this.fireEvent('beforeselectfile', this) != false){ ++ this.selectorEl.dom.click(); ++ } ++ }, ++  ++ onFileSelected : function(e) ++ { ++ e.preventDefault(); ++  ++ if(typeof(this.selectorEl.dom.files) == 'undefined' || !this.selectorEl.dom.files.length){ ++ return; ++ } ++  ++ var file = this.selectorEl.dom.files[0]; ++  ++ if(this.fireEvent('inspect', this, file) != false){ ++ this.prepare(file); ++ } ++  ++ }, ++  ++ trash : function(e) ++ { ++ this.fireEvent('trash', this); ++ }, ++  ++ download : function(e) ++ { ++ this.fireEvent('download', this); ++ }, ++  ++ loadCanvas : function(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; ++ } ++ }, ++  ++ onLoadCanvas : function() ++ {  ++ this.imageEl.OriginWidth = this.imageEl.naturalWidth || this.imageEl.width; ++ this.imageEl.OriginHeight = this.imageEl.naturalHeight || this.imageEl.height; ++ ++ if(this.fireEvent('loadcanvas', this, this.imageEl) != false){ ++  ++ this.bodyEl.un('click', this.beforeSelectFile, this); ++  ++ this.notifyEl.hide(); ++ this.thumbEl.show(); ++ this.footerEl.show(); ++  ++ this.baseRotateLevel(); ++  ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ } ++  ++ this.setThumbBoxPosition(); ++  ++ this.baseScaleLevel(); ++  ++ this.draw(); ++  ++ this.resize(); ++  ++ this.canvasLoaded = true; ++  ++ } ++  ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ }, ++  ++ setCanvasPosition : function() ++ {  ++ 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); ++  ++ }, ++  ++ onMouseDown : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.dragable = true; ++ this.pinching = false; ++  ++ if(this.isDocument && (this.canvasEl.width < this.thumbEl.getWidth() || this.canvasEl.height < this.thumbEl.getHeight())){ ++ this.dragable = false; ++ return; ++ } ++  ++ this.mouseX = Roo.isTouch ? e.browserEvent.touches[0].pageX : e.getPageX(); ++ this.mouseY = Roo.isTouch ? e.browserEvent.touches[0].pageY : e.getPageY(); ++  ++ }, ++  ++ onMouseMove : function(e) ++ {  ++ e.stopEvent(); ++  ++ if(!this.canvasLoaded){ ++ return; ++ } ++  ++ if (!this.dragable){ ++ return; ++ } ++  ++ var minX = Math.ceil(this.thumbEl.getLeft(true)); ++ var minY = Math.ceil(this.thumbEl.getTop(true)); ++  ++ 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(); ++  ++ x = x - this.mouseX; ++ y = y - this.mouseY; ++  ++ 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.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(); ++ }, ++  ++ onMouseUp : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.dragable = false; ++ }, ++  ++ onMouseWheel : function(e) ++ {  ++ e.stopEvent(); ++  ++ this.startScale = this.scale; ++  ++ this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1); ++  ++ if(!this.zoomable()){ ++ this.scale = this.startScale; ++ return; ++ } ++  ++ this.draw(); ++  ++ return; ++ }, ++  ++ zoomable : function() ++ { ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ if(this.minWidth < this.minHeight){ ++ minScale = this.thumbEl.getHeight() / this.minHeight; ++ } ++  ++ var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale); ++ var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale); ++  ++ if( ++ this.isDocument && ++ (this.rotate == 0 || this.rotate == 180) &&  ++ ( ++ width > this.imageEl.OriginWidth ||  ++ height > this.imageEl.OriginHeight || ++ (width < this.minWidth && height < this.minHeight) ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ this.isDocument && ++ (this.rotate == 90 || this.rotate == 270) &&  ++ ( ++ width > this.imageEl.OriginWidth ||  ++ height > this.imageEl.OriginHeight || ++ (width < this.minHeight && height < this.minWidth) ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ !this.isDocument && ++ (this.rotate == 0 || this.rotate == 180) &&  ++ ( ++ width < this.minWidth ||  ++ width > this.imageEl.OriginWidth ||  ++ height < this.minHeight ||  ++ height > this.imageEl.OriginHeight ++ ) ++ ){ ++ return false; ++ } ++  ++ if( ++ !this.isDocument && ++ (this.rotate == 90 || this.rotate == 270) &&  ++ ( ++ width < this.minHeight ||  ++ width > this.imageEl.OriginWidth ||  ++ height < this.minWidth ||  ++ height > this.imageEl.OriginHeight ++ ) ++ ){ ++ return false; ++ } ++  ++ return true; ++  ++ }, ++  ++ onRotateLeft : function(e) ++ {  ++ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){ ++  ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel()); ++ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel()); ++  ++ this.startScale = this.scale; ++  ++ while (this.getScaleLevel() < minScale){ ++  ++ this.scale = this.scale + 1; ++  ++ if(!this.zoomable()){ ++ break; ++ } ++  ++ if( ++ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() || ++ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth() ++ ){ ++ continue; ++ } ++  ++ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90; ++ ++ this.draw(); ++  ++ return; ++ } ++  ++ this.scale = this.startScale; ++  ++ this.onRotateFail(); ++  ++ return false; ++ } ++  ++ this.rotate = (this.rotate < 90) ? 270 : this.rotate - 90; ++ ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ this.setThumbBoxPosition(); ++ this.setCanvasPosition(); ++ } ++  ++ this.draw(); ++  ++ this.fireEvent('rotate', this, 'left'); ++  ++ }, ++  ++ onRotateRight : function(e) ++ { ++ if(!this.isDocument && (this.canvasEl.height < this.thumbEl.getWidth() || this.canvasEl.width < this.thumbEl.getHeight())){ ++  ++ var minScale = this.thumbEl.getWidth() / this.minWidth; ++  ++ var bw = Math.ceil(this.canvasEl.width / this.getScaleLevel()); ++ var bh = Math.ceil(this.canvasEl.height / this.getScaleLevel()); ++  ++ this.startScale = this.scale; ++  ++ while (this.getScaleLevel() < minScale){ ++  ++ this.scale = this.scale + 1; ++  ++ if(!this.zoomable()){ ++ break; ++ } ++  ++ if( ++ Math.ceil(bw * this.getScaleLevel()) < this.thumbEl.getHeight() || ++ Math.ceil(bh * this.getScaleLevel()) < this.thumbEl.getWidth() ++ ){ ++ continue; ++ } ++  ++ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90; ++ ++ this.draw(); ++  ++ return; ++ } ++  ++ this.scale = this.startScale; ++  ++ this.onRotateFail(); ++  ++ return false; ++ } ++  ++ this.rotate = (this.rotate > 180) ? 0 : this.rotate + 90; ++ ++ if(this.isDocument){ ++ this.setThumbBoxSize(); ++ this.setThumbBoxPosition(); ++ this.setCanvasPosition(); ++ } ++  ++ this.draw(); ++  ++ this.fireEvent('rotate', this, 'right'); ++ }, ++  ++ 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; ++ } ++  ++ this.previewEl.appendChild(this.canvasEl); ++  ++ this.setCanvasPosition(); ++ }, ++  ++ crop : function() ++ { ++ if(!this.canvasLoaded){ ++ return; ++ } ++  ++ var imageCanvas = document.createElement("canvas"); ++  ++ var imageContext = imageCanvas.getContext("2d"); ++  ++ imageCanvas.width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight; ++ imageCanvas.height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? this.imageEl.OriginWidth : this.imageEl.OriginHeight; ++  ++ var center = imageCanvas.width / 2; ++  ++ imageContext.translate(center, center); ++  ++ imageContext.rotate(this.rotate * Math.PI / 180); ++  ++ imageContext.drawImage(this.imageEl, 0, 0, this.imageEl.OriginWidth, this.imageEl.OriginHeight, center * -1, center * -1, this.imageEl.OriginWidth, this.imageEl.OriginHeight); ++  ++ var canvas = document.createElement("canvas"); ++  ++ var context = canvas.getContext("2d"); ++  ++ canvas.width = this.minWidth; ++ canvas.height = this.minHeight; ++ ++ switch (this.rotate) { ++ case 0 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++ ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 90 :  ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++  ++ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0; ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 180 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++ ++ sx += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight); ++ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight) : 0; ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ case 270 : ++  ++ var width = (this.thumbEl.getWidth() / this.getScaleLevel() > this.imageEl.OriginHeight) ? this.imageEl.OriginHeight : (this.thumbEl.getWidth() / this.getScaleLevel()); ++ var height = (this.thumbEl.getHeight() / this.getScaleLevel() > this.imageEl.OriginWidth) ? this.imageEl.OriginWidth : (this.thumbEl.getHeight() / this.getScaleLevel()); ++  ++ var x = (this.thumbEl.getLeft(true) > this.previewEl.getLeft(true)) ? 0 : ((this.previewEl.getLeft(true) - this.thumbEl.getLeft(true)) / this.getScaleLevel()); ++ var y = (this.thumbEl.getTop(true) > this.previewEl.getTop(true)) ? 0 : ((this.previewEl.getTop(true) - this.thumbEl.getTop(true)) / this.getScaleLevel()); ++  ++ var targetWidth = this.minWidth - 2 * x; ++ var targetHeight = this.minHeight - 2 * y; ++  ++ var scale = 1; ++  ++ if((x == 0 && y == 0) || (x == 0 && y > 0)){ ++ scale = targetWidth / width; ++ } ++  ++ if(x > 0 && y == 0){ ++ scale = targetHeight / height; ++ } ++  ++ if(x > 0 && y > 0){ ++ scale = targetWidth / width; ++  ++ if(width < height){ ++ scale = targetHeight / height; ++ } ++ } ++  ++ context.scale(scale, scale); ++  ++ var sx = Math.min(this.canvasEl.width - this.thumbEl.getWidth(), this.thumbEl.getLeft(true) - this.previewEl.getLeft(true)); ++ var sy = Math.min(this.canvasEl.height - this.thumbEl.getHeight(), this.thumbEl.getTop(true) - this.previewEl.getTop(true)); ++ ++ sx = sx < 0 ? 0 : (sx / this.getScaleLevel()); ++ sy = sy < 0 ? 0 : (sy / this.getScaleLevel()); ++  ++ sy += (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? 0 : Math.abs(this.imageEl.OriginWidth - this.imageEl.OriginHeight); ++  ++ context.drawImage(imageCanvas, sx, sy, width, height, x, y, width, height); ++  ++ break; ++ default :  ++ break; ++ } ++  ++ this.cropData = canvas.toDataURL(this.cropType); ++  ++ if(this.fireEvent('crop', this, this.cropData) !== false){ ++ this.process(this.file, this.cropData); ++ } ++  ++ return; ++  ++ }, ++  ++ setThumbBoxSize : function() ++ { ++ var width, height; ++  ++ if(this.isDocument && typeof(this.imageEl) != 'undefined'){ ++ width = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.max(this.minWidth, this.minHeight) : Math.min(this.minWidth, this.minHeight); ++ height = (this.imageEl.OriginWidth > this.imageEl.OriginHeight) ? Math.min(this.minWidth, this.minHeight) : Math.max(this.minWidth, this.minHeight); ++  ++ this.minWidth = width; ++ this.minHeight = height; ++  ++ if(this.rotate == 90 || this.rotate == 270){ ++ this.minWidth = height; ++ this.minHeight = width; ++ } ++ } ++  ++ height = 300; ++ width = Math.ceil(this.minWidth * height / this.minHeight); ++  ++ if(this.minWidth > this.minHeight){ ++ width = 300; ++ height = Math.ceil(this.minHeight * width / this.minWidth); ++ } ++  ++ this.thumbEl.setStyle({ ++ width : width + 'px', ++ height : height + 'px' ++ }); ++ ++ return; ++  ++ }, ++  ++ 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() ++ { ++ this.baseRotate = 1; ++  ++ if( ++ typeof(this.exif) != 'undefined' && ++ typeof(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]) != 'undefined' && ++ [1, 3, 6, 8].indexOf(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]) != -1 ++ ){ ++ this.baseRotate = this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]; ++ } ++  ++ this.rotate = Roo.dialog.UploadCropbox['Orientation'][this.baseRotate]; ++  ++ }, ++  ++ baseScaleLevel : function() ++ { ++ var width, height; ++  ++ if(this.isDocument){ ++  ++ if(this.baseRotate == 6 || this.baseRotate == 8){ ++  ++ height = this.thumbEl.getHeight(); ++ this.baseScale = height / this.imageEl.OriginWidth; ++ ++ if(this.imageEl.OriginHeight * this.baseScale > this.thumbEl.getWidth()){ ++ width = this.thumbEl.getWidth(); ++ this.baseScale = width / this.imageEl.OriginHeight; ++ } ++ ++ return; ++ } ++ ++ 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; ++ } ++ ++ return; ++ } ++  ++ if(this.baseRotate == 6 || this.baseRotate == 8){ ++  ++ width = this.thumbEl.getHeight(); ++ this.baseScale = width / 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; ++ } ++  ++ 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; ++ } ++  ++ } ++  ++ return; ++ }, ++  ++ getScaleLevel : function() ++ { ++ return this.baseScale * Math.pow(1.1, this.scale); ++ }, ++  ++ onTouchStart : function(e) ++ { ++ if(!this.canvasLoaded){ ++ this.beforeSelectFile(e); ++ return; ++ } ++  ++ var touches = e.browserEvent.touches; ++  ++ if(!touches){ ++ return; ++ } ++  ++ if(touches.length == 1){ ++ this.onMouseDown(e); ++ return; ++ } ++  ++ if(touches.length != 2){ ++ return; ++ } ++  ++ var coords = []; ++  ++ for(var i = 0, finger; finger = touches[i]; i++){ ++ coords.push(finger.pageX, finger.pageY); ++ } ++  ++ 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.startScale = this.scale; ++  ++ this.pinching = true; ++ this.dragable = false; ++  ++ }, ++  ++ onTouchMove : function(e) ++ { ++ if(!this.pinching && !this.dragable){ ++ return; ++ } ++  ++ var touches = e.browserEvent.touches; ++  ++ if(!touches){ ++ return; ++ } ++  ++ if(this.dragable){ ++ this.onMouseMove(e); ++ return; ++ } ++  ++ var coords = []; ++  ++ for(var i = 0, finger; finger = touches[i]; i++){ ++ coords.push(finger.pageX, finger.pageY); ++ } ++  ++ 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.scale = this.startScale + Math.floor(Math.log(this.endDistance / this.startDistance) / Math.log(1.1)); ++  ++ if(!this.zoomable()){ ++ this.scale = this.startScale; ++ return; ++ } ++  ++ this.draw(); ++  ++ }, ++  ++ onTouchEnd : function(e) ++ { ++ this.pinching = false; ++ this.dragable = false; ++  ++ }, ++  ++ process : function(file, crop) ++ { ++ if(this.loadMask){ ++ this.maskEl.mask(this.loadingText); ++ } ++  ++ this.xhr = new XMLHttpRequest(); ++  ++ file.xhr = this.xhr; ++ ++ this.xhr.open(this.method, this.url, true); ++  ++ var headers = { ++ "Accept": "application/json", ++ "Cache-Control": "no-cache", ++ "X-Requested-With": "XMLHttpRequest" ++ }; ++  ++ for (var headerName in headers) { ++ var headerValue = headers[headerName]; ++ if (headerValue) { ++ this.xhr.setRequestHeader(headerName, headerValue); ++ } ++ } ++  ++ var _this = this; ++  ++ this.xhr.onload = function() ++ { ++ _this.xhrOnLoad(_this.xhr); ++ } ++  ++ this.xhr.onerror = function() ++ { ++ _this.xhrOnError(_this.xhr); ++ } ++  ++ var formData = new FormData(); ++ ++ formData.append('returnHTML', 'NO'); ++  ++ if(crop){ ++ formData.append('crop', crop); ++ } ++  ++ if(typeof(file) != 'undefined' && (typeof(file.id) == 'undefined' || file.id * 1 < 1)){ ++ formData.append(this.paramName, file, file.name); ++ } ++  ++ if(typeof(file.filename) != 'undefined'){ ++ formData.append('filename', file.filename); ++ } ++  ++ if(typeof(file.mimetype) != 'undefined'){ ++ formData.append('mimetype', file.mimetype); ++ } ++  ++ if(this.fireEvent('arrange', this, formData) != false){ ++ this.xhr.send(formData); ++ }; ++ }, ++  ++ xhrOnLoad : function(xhr) ++ { ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ if (xhr.readyState !== 4) { ++ this.fireEvent('exception', this, xhr); ++ return; ++ } ++ ++ var response = Roo.decode(xhr.responseText); ++  ++ if(!response.success){ ++ this.fireEvent('exception', this, xhr); ++ return; ++ } ++  ++ var response = Roo.decode(xhr.responseText); ++  ++ this.fireEvent('upload', this, response); ++  ++ }, ++  ++ xhrOnError : function() ++ { ++ if(this.loadMask){ ++ this.maskEl.unmask(); ++ } ++  ++ Roo.log('xhr on error'); ++  ++ var response = Roo.decode(xhr.responseText); ++  ++ Roo.log(response); ++  ++ }, ++  ++ prepare : function(file) ++ {  ++ if(this.loadMask){ ++ this.maskEl.mask(this.loadingText); ++ } ++  ++ this.file = false; ++ this.exif = {}; ++  ++ if(typeof(file) === 'string'){ ++ this.loadCanvas(file); ++ return; ++ } ++  ++ if(!file || !this.urlAPI){ ++ return; ++ } ++  ++ this.file = file; ++ this.cropType = file.type; ++  ++ var _this = this; ++  ++ if(this.fireEvent('prepare', this, this.file) != false){ ++  ++ 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.dialog.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.dialog.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 : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-picture', ++ action : 'picture', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ], ++ DOCUMENT : [ ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-left', ++ action : 'rotate-left', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-download', ++ action : 'download', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-crop', ++ action : 'crop', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-trash', ++ action : 'trash', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ], ++ ROTATOR : [ ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-left', ++ action : 'rotate-left', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ }, ++ { ++ tag : 'div', ++ cls : 'btn-group roo-upload-cropbox-rotate-right', ++ action : 'rotate-right', ++ cn : [ ++ { ++ tag : 'button', ++ cls : 'btn btn-default', ++ html : '' ++ } ++ ] ++ } ++ ] ++ } ++}); +diff --git a/roojs-ui.js b/roojs-ui.js +index 98443d0ddf..0cc67d83a4 100644 +--- a/roojs-ui.js ++++ b/roojs-ui.js +@@ -1598,9 +1598,9 @@ return this.el.getUpdateManager();},_handleRefresh:function(A,B,C){if(!C||!this. + te.setWidth(A);}if(this.adjustments){A+=this.adjustments[0];B+=this.adjustments[1];}return {"width":A,"height":B};},setSize:function(A,B){if(this.fitToFrame&&!this.ignoreResize(A,B)){if(this.fitContainer&&this.resizeEl!=this.el){this.el.setSize(A,B);}var C=this.adjustForComponents(A,B); + this.resizeEl.setSize(this.autoWidth?"auto":C.width,this.autoHeight?"auto":C.height);this.fireEvent('resize',this,C.width,C.height);}},getTitle:function(){return this.title;},setTitle:function(A){this.title=A;if(this.region){this.region.updatePanelTitle(this,A); + }},isClosable:function(){return this.closable;},beforeSlide:function(){this.el.clip();this.resizeEl.clip();},afterSlide:function(){this.el.unclip();this.resizeEl.unclip();},refresh:function(){if(this.refreshDelegate){this.loaded=false;this.refreshDelegate(); +-}},destroy:function(){this.el.removeAllListeners();var A=document.createElement("span");A.appendChild(this.el.dom);A.innerHTML="";this.el.remove();this.el=null;},form:false,view:false,addxtype:function(A){if(A.xtype.match(/^Form$/)){var el;el=this.el.createChild(); +-this.form=new Roo.form.Form(A);if(this.form.allItems.length){this.form.render(el.dom);}return this.form;}if(['View','JsonView','DatePicker'].indexOf(A.xtype)>-1){A.el=this.el.appendChild(document.createElement("div"));var B=new Roo.factory(A);B.render&&B.render(false,''); +-this.view=B;return B;}return false;}}); ++}},destroy:function(){this.el.removeAllListeners();var A=document.createElement("span");A.appendChild(this.el.dom);A.innerHTML="";this.el.remove();this.el=null;},form:false,view:false,addxtype:function(A){if(A.xtype.match(/^UploadCropbox$/)){this.cropbox=new Roo.factory(A); ++this.cropbox.render(this.el);return this.cropbox;}if(A.xtype.match(/^Form$/)){var el;el=this.el.createChild();this.form=new Roo.form.Form(A);if(this.form.allItems.length){this.form.render(el.dom);}return this.form;}if(['View','JsonView','DatePicker'].indexOf(A.xtype)>-1){A.el=this.el.appendChild(document.createElement("div")); ++var B=new Roo.factory(A);B.render&&B.render(false,'');this.view=B;return B;}return false;}}); + // Roo/GridPanel.js + Roo.GridPanel=function(A,B){if(typeof(A.grid)!='undefined'){B=A;A=B.grid;}this.wrapper=Roo.DomHelper.append(document.body,{tag:"div",cls:"x-layout-grid-wrapper x-layout-inactive-content"},true);this.wrapper.dom.appendChild(A.getGridEl().dom);Roo.GridPanel.superclass.constructor.call(this,this.wrapper,B); + if(this.toolbar){this.toolbar.el.insertBefore(this.wrapper.dom.firstChild);}if(this.footer&&!this.footer.el&&this.footer.xtype){this.footer.container=this.grid.getView().getFooterPanel(true);this.footer.dataSource=this.grid.dataSource;this.footer=Roo.factory(this.footer,Roo); +@@ -1929,3 +1929,103 @@ F.push("(typeof("+G+") == 'undefined')");});var H='(('+F.join(" || ")+") ? undef + }return "'"+A+H+C+")"+A+"'";};var B;if(Roo.isGecko){B="tpl.compiled = function(values, parent){ with(values) { return '"+tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn)+"';};};";}else{B=["tpl.compiled = function(values, parent){ with (values) { return ['"]; + B.push(tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re,fn));B.push("'].join('');};};");B=B.join('');}Roo.debug&&Roo.log(B.replace(/\\n/,'\n'));eval(B);return this;},applyTemplate:function(A){return this.master.compiled.call(this,A,{} + );},apply:function(){return this.applyTemplate.apply(this,arguments);}});Roo.XTemplate.from=function(el){el=Roo.getDom(el);return new Roo.XTemplate(el.value||el.innerHTML);}; ++// Roo/dialog/namespace.js ++Roo.dialog={}; ++// Roo/dialog/UploadCropbox.js ++Roo.dialog.UploadCropbox=function(A){console.log("Dialog UploadCropbox Constructor");Roo.dialog.UploadCropbox.superclass.constructor.call(this,A);this.addEvents({"beforeselectfile":true,"initial":true,"crop":true,"prepare":true,"exception":true,"beforeloadcanvas":true,"trash":true,"download":true,"footerbuttonclick":true,"resize":true,"rotate":true,"inspect":true,"upload":true,"arrange":true,"loadcanvas":true} ++);this.buttons=this.buttons||Roo.dialog.UploadCropbox.footer.STANDARD;};Roo.extend(Roo.dialog.UploadCropbox,Roo.Component,{emptyText:'Click to upload image',rotateNotify:'Image is too small to rotate',errorTimeout:3000,scale:0,baseScale:1,rotate:0,dragable:false,pinching:false,mouseX:0,mouseY:0,cropData:false,minWidth:300,minHeight:300,file:false,exif:{} ++,baseRotate:1,cropType:'image/jpeg',buttons:false,canvasLoaded:false,isDocument:false,method:'POST',paramName:'imageUpload',loadMask:true,loadingText:'Loading...',maskEl:false,getAutoCreate:function(){var A={tag:'div',cls:'roo-upload-cropbox',cn:[{tag:'input',cls:'roo-upload-cropbox-selector',type:'file'} ++,{tag:'div',cls:'roo-upload-cropbox-body',style:'cursor:pointer',cn:[{tag:'div',cls:'roo-upload-cropbox-preview'},{tag:'div',cls:'roo-upload-cropbox-thumb'},{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',cn:{tag:'div',cls:'btn-group btn-group-justified roo-upload-cropbox-btn-group',cn:[]}}]};return A;},onRender:function(ct,A){console.log("On Render");console.log(this);Roo.dialog.UploadCropbox.superclass.onRender.call(this,ct,A); ++if(this.el){if(this.el.attr('xtype')){this.el.attr('xtypex',this.el.attr('xtype'));this.el.dom.removeAttribute('xtype');this.initEvents();}}else{var B=Roo.apply({},this.getAutoCreate());B.id=this.id||Roo.id();if(this.cls){B.cls=(typeof(B.cls)=='undefined'?this.cls:B.cls)+' '+this.cls; ++}if(this.style){B.style=(typeof(B.style)=='undefined'?this.style:B.style)+'; '+this.style;}this.el=ct.createChild(B,A);this.initEvents();}if(this.buttons.length){Roo.each(this.buttons,function(bb){var C=this.el.select('.roo-upload-cropbox-footer div.roo-upload-cropbox-btn-group').first().createChild(bb); ++C.on('click',this.onFooterButtonClick.createDelegate(this,[bb.action],true));},this);}if(this.loadMask){this.maskEl=this.el;}},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.selectorEl=this.el.select('.roo-upload-cropbox-selector',true).first();this.selectorEl.hide();this.previewEl=this.el.select('.roo-upload-cropbox-preview',true).first(); ++this.previewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.thumbEl=this.el.select('.roo-upload-cropbox-thumb',true).first();this.thumbEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.thumbEl.hide();this.notifyEl=this.el.select('.roo-upload-cropbox-empty-notify',true).first(); ++this.notifyEl.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.footerEl=this.el.select('.roo-upload-cropbox-footer',true).first(); ++this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.footerEl.hide();this.setThumbBoxSize();this.bind();this.resize();this.fireEvent('initial',this);},bind:function(){var A=this;window.addEventListener("resize",function(){A.resize(); ++});this.bodyEl.on('click',this.beforeSelectFile,this);if(Roo.isTouch){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.bodyEl.on('mousedown',this.onMouseDown,this); ++this.bodyEl.on('mousemove',this.onMouseMove,this);var B=(/Firefox/i.test(navigator.userAgent))?'DOMMouseScroll':'mousewheel';this.bodyEl.on(B,this.onMouseWheel,this);Roo.get(document).on('mouseup',this.onMouseUp,this);}this.selectorEl.on('change',this.onFileSelected,this); ++},reset:function(){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.cropData=false;this.notifyEl.dom.innerHTML=this.emptyText;},resize:function(){if(this.fireEvent('resize',this)!=false){this.setThumbBoxPosition(); ++this.setCanvasPosition();}},onFooterButtonClick:function(e,el,o,A){switch(A){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,A);},beforeSelectFile:function(e){e.preventDefault();if(this.fireEvent('beforeselectfile',this)!=false){this.selectorEl.dom.click();}},onFileSelected:function(e){e.preventDefault(); ++if(typeof(this.selectorEl.dom.files)=='undefined'||!this.selectorEl.dom.files.length){return;}var A=this.selectorEl.dom.files[0];if(this.fireEvent('inspect',this,A)!=false){this.prepare(A);}},trash:function(e){this.fireEvent('trash',this);},download:function(e){this.fireEvent('download',this); ++},loadCanvas:function(A){if(this.fireEvent('beforeloadcanvas',this,A)!=false){this.reset();this.imageEl=document.createElement('img');var B=this;this.imageEl.addEventListener("load",function(){B.onLoadCanvas();});this.imageEl.src=A;}},onLoadCanvas:function(){this.imageEl.OriginWidth=this.imageEl.naturalWidth||this.imageEl.width; ++this.imageEl.OriginHeight=this.imageEl.naturalHeight||this.imageEl.height;if(this.fireEvent('loadcanvas',this,this.imageEl)!=false){this.bodyEl.un('click',this.beforeSelectFile,this);this.notifyEl.hide();this.thumbEl.show();this.footerEl.show();this.baseRotateLevel(); ++if(this.isDocument){this.setThumbBoxSize();}this.setThumbBoxPosition();this.baseScaleLevel();this.draw();this.resize();this.canvasLoaded=true;}if(this.loadMask){this.maskEl.unmask();}},setCanvasPosition:function(){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);},onMouseDown:function(e){e.stopEvent();this.dragable=true;this.pinching=false;if(this.isDocument&&(this.canvasEl.widthE)?C:E);F=(BF)?D:F);this.previewEl.setLeft(E);this.previewEl.setTop(F);this.mouseX=Roo.isTouch?e.browserEvent.touches[0].pageX:e.getPageX(); ++this.mouseY=Roo.isTouch?e.browserEvent.touches[0].pageY:e.getPageY();},onMouseUp:function(e){e.stopEvent();this.dragable=false;},onMouseWheel:function(e){e.stopEvent();this.startScale=this.scale;this.scale=(e.getWheelDelta()==1)?(this.scale+1):(this.scale-1); ++if(!this.zoomable()){this.scale=this.startScale;return;}this.draw();return;},zoomable:function(){var A=this.thumbEl.getWidth()/this.minWidth;if(this.minWidththis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false;}if(!this.isDocument&&(this.rotate==90||this.rotate==270)&&(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false; ++}return true;},onRotateLeft:function(e){if(!this.isDocument&&(this.canvasEl.height180)?0:this.rotate+90;this.draw();return;}this.scale=this.startScale;this.onRotateFail();return false;}this.rotate=(this.rotate>180)?0:this.rotate+90;if(this.isDocument){this.setThumbBoxSize();this.setThumbBoxPosition();this.setCanvasPosition(); ++}this.draw();this.fireEvent('rotate',this,'right');},onRotateFail:function(){this.errorEl.show(true);var A=this;(function(){A.errorEl.hide(true);}).defer(this.errorTimeout);},draw:function(){this.previewEl.dom.innerHTML='';var A=document.createElement("canvas"); ++var B=A.getContext("2d");A.width=this.imageEl.OriginWidth*this.getScaleLevel();A.height=this.imageEl.OriginWidth*this.getScaleLevel();var C=this.imageEl.OriginWidth/2;if(this.imageEl.OriginWidththis.imageEl.OriginHeight){this.contextEl.drawImage(A,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(A,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(A,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(A,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(A,0,0,this.canvasEl.width,this.canvasEl.height,0,0,this.canvasEl.width,this.canvasEl.height); ++break;}this.contextEl.drawImage(A,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;}this.previewEl.appendChild(this.canvasEl);this.setCanvasPosition(); ++},crop:function(){if(!this.canvasLoaded){return;}var A=document.createElement("canvas");var B=A.getContext("2d");A.width=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?this.imageEl.OriginWidth:this.imageEl.OriginHeight;A.height=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?this.imageEl.OriginWidth:this.imageEl.OriginHeight; ++var C=A.width/2;B.translate(C,C);B.rotate(this.rotate*Math.PI/180);B.drawImage(this.imageEl,0,0,this.imageEl.OriginWidth,this.imageEl.OriginHeight,C*-1,C*-1,this.imageEl.OriginWidth,this.imageEl.OriginHeight);var D=document.createElement("canvas");var E=D.getContext("2d"); ++D.width=this.minWidth;D.height=this.minHeight;switch(this.rotate){case 0:var F=(this.thumbEl.getWidth()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getWidth()/this.getScaleLevel());var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getHeight()/this.getScaleLevel()); ++var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel());var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel()); ++var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G;}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getWidth()/this.getScaleLevel()); ++var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getHeight()/this.getScaleLevel());var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel()); ++var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel());var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G; ++}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight):0;E.drawImage(A,sx,sy,F,G,x,y,F,G);break;case 180:var F=(this.thumbEl.getWidth()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getWidth()/this.getScaleLevel()); ++var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getHeight()/this.getScaleLevel());var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel()); ++var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel());var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G; ++}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?0:Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight);sy+=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight):0; ++E.drawImage(A,sx,sy,F,G,x,y,F,G);break;case 270:var F=(this.thumbEl.getWidth()/this.getScaleLevel()>this.imageEl.OriginHeight)?this.imageEl.OriginHeight:(this.thumbEl.getWidth()/this.getScaleLevel());var G=(this.thumbEl.getHeight()/this.getScaleLevel()>this.imageEl.OriginWidth)?this.imageEl.OriginWidth:(this.thumbEl.getHeight()/this.getScaleLevel()); ++var x=(this.thumbEl.getLeft(true)>this.previewEl.getLeft(true))?0:((this.previewEl.getLeft(true)-this.thumbEl.getLeft(true))/this.getScaleLevel());var y=(this.thumbEl.getTop(true)>this.previewEl.getTop(true))?0:((this.previewEl.getTop(true)-this.thumbEl.getTop(true))/this.getScaleLevel()); ++var H=this.minWidth-2*x;var I=this.minHeight-2*y;var J=1;if((x==0&&y==0)||(x==0&&y>0)){J=H/F;}if(x>0&&y==0){J=I/G;}if(x>0&&y>0){J=H/F;if(Fthis.imageEl.OriginHeight)?0:Math.abs(this.imageEl.OriginWidth-this.imageEl.OriginHeight); ++E.drawImage(A,sx,sy,F,G,x,y,F,G);break;default:break;}this.cropData=D.toDataURL(this.cropType);if(this.fireEvent('crop',this,this.cropData)!==false){this.process(this.file,this.cropData);}return;},setThumbBoxSize:function(){var A,B;if(this.isDocument&&typeof(this.imageEl)!='undefined'){A=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?Math.max(this.minWidth,this.minHeight):Math.min(this.minWidth,this.minHeight); ++B=(this.imageEl.OriginWidth>this.imageEl.OriginHeight)?Math.min(this.minWidth,this.minHeight):Math.max(this.minWidth,this.minHeight);this.minWidth=A;this.minHeight=B;if(this.rotate==90||this.rotate==270){this.minWidth=B;this.minHeight=A;}}B=300;A=Math.ceil(this.minWidth*B/this.minHeight); ++if(this.minWidth>this.minHeight){A=300;B=Math.ceil(this.minHeight*A/this.minWidth);}this.thumbEl.setStyle({width:A+'px',height:B+'px'});return;},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(){this.baseRotate=1;if(typeof(this.exif)!='undefined'&&typeof(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']])!='undefined'&&[1,3,6,8].indexOf(this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']])!=-1){this.baseRotate=this.exif[Roo.dialog.UploadCropbox['tags']['Orientation']]; ++}this.rotate=Roo.dialog.UploadCropbox['Orientation'][this.baseRotate];},baseScaleLevel:function(){var A,B;if(this.isDocument){if(this.baseRotate==6||this.baseRotate==8){B=this.thumbEl.getHeight();this.baseScale=B/this.imageEl.OriginWidth;if(this.imageEl.OriginHeight*this.baseScale>this.thumbEl.getWidth()){A=this.thumbEl.getWidth(); ++this.baseScale=A/this.imageEl.OriginHeight;}return;}B=this.thumbEl.getHeight();this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScale>this.thumbEl.getWidth()){A=this.thumbEl.getWidth();this.baseScale=A/this.imageEl.OriginWidth; ++}return;}if(this.baseRotate==6||this.baseRotate==8){A=this.thumbEl.getHeight();this.baseScale=A/this.imageEl.OriginHeight;if(this.imageEl.OriginHeight*this.baseScalethis.imageEl.OriginHeight){B=this.thumbEl.getWidth();this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScalethis.imageEl.OriginHeight){B=this.thumbEl.getHeight(); ++this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScale=0xffe0&&H<=0xffef)||H===0xfffe){I=E.getUint16(F+2)+2;if(F+I>E.byteLength){Roo.log('Invalid meta data: Invalid segment size.'); ++break;}if(H==0xffe1){B.parseExifData(E,F,I);}F+=I;continue;}break;}}var J=B.urlAPI.createObjectURL(B.file);B.loadCanvas(J);return;};C.readAsArrayBuffer(this.file);}},parseExifData:function(A,B,C){var D=B+10,E,F;if(A.getUint32(B+4)!==0x45786966){return;}if(A.getUint32(B+4)!==0x45786966){return; ++}if(D+8>A.byteLength){Roo.log('Invalid Exif data: Invalid segment size.');return;}if(A.getUint16(B+8)!==0x0000){Roo.log('Invalid Exif data: Missing byte alignment offset.');return;}switch(A.getUint16(D)){case 0x4949:E=true;break;case 0x4D4D:E=false;break; ++default:Roo.log('Invalid Exif data: Invalid byte alignment marker.');return;}if(A.getUint16(D+2,E)!==0x002A){Roo.log('Invalid Exif data: Missing TIFF marker.');return;}F=A.getUint32(D+4,E);this.parseExifTags(A,D,D+F,E);},parseExifTags:function(A,B,C,D){var E,F,i; ++if(C+6>A.byteLength){Roo.log('Invalid Exif data: Invalid directory offset.');return;}E=A.getUint16(C,D);F=C+2+12*E;if(F+4>A.byteLength){Roo.log('Invalid Exif data: Invalid directory size.');return;}for(i=0;i4?B+A.getUint32(C+8,F):(C+8);if(I+H>A.byteLength){Roo.log('Invalid Exif data: Invalid data offset.');return;}if(E===1){return G.getValue(A,I,F);}J=[];for(i=0;i'} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-picture',action:'picture',cn:[{tag:'button',cls:'btn btn-default',html:''}]},{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-right',action:'rotate-right',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]}],DOCUMENT:[{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-left',action:'rotate-left',cn:[{tag:'button',cls:'btn btn-default',html:''}]},{tag:'div',cls:'btn-group roo-upload-cropbox-download',action:'download',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-crop',action:'crop',cn:[{tag:'button',cls:'btn btn-default',html:''}]},{tag:'div',cls:'btn-group roo-upload-cropbox-trash',action:'trash',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-right',action:'rotate-right',cn:[{tag:'button',cls:'btn btn-default',html:''}]}],ROTATOR:[{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-left',action:'rotate-left',cn:[{tag:'button',cls:'btn btn-default',html:''} ++]},{tag:'div',cls:'btn-group roo-upload-cropbox-rotate-right',action:'rotate-right',cn:[{tag:'button',cls:'btn btn-default',html:''}]}]}}); diff --git a/Roo/Component.js b/Roo/Component.js index 15d9ae20e9..7f78933358 100644 --- a/Roo/Component.js +++ b/Roo/Component.js @@ -23,7 +23,6 @@ * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component. */ Roo.Component = function(config){ - console.log("COMPONENT CONSTRUCTOR"); config = config || {}; if(config.tagName || config.dom || typeof config == "string"){ // element object config = {el: config, id: config.id || config}; diff --git a/Roo/dialog/UploadCropbox.js b/Roo/dialog/UploadCropbox.js index 88058ecd45..a5d3e5c5ee 100644 --- a/Roo/dialog/UploadCropbox.js +++ b/Roo/dialog/UploadCropbox.js @@ -26,7 +26,6 @@ */ Roo.dialog.UploadCropbox = function(config){ - console.log("Dialog UploadCropbox Constructor"); Roo.dialog.UploadCropbox.superclass.constructor.call(this, config); this.addEvents({ @@ -339,8 +338,7 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { this.cropData = false; this.notifyEl.dom.innerHTML = this.emptyText; - console.log("RESET SELECTOR EL") - this.selectorEl.dom.value = ''; + // this.selectorEl.dom.value = ''; }, @@ -548,9 +546,9 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { e.stopEvent(); this.startScale = this.scale; - + console.log("START SCALE: " + this.scale); this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1); - + console.log("END SCALE: " + this.scale); if(!this.zoomable()){ this.scale = this.startScale; return; @@ -563,14 +561,34 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { zoomable : function() { + console.log("THUMBEL"); + console.log(this.thumbEl); var minScale = this.thumbEl.getWidth() / this.minWidth; if(this.minWidth < this.minHeight){ minScale = this.thumbEl.getHeight() / this.minHeight; } + + console.log("MINSCALE: " + minScale); var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale); var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale); + + var maxWidth = this.imageEl.OriginWidth; + var maxHeight = this.imageEl.OriginHeight; + + if(this.imageEl.OriginWidth / this.imageEl.OriginHeight > this.minWidth / this.minHeight && this.imageEl.OriginHeight < this.minHeight) { + maxHeight = this.minHeight; + maxWidth = this.imageEl.OriginWidth / this.imageEl.OriginHeight * this.minHeight; + } + if(this.imageEl.OriginWidth / this.imageEl.OriginHeight < this.minWidth / this.minHeight && this.imageEl.OriginWidth < this.minWidth) { + maxWidth = this.minWidth; + maxHeight = this.imageEl.OriginHeight /this.imageEl.OriginWidth * this.minWidth; + } + + console.log("GETSCALELEVEL: " + this.getScaleLevel()); + console.log("width: " + width); + console.log("height: " + height); if( this.isDocument && @@ -600,10 +618,10 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { !this.isDocument && (this.rotate == 0 || this.rotate == 180) && ( - width < this.minWidth || - width > this.imageEl.OriginWidth || - height < this.minHeight || - height > this.imageEl.OriginHeight + (this.imageEl.OriginWidth / this.imageEl.OriginHeight > this.minWidth / this.minHeight && width < this.minWidth) || + width > maxWidth || + (this.imageEl.OriginWidth / this.imageEl.OriginHeight < this.minWidth / this.minHeight && height < this.minHeight) || + height > maxHeight ) ){ return false; @@ -1176,7 +1194,8 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { getScaleLevel : function() { - return this.baseScale * Math.pow(1.1, this.scale); + console.log("BASESCALE: " + this.baseScale); + return this.baseScale * Math.pow(1.02, this.scale); }, onTouchStart : function(e) diff --git a/Roo/dialog/namespace.js b/Roo/dialog/namespace.js new file mode 100644 index 0000000000..b04737593a --- /dev/null +++ b/Roo/dialog/namespace.js @@ -0,0 +1 @@ +Roo.dialog = {}; \ No newline at end of file diff --git a/Roo/util/Observable.js b/Roo/util/Observable.js index 11e39c5c87..1735439bd2 100644 --- a/Roo/util/Observable.js +++ b/Roo/util/Observable.js @@ -28,7 +28,6 @@ */ Roo.util.Observable = function(cfg){ - console.log("UTIL OBSERVABLE CONSTRUCTOR"); cfg = cfg|| {}; this.addEvents(cfg.events || {}); diff --git a/buildSDK/dependancy_ui.txt b/buildSDK/dependancy_ui.txt index 5a8e5a9ac5..f89656e412 100644 --- a/buildSDK/dependancy_ui.txt +++ b/buildSDK/dependancy_ui.txt @@ -197,3 +197,6 @@ Roo.XTemplate // is this ready yet? - is it used? // Roo.Login + +Roo.dialog.namespace +Roo.dialog.UploadCropbox diff --git a/examples/dialog/test-2.js b/examples/dialog/test-2.js index 08c28d1674..b8efe82c2f 100644 --- a/examples/dialog/test-2.js +++ b/examples/dialog/test-2.js @@ -36,35 +36,25 @@ var uploadCropbox = { xns : Roo.dialog, minWidth : 720, minHeight: 480, - buttons: [ - { - tag : 'div', - cls : 'btn-group roo-upload-cropbox-picture', - action : 'picture', - cn : [ - { - tag : 'button', - cls : 'btn btn-default', - html : '' - } - ] - } - ], + buttons: [], listeners : { render : function (_self) { - console.log("RENDER"); _this.cropbox = _self; }, loadcanvas : function (_self, imageEl) { - console.log("LOADCANVAS"); - console.log(_self); - console.log(imageEl); - if(imageEl.OriginWidth < 720) { - console.log("Image width should be at least 720"); - return false; - } + // if(imageEl.OriginWidth < 720) { + // Roo.Msg.show({ + // title: 'Error', + // msg: "Image width should be at least 720", + // buttons: {ok : true}, + // fn: function(res) { + // _this.cropbox.selectorEl.dom.click(); + // } + // }); + // return false; + // } } } } diff --git a/examples/dialog/test.html b/examples/dialog/test.html index 4e2ba88244..ecb2a0afa3 100644 --- a/examples/dialog/test.html +++ b/examples/dialog/test.html @@ -18,7 +18,7 @@ -

Upload Cropbox Dialog

+

Upload Cropbox Bootstrap

This example shows how to create a very simple modal BasicDialog with "autoTabs".



Note that the js is not minified so it is readable. See diff --git a/roojs-all.js b/roojs-all.js index 61029141ac..7209230cce 100644 --- a/roojs-all.js +++ b/roojs-all.js @@ -2530,7 +2530,7 @@ var r=A.getRegion(E);if(r&&F){if(F.size){r.resizeTo(F.size);}if(F.collapsed==tru A.on("regionexpanded",this.onRegionExpanded,this);},storeState:function(){this.provider.set(this.layout.id+"-layout-state",this.state);},onRegionResized:function(A,B){this.state[A.getPosition()].size=B;this.storeState();},onRegionCollapsed:function(A){this.state[A.getPosition()].collapsed=true; this.storeState();},onRegionExpanded:function(A){this.state[A.getPosition()].collapsed=false;this.storeState();}}; // Roo/ContentPanel.js -Roo.ContentPanel=function(el,A,B){console.log("ContentPanel Constructor");if(el.autoCreate){A=el;el=Roo.id();}this.el=Roo.get(el);if(!this.el&&A&&A.autoCreate){if(typeof A.autoCreate=="object"){if(!A.autoCreate.id){A.autoCreate.id=A.id||el;}this.el=Roo.DomHelper.append(document.body,A.autoCreate,true); +Roo.ContentPanel=function(el,A,B){if(el.autoCreate){A=el;el=Roo.id();}this.el=Roo.get(el);if(!this.el&&A&&A.autoCreate){if(typeof A.autoCreate=="object"){if(!A.autoCreate.id){A.autoCreate.id=A.id||el;}this.el=Roo.DomHelper.append(document.body,A.autoCreate,true); }else{this.el=Roo.DomHelper.append(document.body,{tag:"div",cls:"x-layout-inactive-content",id:A.id||el},true);}}this.closable=false;this.loaded=false;this.active=false;if(typeof A=="string"){this.title=A;}else{Roo.apply(this,A);}if(this.toolbar&&!this.toolbar.el&&this.toolbar.xtype){this.wrapEl=this.el.wrap(); this.toolbar.container=this.el.insertSibling(false,'before');this.toolbar=new Roo.Toolbar(this.toolbar);}if(this.footer&&!this.footer.el&&this.footer.xtype){if(!this.wrapEl){this.wrapEl=this.el.wrap();}this.footer.container=this.wrapEl.createChild();this.footer=Roo.factory(this.footer,Roo); }if(this.resizeEl){this.resizeEl=Roo.get(this.resizeEl,true);}else{this.resizeEl=this.el;}this.addEvents({"activate":true,"deactivate":true,"resize":true,"render":true});if(this.autoScroll){this.resizeEl.setStyle("overflow","auto");}else{this.el.on('scroll',function(){Roo.log('fix random scolling'); @@ -2878,7 +2878,7 @@ B.push(tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re, // Roo/dialog/namespace.js Roo.dialog={}; // Roo/dialog/UploadCropbox.js -Roo.dialog.UploadCropbox=function(A){console.log("Dialog UploadCropbox Constructor");Roo.dialog.UploadCropbox.superclass.constructor.call(this,A);this.addEvents({"beforeselectfile":true,"initial":true,"crop":true,"prepare":true,"exception":true,"beforeloadcanvas":true,"trash":true,"download":true,"footerbuttonclick":true,"resize":true,"rotate":true,"inspect":true,"upload":true,"arrange":true,"loadcanvas":true} +Roo.dialog.UploadCropbox=function(A){Roo.dialog.UploadCropbox.superclass.constructor.call(this,A);this.addEvents({"beforeselectfile":true,"initial":true,"crop":true,"prepare":true,"exception":true,"beforeloadcanvas":true,"trash":true,"download":true,"footerbuttonclick":true,"resize":true,"rotate":true,"inspect":true,"upload":true,"arrange":true,"loadcanvas":true} );this.buttons=this.buttons||Roo.dialog.UploadCropbox.footer.STANDARD;};Roo.extend(Roo.dialog.UploadCropbox,Roo.Component,{emptyText:'Click to upload image',rotateNotify:'Image is too small to rotate',errorTimeout:3000,scale:0,baseScale:1,rotate:0,dragable:false,pinching:false,mouseX:0,mouseY:0,cropData:false,minWidth:300,minHeight:300,file:false,exif:{} ,baseRotate:1,cropType:'image/jpeg',buttons:false,canvasLoaded:false,isDocument:false,method:'POST',paramName:'imageUpload',loadMask:true,loadingText:'Loading...',maskEl:false,getAutoCreate:function(){var A={tag:'div',cls:'roo-upload-cropbox',cn:[{tag:'input',cls:'roo-upload-cropbox-selector',type:'file'} ,{tag:'div',cls:'roo-upload-cropbox-body',style:'cursor:pointer',cn:[{tag:'div',cls:'roo-upload-cropbox-preview'},{tag:'div',cls:'roo-upload-cropbox-thumb'},{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} @@ -2892,7 +2892,7 @@ this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';thi this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.footerEl.hide();this.setThumbBoxSize();this.bind();this.resize();this.fireEvent('initial',this);},bind:function(){var A=this;window.addEventListener("resize",function(){A.resize(); });this.bodyEl.on('click',this.beforeSelectFile,this);if(Roo.isTouch){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.bodyEl.on('mousedown',this.onMouseDown,this); this.bodyEl.on('mousemove',this.onMouseMove,this);var B=(/Firefox/i.test(navigator.userAgent))?'DOMMouseScroll':'mousewheel';this.bodyEl.on(B,this.onMouseWheel,this);Roo.get(document).on('mouseup',this.onMouseUp,this);}this.selectorEl.on('change',this.onFileSelected,this); -},reset:function(){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.cropData=false;this.notifyEl.dom.innerHTML=this.emptyText;this.selectorEl.dom.value='';},resize:function(){if(this.fireEvent('resize',this)!=false){this.setThumbBoxPosition(); +},reset:function(){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.cropData=false;this.notifyEl.dom.innerHTML=this.emptyText;},resize:function(){if(this.fireEvent('resize',this)!=false){this.setThumbBoxPosition(); this.setCanvasPosition();}},onFooterButtonClick:function(e,el,o,A){switch(A){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,A);},beforeSelectFile:function(e){e.preventDefault();if(this.fireEvent('beforeselectfile',this)!=false){this.selectorEl.dom.click();}},onFileSelected:function(e){e.preventDefault(); if(typeof(this.selectorEl.dom.files)=='undefined'||!this.selectorEl.dom.files.length){return;}var A=this.selectorEl.dom.files[0];if(this.fireEvent('inspect',this,A)!=false){this.prepare(A);}},trash:function(e){this.fireEvent('trash',this);},download:function(e){this.fireEvent('download',this); @@ -2903,12 +2903,14 @@ var ph=Math.ceil((this.bodyEl.getHeight()-this.canvasEl.height)/2);this.previewE return;}this.mouseX=Roo.isTouch?e.browserEvent.touches[0].pageX:e.getPageX();this.mouseY=Roo.isTouch?e.browserEvent.touches[0].pageY:e.getPageY();},onMouseMove:function(e){e.stopEvent();if(!this.canvasLoaded){return;}if(!this.dragable){return;}var A=Math.ceil(this.thumbEl.getLeft(true)); var B=Math.ceil(this.thumbEl.getTop(true));var C=Math.ceil(A+this.thumbEl.getWidth()-this.canvasEl.width);var D=Math.ceil(B+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(); x=x-this.mouseX;y=y-this.mouseY;var E=Math.ceil(x+this.previewEl.getLeft(true));var F=Math.ceil(y+this.previewEl.getTop(true));E=(AE)?C:E);F=(BF)?D:F);this.previewEl.setLeft(E);this.previewEl.setTop(F);this.mouseX=Roo.isTouch?e.browserEvent.touches[0].pageX:e.getPageX(); -this.mouseY=Roo.isTouch?e.browserEvent.touches[0].pageY:e.getPageY();},onMouseUp:function(e){e.stopEvent();this.dragable=false;},onMouseWheel:function(e){e.stopEvent();this.startScale=this.scale;this.scale=(e.getWheelDelta()==1)?(this.scale+1):(this.scale-1); -if(!this.zoomable()){this.scale=this.startScale;return;}this.draw();return;},zoomable:function(){var A=this.thumbEl.getWidth()/this.minWidth;if(this.minWidththis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false;}if(!this.isDocument&&(this.rotate==90||this.rotate==270)&&(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false; -}return true;},onRotateLeft:function(e){if(!this.isDocument&&(this.canvasEl.heightthis.minWidth/this.minHeight&&this.imageEl.OriginHeightthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.minWidth/this.minHeight&&BD||(this.imageEl.OriginWidth/this.imageEl.OriginHeightE)){return false; +}if(!this.isDocument&&(this.rotate==90||this.rotate==270)&&(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false;}return true;},onRotateLeft:function(e){if(!this.isDocument&&(this.canvasEl.heightthis.imageEl.OriginHeight){B=this.thumbEl.getWidth();this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScalethis.imageEl.OriginHeight){B=this.thumbEl.getHeight(); -this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScale this.minWidth / this.minHeight && this.imageEl.OriginHeight < this.minHeight) { + maxHeight = this.minHeight; + maxWidth = this.imageEl.OriginWidth / this.imageEl.OriginHeight * this.minHeight; + } + if(this.imageEl.OriginWidth / this.imageEl.OriginHeight < this.minWidth / this.minHeight && this.imageEl.OriginWidth < this.minWidth) { + maxWidth = this.minWidth; + maxHeight = this.imageEl.OriginHeight /this.imageEl.OriginWidth * this.minWidth; + } + + console.log("GETSCALELEVEL: " + this.getScaleLevel()); + console.log("width: " + width); + console.log("height: " + height); if( this.isDocument && @@ -68659,10 +68677,10 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { !this.isDocument && (this.rotate == 0 || this.rotate == 180) && ( - width < this.minWidth || - width > this.imageEl.OriginWidth || - height < this.minHeight || - height > this.imageEl.OriginHeight + (this.imageEl.OriginWidth / this.imageEl.OriginHeight > this.minWidth / this.minHeight && width < this.minWidth) || + width > maxWidth || + (this.imageEl.OriginWidth / this.imageEl.OriginHeight < this.minWidth / this.minHeight && height < this.minHeight) || + height > maxHeight ) ){ return false; @@ -69235,7 +69253,8 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { getScaleLevel : function() { - return this.baseScale * Math.pow(1.1, this.scale); + console.log("BASESCALE: " + this.baseScale); + return this.baseScale * Math.pow(1.02, this.scale); }, onTouchStart : function(e) diff --git a/roojs-ui-debug.js b/roojs-ui-debug.js index 464233f876..d855221d18 100644 --- a/roojs-ui-debug.js +++ b/roojs-ui-debug.js @@ -35922,7 +35922,6 @@ Roo.LayoutStateManager.prototype = { */ Roo.ContentPanel = function(el, config, content){ - console.log("ContentPanel Constructor"); /* if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory config = el; @@ -43594,7 +43593,6 @@ Roo.XTemplate.from = function(el){ */ Roo.dialog.UploadCropbox = function(config){ - console.log("Dialog UploadCropbox Constructor"); Roo.dialog.UploadCropbox.superclass.constructor.call(this, config); this.addEvents({ @@ -43907,7 +43905,7 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { this.cropData = false; this.notifyEl.dom.innerHTML = this.emptyText; - this.selectorEl.dom.value = ''; + // this.selectorEl.dom.value = ''; }, @@ -44115,9 +44113,9 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { e.stopEvent(); this.startScale = this.scale; - + console.log("START SCALE: " + this.scale); this.scale = (e.getWheelDelta() == 1) ? (this.scale + 1) : (this.scale - 1); - + console.log("END SCALE: " + this.scale); if(!this.zoomable()){ this.scale = this.startScale; return; @@ -44130,14 +44128,34 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { zoomable : function() { + console.log("THUMBEL"); + console.log(this.thumbEl); var minScale = this.thumbEl.getWidth() / this.minWidth; if(this.minWidth < this.minHeight){ minScale = this.thumbEl.getHeight() / this.minHeight; } + + console.log("MINSCALE: " + minScale); var width = Math.ceil(this.imageEl.OriginWidth * this.getScaleLevel() / minScale); var height = Math.ceil(this.imageEl.OriginHeight * this.getScaleLevel() / minScale); + + var maxWidth = this.imageEl.OriginWidth; + var maxHeight = this.imageEl.OriginHeight; + + if(this.imageEl.OriginWidth / this.imageEl.OriginHeight > this.minWidth / this.minHeight && this.imageEl.OriginHeight < this.minHeight) { + maxHeight = this.minHeight; + maxWidth = this.imageEl.OriginWidth / this.imageEl.OriginHeight * this.minHeight; + } + if(this.imageEl.OriginWidth / this.imageEl.OriginHeight < this.minWidth / this.minHeight && this.imageEl.OriginWidth < this.minWidth) { + maxWidth = this.minWidth; + maxHeight = this.imageEl.OriginHeight /this.imageEl.OriginWidth * this.minWidth; + } + + console.log("GETSCALELEVEL: " + this.getScaleLevel()); + console.log("width: " + width); + console.log("height: " + height); if( this.isDocument && @@ -44167,10 +44185,10 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { !this.isDocument && (this.rotate == 0 || this.rotate == 180) && ( - width < this.minWidth || - width > this.imageEl.OriginWidth || - height < this.minHeight || - height > this.imageEl.OriginHeight + (this.imageEl.OriginWidth / this.imageEl.OriginHeight > this.minWidth / this.minHeight && width < this.minWidth) || + width > maxWidth || + (this.imageEl.OriginWidth / this.imageEl.OriginHeight < this.minWidth / this.minHeight && height < this.minHeight) || + height > maxHeight ) ){ return false; @@ -44743,7 +44761,8 @@ Roo.extend(Roo.dialog.UploadCropbox, Roo.Component, { getScaleLevel : function() { - return this.baseScale * Math.pow(1.1, this.scale); + console.log("BASESCALE: " + this.baseScale); + return this.baseScale * Math.pow(1.02, this.scale); }, onTouchStart : function(e) diff --git a/roojs-ui.js b/roojs-ui.js index 9323b6bf2f..2409d8a666 100644 --- a/roojs-ui.js +++ b/roojs-ui.js @@ -1584,7 +1584,7 @@ var r=A.getRegion(E);if(r&&F){if(F.size){r.resizeTo(F.size);}if(F.collapsed==tru A.on("regionexpanded",this.onRegionExpanded,this);},storeState:function(){this.provider.set(this.layout.id+"-layout-state",this.state);},onRegionResized:function(A,B){this.state[A.getPosition()].size=B;this.storeState();},onRegionCollapsed:function(A){this.state[A.getPosition()].collapsed=true; this.storeState();},onRegionExpanded:function(A){this.state[A.getPosition()].collapsed=false;this.storeState();}}; // Roo/ContentPanel.js -Roo.ContentPanel=function(el,A,B){console.log("ContentPanel Constructor");if(el.autoCreate){A=el;el=Roo.id();}this.el=Roo.get(el);if(!this.el&&A&&A.autoCreate){if(typeof A.autoCreate=="object"){if(!A.autoCreate.id){A.autoCreate.id=A.id||el;}this.el=Roo.DomHelper.append(document.body,A.autoCreate,true); +Roo.ContentPanel=function(el,A,B){if(el.autoCreate){A=el;el=Roo.id();}this.el=Roo.get(el);if(!this.el&&A&&A.autoCreate){if(typeof A.autoCreate=="object"){if(!A.autoCreate.id){A.autoCreate.id=A.id||el;}this.el=Roo.DomHelper.append(document.body,A.autoCreate,true); }else{this.el=Roo.DomHelper.append(document.body,{tag:"div",cls:"x-layout-inactive-content",id:A.id||el},true);}}this.closable=false;this.loaded=false;this.active=false;if(typeof A=="string"){this.title=A;}else{Roo.apply(this,A);}if(this.toolbar&&!this.toolbar.el&&this.toolbar.xtype){this.wrapEl=this.el.wrap(); this.toolbar.container=this.el.insertSibling(false,'before');this.toolbar=new Roo.Toolbar(this.toolbar);}if(this.footer&&!this.footer.el&&this.footer.xtype){if(!this.wrapEl){this.wrapEl=this.el.wrap();}this.footer.container=this.wrapEl.createChild();this.footer=Roo.factory(this.footer,Roo); }if(this.resizeEl){this.resizeEl=Roo.get(this.resizeEl,true);}else{this.resizeEl=this.el;}this.addEvents({"activate":true,"deactivate":true,"resize":true,"render":true});if(this.autoScroll){this.resizeEl.setStyle("overflow","auto");}else{this.el.on('scroll',function(){Roo.log('fix random scolling'); @@ -1932,7 +1932,7 @@ B.push(tpl.body.replace(/(\r\n|\n)/g,'\\n').replace(/'/g,"\\'").replace(this.re, // Roo/dialog/namespace.js Roo.dialog={}; // Roo/dialog/UploadCropbox.js -Roo.dialog.UploadCropbox=function(A){console.log("Dialog UploadCropbox Constructor");Roo.dialog.UploadCropbox.superclass.constructor.call(this,A);this.addEvents({"beforeselectfile":true,"initial":true,"crop":true,"prepare":true,"exception":true,"beforeloadcanvas":true,"trash":true,"download":true,"footerbuttonclick":true,"resize":true,"rotate":true,"inspect":true,"upload":true,"arrange":true,"loadcanvas":true} +Roo.dialog.UploadCropbox=function(A){Roo.dialog.UploadCropbox.superclass.constructor.call(this,A);this.addEvents({"beforeselectfile":true,"initial":true,"crop":true,"prepare":true,"exception":true,"beforeloadcanvas":true,"trash":true,"download":true,"footerbuttonclick":true,"resize":true,"rotate":true,"inspect":true,"upload":true,"arrange":true,"loadcanvas":true} );this.buttons=this.buttons||Roo.dialog.UploadCropbox.footer.STANDARD;};Roo.extend(Roo.dialog.UploadCropbox,Roo.Component,{emptyText:'Click to upload image',rotateNotify:'Image is too small to rotate',errorTimeout:3000,scale:0,baseScale:1,rotate:0,dragable:false,pinching:false,mouseX:0,mouseY:0,cropData:false,minWidth:300,minHeight:300,file:false,exif:{} ,baseRotate:1,cropType:'image/jpeg',buttons:false,canvasLoaded:false,isDocument:false,method:'POST',paramName:'imageUpload',loadMask:true,loadingText:'Loading...',maskEl:false,getAutoCreate:function(){var A={tag:'div',cls:'roo-upload-cropbox',cn:[{tag:'input',cls:'roo-upload-cropbox-selector',type:'file'} ,{tag:'div',cls:'roo-upload-cropbox-body',style:'cursor:pointer',cn:[{tag:'div',cls:'roo-upload-cropbox-preview'},{tag:'div',cls:'roo-upload-cropbox-thumb'},{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} @@ -1946,7 +1946,7 @@ this.notifyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';thi this.footerEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay='block';this.footerEl.hide();this.setThumbBoxSize();this.bind();this.resize();this.fireEvent('initial',this);},bind:function(){var A=this;window.addEventListener("resize",function(){A.resize(); });this.bodyEl.on('click',this.beforeSelectFile,this);if(Roo.isTouch){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.bodyEl.on('mousedown',this.onMouseDown,this); this.bodyEl.on('mousemove',this.onMouseMove,this);var B=(/Firefox/i.test(navigator.userAgent))?'DOMMouseScroll':'mousewheel';this.bodyEl.on(B,this.onMouseWheel,this);Roo.get(document).on('mouseup',this.onMouseUp,this);}this.selectorEl.on('change',this.onFileSelected,this); -},reset:function(){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.cropData=false;this.notifyEl.dom.innerHTML=this.emptyText;this.selectorEl.dom.value='';},resize:function(){if(this.fireEvent('resize',this)!=false){this.setThumbBoxPosition(); +},reset:function(){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.cropData=false;this.notifyEl.dom.innerHTML=this.emptyText;},resize:function(){if(this.fireEvent('resize',this)!=false){this.setThumbBoxPosition(); this.setCanvasPosition();}},onFooterButtonClick:function(e,el,o,A){switch(A){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,A);},beforeSelectFile:function(e){e.preventDefault();if(this.fireEvent('beforeselectfile',this)!=false){this.selectorEl.dom.click();}},onFileSelected:function(e){e.preventDefault(); if(typeof(this.selectorEl.dom.files)=='undefined'||!this.selectorEl.dom.files.length){return;}var A=this.selectorEl.dom.files[0];if(this.fireEvent('inspect',this,A)!=false){this.prepare(A);}},trash:function(e){this.fireEvent('trash',this);},download:function(e){this.fireEvent('download',this); @@ -1957,12 +1957,14 @@ var ph=Math.ceil((this.bodyEl.getHeight()-this.canvasEl.height)/2);this.previewE return;}this.mouseX=Roo.isTouch?e.browserEvent.touches[0].pageX:e.getPageX();this.mouseY=Roo.isTouch?e.browserEvent.touches[0].pageY:e.getPageY();},onMouseMove:function(e){e.stopEvent();if(!this.canvasLoaded){return;}if(!this.dragable){return;}var A=Math.ceil(this.thumbEl.getLeft(true)); var B=Math.ceil(this.thumbEl.getTop(true));var C=Math.ceil(A+this.thumbEl.getWidth()-this.canvasEl.width);var D=Math.ceil(B+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(); x=x-this.mouseX;y=y-this.mouseY;var E=Math.ceil(x+this.previewEl.getLeft(true));var F=Math.ceil(y+this.previewEl.getTop(true));E=(AE)?C:E);F=(BF)?D:F);this.previewEl.setLeft(E);this.previewEl.setTop(F);this.mouseX=Roo.isTouch?e.browserEvent.touches[0].pageX:e.getPageX(); -this.mouseY=Roo.isTouch?e.browserEvent.touches[0].pageY:e.getPageY();},onMouseUp:function(e){e.stopEvent();this.dragable=false;},onMouseWheel:function(e){e.stopEvent();this.startScale=this.scale;this.scale=(e.getWheelDelta()==1)?(this.scale+1):(this.scale-1); -if(!this.zoomable()){this.scale=this.startScale;return;}this.draw();return;},zoomable:function(){var A=this.thumbEl.getWidth()/this.minWidth;if(this.minWidththis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false;}if(!this.isDocument&&(this.rotate==90||this.rotate==270)&&(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false; -}return true;},onRotateLeft:function(e){if(!this.isDocument&&(this.canvasEl.heightthis.minWidth/this.minHeight&&this.imageEl.OriginHeightthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.imageEl.OriginWidth||C>this.imageEl.OriginHeight||(Bthis.minWidth/this.minHeight&&BD||(this.imageEl.OriginWidth/this.imageEl.OriginHeightE)){return false; +}if(!this.isDocument&&(this.rotate==90||this.rotate==270)&&(Bthis.imageEl.OriginWidth||Cthis.imageEl.OriginHeight)){return false;}return true;},onRotateLeft:function(e){if(!this.isDocument&&(this.canvasEl.heightthis.imageEl.OriginHeight){B=this.thumbEl.getWidth();this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScalethis.imageEl.OriginHeight){B=this.thumbEl.getHeight(); -this.baseScale=B/this.imageEl.OriginHeight;if(this.imageEl.OriginWidth*this.baseScale