/**
Returns the number of milliseconds between this date and date
@param {Date} date (optional) Defaults to now
- @return {Number} The diff in milliseconds
+ @param {String} interval (optional) Default Date.MILLI, A valid date interval enum value (eg. Date.DAY)
+ @return {Number} The diff in milliseconds or units of interval
@member Date getElapsed
*/
-Date.prototype.getElapsed = function(date) {
- return Math.abs((date || new Date()).getTime()-this.getTime());
+Date.prototype.getElapsed = function(date, interval)
+{
+ date = date || new Date();
+ var ret = Math.abs(date.getTime()-this.getTime());
+ switch (interval) {
+
+ case Date.SECOND:
+ return Math.floor(ret / (1000));
+ case Date.MINUTE:
+ return Math.floor(ret / (1000*60));
+ case Date.HOUR:
+ return Math.floor(ret / (1000*60*60));
+ case Date.DAY:
+ return Math.floor(ret / (1000*60*60*24));
+ case Date.MONTH: // this does not give exact number...??
+ return ((date.format("Y") - this.format("Y")) * 12) + (date.format("m") - this.format("m"));
+ case Date.YEAR: // this does not give exact number...??
+ return (date.format("Y") - this.format("Y"));
+
+ case Date.MILLI:
+ default:
+ return ret;
+ }
};
+
// was in date file..
*/
/**
* @class Roo.data.MemoryProxy
+ * @extends Roo.data.DataProxy
* An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
* to the Reader when its load method is called.
* @constructor
- * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+ * @param {Object} config A config object containing the objects needed for the Store to access data,
*/
-Roo.data.MemoryProxy = function(data){
- if (data.data) {
- data = data.data;
+Roo.data.MemoryProxy = function(config){
+ var data = config;
+ if (typeof(config) != 'undefined' && typeof(config.data) != 'undefined') {
+ data = config.data;
}
Roo.data.MemoryProxy.superclass.constructor.call(this);
this.data = data;
Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
+ /**
+ * @cfg {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
+ */
/**
* Load data from the requested source (in this case an in-memory
* data object passed to the constructor), read the data object into
this.hide();
}
},
-
+ /**
+ * Similar to toggle, but does not trigger event.
+ * @param {Boolean} state [required] Force a particular state
+ */
+ setPressed : function(state)
+ {
+ if(state != this.pressed){
+ if(state){
+ this.el.addClass("x-btn-pressed");
+ this.pressed = true;
+ }else{
+ this.el.removeClass("x-btn-pressed");
+ this.pressed = false;
+ }
+ }
+ },
+
/**
* If a state it passed, it becomes the pressed state otherwise the current state is toggled.
* @param {Boolean} state (optional) Force a particular state
}
},
+
+
/**
* Focus the button
*/
this.hexStore.push(cmd);
},
cmderror : function(cmd) {
- throw new Exception (cmd.value);
+ throw cmd.value;
},
/*
{
this.emitText();
if (this.controlWord === '') {
- this.emitError('empty control word');
+ // do we want to track this - it seems just to cause problems.
+ //this.emitError('empty control word');
} else {
this.push({
type: 'controlword',
Roo.htmleditor.FilterWord = function(cfg)
{
// no need to apply config.
- this.walk(cfg.node);
+ this.replaceDocBullets(cfg.node);
+
+ // this.walk(cfg.node);
+
+
}
Roo.extend(Roo.htmleditor.FilterWord, Roo.htmleditor.Filter,
node.removeChild(cn);
node.parentNode.insertBefore(cn, node);
// move node to parent - and clean it..
- this.replaceTag(cn);
+ if (cn.nodeType == 1) {
+ this.replaceTag(cn);
+ }
+
}
node.parentNode.removeChild(node);
/// no need to iterate chidlren = it's got none..
+ },
+
+ styleToObject: function(node)
+ {
+ var styles = (node.getAttribute("style") || '').split(";");
+ var ret = {};
+ Roo.each(styles, function(s) {
+ if (!s.match(/:/)) {
+ return;
+ }
+ var kv = s.split(":");
+
+ // what ever is left... we allow.
+ ret[kv[0].trim()] = kv[1];
+ });
+ return ret;
+ },
+
+
+ replaceDocBullets : function(doc)
+ {
+ // this is a bit odd - but it appears some indents use ql-indent-1
+
+ var listpara = doc.getElementsByClassName('ql-indent-1');
+ while(listpara.length) {
+ this.replaceDocBullet(listpara.item(0));
+ }
+
+ var listpara = doc.getElementsByClassName('MsoListParagraph');
+ while(listpara.length) {
+ this.replaceDocBullet(listpara.item(0));
+ }
+ },
+
+ replaceDocBullet : function(p)
+ {
+ // gather all the siblings.
+ var ns = p,
+ parent = p.parentNode,
+ doc = parent.ownerDocument,
+ items = [];
+
+
+ while (ns) {
+ if (ns.nodeType != 1) {
+ ns = ns.nextSibling;
+ continue;
+ }
+ if (!ns.className.match(/(MsoListParagraph|ql-indent-1)/i)) {
+ break;
+ }
+ items.push(ns);
+ ns = ns.nextSibling;
+ }
+
+
+ var ul = parent.ownerDocument.createElement('ul'); // what about number lists...
+ parent.insertBefore(ul, p);
+ var lvl = 0;
+ var stack = [ ul ];
+ var last_li = false;
+
+ items.forEach(function(n, ipos) {
+ //Roo.log("got innertHMLT=" + n.innerHTML);
+
+ var spans = n.getElementsByTagName('span');
+ if (!spans.length) {
+ //Roo.log("No spans found");
+
+ parent.removeChild(n);
+ return; // skip it...
+ }
+
+
+
+ var style = {};
+ for(var i = 0; i < spans.length; i++) {
+
+ style = this.styleToObject(spans[i]);
+ if (typeof(style['mso-list']) == 'undefined') {
+ continue;
+ }
+
+ spans[i].parentNode.removeChild(spans[i]); // remove the fake bullet.
+ break;
+ }
+ //Roo.log("NOW GOT innertHMLT=" + n.innerHTML);
+ style = this.styleToObject(n); // mo-list is from the parent node.
+ if (typeof(style['mso-list']) == 'undefined') {
+ //Roo.log("parent is missing level");
+ parent.removeChild(n);
+ return;
+ }
+
+ var nlvl = (style['mso-list'].split(' ')[1].replace(/level/,'') *1) - 1 ;
+
+
+
+ if (nlvl > lvl) {
+ //new indent
+ var nul = doc.createElement('ul'); // what about number lists...
+ last_li.appendChild(nul);
+ stack[nlvl] = nul;
+
+ }
+ lvl = nlvl;
+
+ var nli = stack[nlvl].appendChild(doc.createElement('li'));
+ last_li = nli;
+ nli.innerHTML = n.innerHTML;
+ //Roo.log("innerHTML = " + n.innerHTML);
+ parent.removeChild(n);
+
+ // copy children of p into nli
+ /*while(n.firstChild) {
+ var fc = n.firstChild;
+ n.removeChild(fc);
+ nli.appendChild(fc);
+ }*/
+
+
+ },this);
+
+
+
+
}
+
+
+
});
/**
* @class Roo.htmleditor.FilterStyleToTag
* @param {String} text String to write out.
* @param {Boolean} raw Optional raw state if true the contents wont get encoded.
*/
- text: function(text, node)
+ text: function(in_text, node)
{
// if not in whitespace critical
- if (text.length < 1) {
+ if (in_text.length < 1) {
return;
}
+ var text = new XMLSerializer().serializeToString(document.createTextNode(in_text)); // escape it properly?
+
if (this.in_pre) {
this.html[this.html.length] = text;
return;
store : {
xtype : 'SimpleStore',
data : [
- ['auto'],
['50%'],
+ ['80%'],
['100%']
],
fields : [ 'val'],
pressed : false,
enableToggle : true,
setValue : function(v) {
- this.toggle(v == 'block' ? false : true);
+ // this trigger toggle.
+
+ this.setText(v ? "Hide Caption" : "Show Caption");
+ this.setPressed(v != 'block');
},
listeners : {
toggle: function (btn, state)
var d = document.createElement('div');
d.innerHTML = this.caption;
- var m = this.width == '50%' && this.align == 'center' ? '0 auto' : 0;
+ var m = this.width != '100%' && this.align == 'center' ? '0 auto' : 0;
var iw = this.align == 'center' ? this.width : '100%';
var img = {
style: {
width : iw,
maxWidth : iw + ' !important', // this is not getting rendered?
- margin : m
-
+ margin : m
}
};
// we remove caption totally if its hidden... - will delete data.. but otherwise we end up with fake caption
var captionhtml = this.caption_display == 'none' ? '' : (this.caption.length ? this.caption : "Caption");
- return {
+
+ var ret = {
tag: 'figure',
'data-block' : 'Figure',
-
+ 'data-width' : this.width,
contenteditable : 'false',
style : {
maxWidth : this.align == 'center' ? '100% !important' : (this.width + ' !important'),
width : this.align == 'center' ? '100%' : this.width,
margin: '0px',
- padding: '10px',
+ padding: this.align == 'center' ? '0' : '0 10px' ,
textAlign : this.align // seems to work for email..
},
fontSize : '16px',
lineHeight : '24px',
display : this.caption_display,
- maxWidth : this.width + ' !important',
+ maxWidth : (this.align == 'center' ? this.width : '100%' ) + ' !important',
margin: m,
- width: this.width
+ width: this.align == 'center' ? this.width : '100%'
},
}
]
};
+ return ret;
},
this.align = this.getVal(node, 'figure', 'align');
var figcaption = this.getVal(node, 'figcaption', false);
- this.caption = this.getVal(figcaption, 'i', 'html');
+ if (figcaption !== '') {
+ this.caption = this.getVal(figcaption, 'i', 'html');
+ }
+
this.caption_display = this.getVal(node, 'figcaption', 'data-display');
//this.text_align = this.getVal(node, 'figcaption', 'style','text-align');
- this.width = this.getVal(node, 'figcaption', 'style', 'width');
+ this.width = this.getVal(node, true, 'data-width');
//this.margin = this.getVal(node, 'figure', 'style', 'margin');
},
//Roo.log("HtmlEditorCore:syncValue (EDITOR->TEXT)");
if(this.initialized){
- this.undoManager.addEvent();
+ if (this.undoManager) {
+ this.undoManager.addEvent();
+ }
var bd = (this.doc.body || this.doc.documentElement);
var parser = new Roo.rtf.Parser(cd.getData('text/rtf'));
images = parser.doc ? parser.doc.getElementsByType('pict') : [];
}
- Roo.log(images);
+ //Roo.log(images);
//Roo.log(imgs);
// fixme..
images = images.filter(function(g) { return !g.path.match(/^rtf\/(head|pgdsctbl|listtable|footerf)/); }) // ignore headers/footers etc.
});
}
if (this.autoClean) {
+ new Roo.htmleditor.FilterWord({ node : d });
+
new Roo.htmleditor.FilterStyleToTag({ node : d });
new Roo.htmleditor.FilterAttributes({
node : d,
- attrib_white : ['href', 'src', 'name', 'align'],
+ attrib_white : ['href', 'src', 'name', 'align', 'colspan', 'rowspan', 'data-display', 'data-width'],
attrib_clean : ['href', 'src' ]
});
new Roo.htmleditor.FilterBlack({ node : d, tag : this.black});
new Roo.htmleditor.FilterParagraph({ node : d });
new Roo.htmleditor.FilterSpan({ node : d });
new Roo.htmleditor.FilterLongBr({ node : d });
+ new Roo.htmleditor.FilterComment({ node : d });
+
+
}
if (this.enableBlocks) {
if (this.enableBlocks) {
Roo.htmleditor.Block.initAll(this.doc.body);
}
-
+
e.preventDefault();
return false;
* @cfg {String} itemCls A css class to apply to the x-form-item of fields. This property cascades to child containers.
*/
/**
- * @cfg {String} buttonAlign Valid values are "left," "center" and "right" (defaults to "center")
+ * @cfg {String} (left|center|right) buttonAlign Valid values are "left," "center" and "right" (defaults to "center")
*/
buttonAlign:'center',
minButtonWidth:75,
/**
- * @cfg {String} labelAlign Valid values are "left," "top" and "right" (defaults to "left").
+ * @cfg {String} labelAlign (left|top|right) Valid values are "left," "top" and "right" (defaults to "left").
* This property cascades to child containers if not set.
*/
labelAlign:'left',
* a function which returns such a specification.
*/
/**
- * @cfg {String} labelAlign
+ * @cfg {String} labelAlign (left|top|right)
* Valid values are "left," "top" and "right" (defaults to "left")
*/
/**
}
});
+
/**
* @class Roo.form.Column
* @extends Roo.form.Layout
}
});
-
/**
* @class Roo.form.Row
* @extends Roo.form.Layout
*/
Roo.ContentPanel = function(el, config, content){
-
/*
if(el.autoCreate || el.xtype){ // xtype is available if this is called from factory
config = el;
*/
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$/)) {
* @cfg {Roo.grid.ColumnModel} cm[] The columns of the grid
*/
/**
- * @cfg {Roo.grid.Store} ds The data store for the grid
+ * @cfg {Roo.data.Store} ds The data store for the grid
*/
/**
* @cfg {Roo.Toolbar} toolbar a toolbar for buttons etc.
};
Roo.extend(Roo.grid.ColumnModel, Roo.util.Observable, {
/**
- * @cfg {String} header The header text to display in the Grid view.
+ * @cfg {String} header [required] The header text to display in the Grid view.
*/
/**
* @cfg {String} xsHeader Header at Bootsrap Extra Small width (default for all)
* @cfg {String} xlHeader Header at Bootsrap extra Large width
*/
/**
- * @cfg {String} dataIndex (Optional) The name of the field in the grid's {@link Roo.data.Store}'s
+ * @cfg {String} dataIndex The name of the field in the grid's {@link Roo.data.Store}'s
* {@link Roo.data.Record} definition from which to draw the column's value. If not
* specified, the column's index is used as an index into the Record's data Array.
*/
/**
- * @cfg {Number} width (Optional) The initial width in pixels of the column. Using this
+ * @cfg {Number} width The initial width in pixels of the column. Using this
* instead of {@link Roo.grid.Grid#autoSizeColumns} is more efficient.
*/
/**
- * @cfg {Boolean} sortable (Optional) True if sorting is to be allowed on this column.
+ * @cfg {Boolean} sortable True if sorting is to be allowed on this column.
* Defaults to the value of the {@link #defaultSortable} property.
* Whether local/remote sorting is used is specified in {@link Roo.data.Store#remoteSort}.
*/
/**
- * @cfg {Boolean} locked (Optional) True to lock the column in place while scrolling the Grid. Defaults to false.
+ * @cfg {Boolean} locked True to lock the column in place while scrolling the Grid. Defaults to false.
*/
/**
- * @cfg {Boolean} fixed (Optional) True if the column width cannot be changed. Defaults to false.
+ * @cfg {Boolean} fixed True if the column width cannot be changed. Defaults to false.
*/
/**
- * @cfg {Boolean} resizable (Optional) False to disable column resizing. Defaults to true.
+ * @cfg {Boolean} resizable False to disable column resizing. Defaults to true.
*/
/**
- * @cfg {Boolean} hidden (Optional) True to hide the column. Defaults to false.
+ * @cfg {Boolean} hidden True to hide the column. Defaults to false.
*/
/**
- * @cfg {Function} renderer (Optional) A function used to generate HTML markup for a cell
+ * @cfg {Function} renderer A function used to generate HTML markup for a cell
* given the cell's data value. See {@link #setRenderer}. If not specified, the
* default renderer returns the escaped data value. If an object is returned (bootstrap only)
* then it is treated as a Roo Component object instance, and it is rendered after the initial row is rendered
*/
/**
- * @cfg {Roo.grid.GridEditor} editor (Optional) For grid editors - returns the grid editor
+ * @cfg {Roo.grid.GridEditor} editor For grid editors - returns the grid editor
*/
/**
- * @cfg {String} align (Optional) Set the CSS text-align property of the column. Defaults to undefined.
+ * @cfg {String} align (left|right) Set the CSS text-align property of the column. Defaults to undefined (left).
*/
/**
- * @cfg {String} valign (Optional) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc). Defaults to undefined.
+ * @cfg {String} valign (top|bottom|middle) Set the CSS vertical-align property of the column (eg. middle, top, bottom etc). Defaults to undefined (middle)
*/
/**
- * @cfg {String} cursor (Optional)
+ * @cfg {String} cursor ( auto|default|none|context-menu|help|pointer|progress|wait|cell|crosshair|text|vertical-text|alias|copy|move|no-drop|not-allowed|e-resize|n-resize|ne-resize|nw-resize|s-resize|se-resize|sw-resize|w-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|col-resize|row-resize|all-scroll|zoom-in|zoom-out|grab|grabbing)
*/
/**
- * @cfg {String} tooltip (Optional)
+ * @cfg {String} tooltip mouse over tooltip text
*/
/**
- * @cfg {Number} xs (Optional) can be '0' for hidden at this size (number less than 12)
+ * @cfg {Number} xs can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} sm (Optional) can be '0' for hidden at this size (number less than 12)
+ * @cfg {Number} sm can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} md (Optional) can be '0' for hidden at this size (number less than 12)
+ * @cfg {Number} md can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} lg (Optional) can be '0' for hidden at this size (number less than 12)
+ * @cfg {Number} lg can be '0' for hidden at this size (number less than 12)
*/
/**
- * @cfg {Number} xl (Optional) can be '0' for hidden at this size (number less than 12)
+ * @cfg {Number} xl can be '0' for hidden at this size (number less than 12)
*/
/**
* Returns the id of the column at the specified index.
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){
+ 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)
+ {
+ 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)
+ {
+ console.log("ON FILE SELECTED");
+ 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)
+ {
+ console.log("LOAD CANVAS");
+ console.log(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()
+ {
+ console.log("ON LOAD CANVAS");
+ 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()
+ {
+ console.log("SET CANVAS POSITION");
+ 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);
+
+ if(minX > maxX) {
+ var tempX = minX;
+ minX = maxX;
+ maxX = tempX;
+ }
+
+ if(minY > maxY) {
+ var tempY = minY;
+ minY = maxY;
+ maxY = tempY;
+ }
+
+ 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 = (bgX < minX) ? minX : ((bgX > maxX) ? maxX : bgX);
+ bgY = (bgY < minY) ? minY : ((bgY > maxY) ? 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);
+
+ console.log("START SCALE:" + this.startScale);
+ console.log("TEST SCALE: " + this.scale);
+ if(!this.zoomable()){
+ this.scale = this.startScale;
+ return;
+ }
+
+ console.log("END SCALE: " + this.scale);
+
+ this.draw();
+
+ return;
+ },
+
+ zoomable : function()
+ {
+ 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);
+
+ console.log("WIDTH: " + width);
+ console.log("HEIGHT: " + height);
+
+ var maxWidth = this.imageEl.OriginWidth;
+ var maxHeight = this.imageEl.OriginHeight;
+
+ 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 ||
+ height < this.minHeight ||
+ width > maxWidth ||
+ height > maxHeight
+ )
+ ){
+ 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()
+ {
+ console.log("DRAW");
+ this.previewEl.dom.innerHTML = '';
+
+ var canvasEl = document.createElement("canvas");
+
+ var contextEl = canvasEl.getContext("2d");
+
+ console.log(this.getScaleLevel());
+
+ 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()
+ {
+ console.log("SET THUMBBOX POSITION");
+ 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()
+ {
+ console.log("BASE ROTATE LEVEL");
+ 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()
+ {
+ console.log("BASE SCALE LEVEL");
+ 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;
+ }
+
+ }
+
+ if(this.imageEl.OriginWidth < this.minWidth || this.imageEl.OriginHeight < this.minHeight) {
+ this.baseScale = width / this.minWidth;
+ }
+ console.log(this.baseScale);
+ return;
+ },
+
+ getScaleLevel : function()
+ {
+ return this.baseScale * Math.pow(1.02, 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)
+ {
+ console.log("PREPARE");
+ console.log(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 : '<i class="fa fa-undo"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-picture',
+ action : 'picture',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-picture-o"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-right',
+ action : 'rotate-right',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-repeat"></i>'
+ }
+ ]
+ }
+ ],
+ DOCUMENT : [
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-left',
+ action : 'rotate-left',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-undo"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-download',
+ action : 'download',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-download"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-crop',
+ action : 'crop',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-crop"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-trash',
+ action : 'trash',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-trash"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-right',
+ action : 'rotate-right',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-repeat"></i>'
+ }
+ ]
+ }
+ ],
+ ROTATOR : [
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-left',
+ action : 'rotate-left',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-undo"></i>'
+ }
+ ]
+ },
+ {
+ tag : 'div',
+ cls : 'btn-group roo-upload-cropbox-rotate-right',
+ action : 'rotate-right',
+ cn : [
+ {
+ tag : 'button',
+ cls : 'btn btn-default',
+ html : '<i class="fa fa-repeat"></i>'
+ }
+ ]
+ }
+ ]
+ }
+});