/**
* FileUploader
* Copyright (c) 2017 Innostudio.de
* Website: http://innostudio.de/fileuploader/
* Version: 1.3 (21-Sep-2017)
* Requires: jQuery v1.7.1 or later
* License: https://innostudio.de/fileuploader/documentation/#license
*/
(function($) {
"use strict";
$.fn.fileuploader = function(q) {
return this.each(function(t, r) {
var s = $(r), // input element
p = null, // parent element
o = null, // new input element
l = null, // list element
sl = [], // input elements !important for addMore option
n = $.extend(true, {}, $.fn.fileuploader.defaults, q), // options
f = {
/**
* init
* initialize the plugin
*
* @void
*/
init: function() {
// create and set the parent element
if (!s.closest('.fileuploader').length)
s.wrap('
');
p = s.closest('.fileuploader');
// add, merge and apply input attributes with the options
// also define the defaults for some options
f.set('attrOpts');
// check if the plugin is supported in current browser
if (!f.isSupported()) {
n.onSupportError && $.isFunction(n.onSupportError) ? n.onSupportError(p, s) : null;
return false;
}
// before render callback
if (n.beforeRender && $.isFunction(n.beforeRender) && n.beforeRender(p, s) === false) {
return false;
}
// redesign the new input
f.redesign();
// append files from options
if (n.files)
f.files.append(n.files);
// after render callback
f.rendered = true;
n.afterRender && $.isFunction(n.afterRender) ? n.afterRender(l, p, o, s) : null;
// bind events
if (!f.disabled)
f.bindUnbindEvents(true);
},
/**
* bindUnbindEvents
* bind or unbind events for input and new elements
*
* @param {bool} bind - bind the events?
* @void
*/
bindUnbindEvents: function(bind) {
// unbind events
if (bind)
f.bindUnbindEvents(false);
// bind all input events
s[bind ? 'on' : 'off'](f._assets.getAllEvents(), f.onEvent);
// bind click event for the new input
if (n.changeInput && o!==s)
o[bind ? 'on' : 'off']('click', f.clickHandler);
// bind drag&drop events
if (f.isUploadMode() && n.dragDrop && n.dragDrop.container.length) {
n.dragDrop.container[bind ? 'on' : 'off']('drag dragstart dragend dragover dragenter dragleave drop', function(e) { e.preventDefault(); });
n.dragDrop.container[bind ? 'on' : 'off']('drop', f.dragDrop.onDrop);
n.dragDrop.container[bind ? 'on' : 'off']('dragover', f.dragDrop.onDragEnter);
n.dragDrop.container[bind ? 'on' : 'off']('dragleave', f.dragDrop.onDragLeave);
}
// bind the paste from clipboard event
if (f.isUploadMode() && n.clipboardPaste)
$(window)[bind ? 'on' : 'off']('paste', f.clipboard.paste);
// bind sorter events
if (n.sorter && n.thumbnails && n.thumbnails._selectors.sorter)
f.sorter[bind ? 'init': 'destroy']();
// bind the form reset
s.closest('form')[bind ? 'on' : 'off']('reset', f.reset);
},
/**
* redesign
* create the new input and hide the standard one
*
* @void
*/
redesign: function() {
// set as default
o = s;
// add a class name with theme
if (n.theme)
p.addClass('fileuploader-theme-' + n.theme);
// set new input html
if (n.changeInput) {
switch ((typeof n.changeInput + "").toLowerCase()) {
case 'boolean':
o = $('
' +
'
' + f._assets.textParse(n.captions.feedback) + '
' +
'
' + f._assets.textParse(n.captions.button) + '
' +
'
');
break;
case 'string':
if (n.changeInput != ' ')
o = $(f._assets.textParse(n.changeInput, n));
break;
case 'object':
o = $(n.changeInput);
break;
case 'function':
o = $(n.changeInput(s, p, n, f._assets.textParse));
break;
}
// add the new input after standard input
s.after(o);
// hide the standard input
s.css({
position: "absolute",
"z-index": "-9999",
height: '0',
width: '0',
padding: '0',
margin: '0',
"line-height": '0',
outline: '0',
border: '0',
opacity: '0'
});
}
// create thumbnails list
if (n.thumbnails)
f.thumbnails.create();
// set drag&drop container
if (n.dragDrop) {
n.dragDrop = typeof(n.dragDrop) != 'object' ? {container: null} : n.dragDrop;
n.dragDrop.container = n.dragDrop.container ? $(n.dragDrop.container) : o;
}
},
/**
* clickHandler
* click event for new input
*
* @param {Event} e - jQuery event
* @void
*/
clickHandler: function(e) {
e.preventDefault();
// clear clipboard pending
if (f.clipboard._timer) {
f.clipboard.clean();
return;
}
// trigger input click
s.click();
},
/**
* onEvent
* callbacks for each input event
*
* @param {Event} e - jQuery event
* @void
*/
onEvent: function(e) {
switch(e.type) {
case 'focus':
p ? p.addClass('fileuploader-focused') : null;
break;
case 'blur':
p ? p.removeClass('fileuploader-focused') : null;
break;
case 'change':
f.onChange.call(this);
break;
}
// listeners callback
n.listeners && $.isFunction(n.listeners[e.type]) ? n.listeners[e.type].call(s, p) : null;
},
/**
* set
* set properties
*
* @param {String} type - property type
* @param {null|String} value - property value
* @void
*/
set: function(type, value) {
switch(type) {
case 'attrOpts':
var d = ['limit', 'maxSize', 'fileMaxSize', 'extensions', 'changeInput', 'theme', 'addMore', 'listInput', 'files'];
for (var k = 0; k < d.length; k++) {
var j = 'data-fileuploader-' + d[k];
if (f._assets.hasAttr(j)) {
switch (d[k]) {
case 'changeInput':
case 'addMore':
case 'listInput':
n[d[k]] = (['true', 'false'].indexOf(s.attr(j)) > -1 ? s.attr(j) == 'true' : s.attr(j));
break;
case 'extensions':
n[d[k]] = s.attr(j)
.replace(/ /g, '')
.split(',');
break;
case 'files':
n[d[k]] = JSON.parse(s.attr(j));
break;
default:
n[d[k]] = s.attr(j);
}
}
s.removeAttr(j);
}
// set the plugin on disabled if the input has disabled attribute or limit is 0
if (s.attr('disabled') != null || s.attr('readonly') != null || n.limit === 0)
f.disabled = true;
// set multiple attribute to the input
if (!n.limit || (n.limit && n.limit >= 2)) {
s.attr('multiple', 'multiple');
// set brackets at the end of input name
n.inputNameBrackets && s.attr('name').slice(-2) != '[]' ? s.attr('name', s.attr('name') + '[]') : null;
}
// set list input element
if (n.listInput === true) {
n.listInput = $('').insertBefore(s);
}
if (typeof n.listInput == "string" && $(n.listInput).length == 0) {
n.listInput = $('').insertBefore(s);
}
// apply some defined options to plugin
f.set('disabled', f.disabled);
if (!n.fileMaxSize && n.maxSize)
n.fileMaxSize = n.maxSize;
break;
// set and apply disable option to plugin
case 'disabled':
f.disabled = value;
p[f.disabled ? 'addClass' : 'removeClass']('fileuploader-disabled');
s[f.disabled ? 'attr' : 'removeAttr']('disabled', 'disabled');
if (f.rendered)
f.bindUnbindEvents(!value);
break;
// set new input feedback html
case 'feedback':
if (!value)
value = f._assets.textParse(f._itFl.length > 0 ? n.captions.feedback2 : n.captions.feedback, {length: f._itFl.length});
$(!o.is(':file')) ? o.find('.fileuploader-input-caption span').html(value) : null;
break;
// set file input value to empty
case 'input':
var el = f._assets.copyAllAttributes($(''), s, true);
f.bindUnbindEvents(false);
s.after(s = el).remove();
f.bindUnbindEvents(true);
break;
// set previous input; only for addMore option
case 'prevInput':
if (sl.length > 0) {
f.bindUnbindEvents(false);
sl[value].remove();
sl.splice(value, 1);
s = sl[sl.length - 1];
f.bindUnbindEvents(true);
}
break;
// set next input; only for addMore option
case 'nextInput':
var el = f._assets.copyAllAttributes($(''), s);
f.bindUnbindEvents(false);
if (sl.length > 0 && sl[sl.length - 1].get(0).files.length == 0) {
s = sl[sl.length - 1];
} else {
sl.indexOf(s) == -1 ? sl.push(s) : null;
sl.push(el);
s.after(s = el);
}
f.bindUnbindEvents(true);
break;
// set list input with list of the files
case 'listInput':
if (n.listInput)
n.listInput.val(f.files.list(true, null, false, value));
break;
}
},
/**
* onChange
* on input change event
*
* @param {Event} e - jQuery event
* @param {Array} fileList - FileList array, used only by drag&drop and clipboard paste
* @void
*/
onChange: function(e, fileList) {
var files = s.get(0).files;
// drag&drop or clipboard paste
if (fileList) {
if (fileList.length) {
files = fileList;
} else {
f.set('input', '');
f.files.clear();
return false;
}
}
// clean clipboard timer
// made only for safety
if (f.clipboard._timer)
f.clipboard.clean();
// reset the input if default mode
if (f.isDefaultMode()) {
f.reset();
if (files.length == 0)
return;
}
// beforeSelect callback
if (n.beforeSelect && $.isFunction(n.beforeSelect) && n.beforeSelect(files, l, p, o, s) == false) {
return false;
}
// files
var t = 0; // total processed files
for (var i = 0; i < files.length; i++ ) {
var file = files[i], // file
item = f._itFl[f.files.add(file, 'choosed')], // item
status = f.files.check(item, files, i == 0); // ["type", "message", "do not show the warning message", "do not check the next files"]
// process the warnings
if (status !== true) {
f.files.remove(item, true);
if (!status[2]) {
if (f.isDefaultMode()) {
f.set('input', '');
f.reset();
status[3] = true;
}
status[1] ? n.dialogs.alert(status[1], item, l, p, o, s) : null;
}
if (status[3]) {
break;
}
continue;
}
// file is valid
// create item html
if (n.thumbnails)
f.thumbnails.item(item);
// create item ajax request
if (f.isUploadMode())
f.upload.prepare(item);
// onSelect callback
n.onSelect && $.isFunction(n.onSelect) ? n.onSelect(item, l, p, o, s) : null;
t++;
}
// clear the input in uploadMode
if (f.isUploadMode() && t > 0)
f.set('input', '');
// set feedback caption
f.set('feedback', null);
// set nextInput for addMore option
if (f.isAddMoreMode() && t > 0) {
f.set('nextInput');
}
// set listInput value
f.set('listInput', null);
// afterSelect callback
n.afterSelect && $.isFunction(n.afterSelect) ? n.afterSelect(l, p, o, s) : null;
},
/**
* @namespace thumbnails
*/
thumbnails: {
/**
* create
* create the thumbnails list
*
* @namespace thumbnails
* @void
*/
create: function() {
// thumbnails.beforeShow callback
n.thumbnails.beforeShow != null && $.isFunction(n.thumbnails.beforeShow) ? n.thumbnails.beforeShow(p, o, s) : null;
// create item's list element
var box = $(f._assets.textParse(n.thumbnails.box)).appendTo(n.thumbnails.boxAppendTo ? n.thumbnails.boxAppendTo : p);
l = !box.is(n.thumbnails._selectors.list) ? box.find(n.thumbnails._selectors.list) : box;
// bind item popup method to the selector
if (n.thumbnails._selectors.popup_open) {
l.on('click', n.thumbnails._selectors.popup_open, function(e) {
e.preventDefault();
var m = $(this).closest(n.thumbnails._selectors.item),
item = f.files.find(m);
if (item && item.html.hasClass('file-has-popup'))
f.thumbnails.popup(item);
});
}
// bind item upload start method to the selector
if (f.isUploadMode() && n.thumbnails._selectors.start) {
l.on('click', n.thumbnails._selectors.start, function(e) {
e.preventDefault();
if (f.locked)
return false;
var m = $(this).closest(n.thumbnails._selectors.item),
item = f.files.find(m);
if (item)
f.upload.send(item, true);
});
}
// bind item upload retry method to the selector
if (f.isUploadMode() && n.thumbnails._selectors.retry) {
l.on('click', n.thumbnails._selectors.retry, function(e) {
e.preventDefault();
if (f.locked)
return false;
var m = $(this).closest(n.thumbnails._selectors.item),
item = f.files.find(m);
if (item)
f.upload.retry(item);
});
}
// bind item remove / upload.cancel method to the selector
if (n.thumbnails._selectors.remove) {
l.on('click', n.thumbnails._selectors.remove, function(e) {
e.preventDefault();
if (f.locked)
return false;
var m = $(this).closest(n.thumbnails._selectors.item),
item = f.files.find(m),
c = function(a) {
f.files.remove(item);
};
if (item) {
if (item.upload && item.upload.status != 'successful') {
f.upload.cancel(item);
} else {
if (n.thumbnails.removeConfirmation && !($(n.listInput[0]).attr('data-immidiate-remove'))) {
n.dialogs.confirm(f._assets.textParse(n.captions.removeConfirmation, item), c);
} else {
c();
}
}
}
});
}
},
/**
* clear
* set the HTML content from items list to empty
*
* @namespace thumbnails
* @void
*/
clear: function() {
if (l)
l.html('');
},
/**
* item
* create the item.html and append it to the list
*
* @namespace thumbnails
* @param {Object} item
* @void
*/
item: function(item) {
item.icon = f.thumbnails.generateFileIcon(item.format, item.extension);
item.image = '';
item.progressBar = f.isUploadMode() ? '
' : '';
item.html = $(f._assets.textParse(item.appended && n.thumbnails.item2 ? n.thumbnails.item2 : n.thumbnails.item, item));
item.progressBar = item.html.find('.fileuploader-progressbar');
// add class with file extension and file format to item html
item.html.addClass('file-type-' + (item.format ? item.format : 'no') + ' file-ext-' + (item.extension ? item.extension : 'no') + '');
// add item html to list element
item.html[n.thumbnails.itemPrepend ? 'prependTo' : 'appendTo'](l);
// render the image thumbnail
f.thumbnails.renderThumbnail(item);
item.renderThumbnail = function(src) { f.thumbnails.renderThumbnail(item, true, src); };
item.popup = { open: function() { f.thumbnails.popup(item); } };
// thumbnails.onItemShow callback
n.thumbnails.onItemShow != null && $.isFunction(n.thumbnails.onItemShow) ? n.thumbnails.onItemShow(item, l, p, o, s) : null;
},
/**
* generateFileIcon
* generate a file icon with custom background color
*
* @namespace thumbnails
* @param {String} form - file format
* @param {String} extension - file extension
* @return {String} html element
*/
generateFileIcon: function(format, extension) {
var el = '
' + (extension ? extension : '') + '
';
// set generated color to icon background
var bgColor = f._assets.textToColor(extension);
if (bgColor) {
var isBgColorBright = f._assets.isBrightColor(bgColor);
if (isBgColorBright)
el = el.replace('${class}', ' is-bright-color');
el = el.replace('${style}', 'background-color: ' + bgColor);
}
return el.replace('${style}', '').replace('${class}', '');
},
/**
* renderThumbnail
* render image thumbnail and append to .fileuploader-item-image element
* it appends the generated icon if the file is not an image or not a valid image
*
* @namespace thumbnails
* @param {Object} item
* @param {bool} forceRender - skip the synchron functions and force the rendering
* @param {string} src - custom image source
* @void
*/
renderThumbnail: function(item, forceRender, src) {
var m = item.html.find('.fileuploader-item-image'),
readerSkip = item.data && item.data.readerSkip,
setImageThumb = function(img) {
var $img = $(img);
// add $img to html
m.removeClass('fileuploader-no-thumbnail fileuploader-loading').html($img);
// add onImageLoaded callback
if ($img.is('img'))
$img.attr('draggable', 'false').on('load error', function(e) {
if (e.type == 'error')
setIconThumb(true);
renderNextItem();
n.thumbnails.onImageLoaded != null && $.isFunction(n.thumbnails.onImageLoaded) ? n.thumbnails.onImageLoaded(item, l, p, o, s) : null;
});
if ($img.is('canvas'))
n.thumbnails.onImageLoaded != null && $.isFunction(n.thumbnails.onImageLoaded) ? n.thumbnails.onImageLoaded(item, l, p, o, s) : null;
},
setIconThumb = function(onImageError) {
m.addClass('fileuploader-no-thumbnail');
m.removeClass('fileuploader-loading').html(item.icon);
if (onImageError)
n.thumbnails.onImageLoaded != null && $.isFunction(n.thumbnails.onImageLoaded) ? n.thumbnails.onImageLoaded(item, l, p, o, s) : null;
},
renderNextItem = function() {
var i = 0;
if (item && f._pfrL.indexOf(item) > -1) {
f._pfrL.splice(f._pfrL.indexOf(item), 1);
while (i < f._pfrL.length) {
if (f._itFl.indexOf(f._pfrL[i]) > -1) {
f.thumbnails.renderThumbnail(f._pfrL[i], true);
break;
} else {
f._pfrL.splice(i, 1);
}
i++;
}
}
};
// skip this function if there is no place for image
if (!m.length) {
renderNextItem();
return;
}
// set item.image to jQuery element
item.image = m;
// create an image thumbnail only if file is an image and if FileReader is supported
if (['image', 'video', 'audio', 'astext'].indexOf(item.format) > -1 && f.isFileReaderSupported() && !readerSkip && (item.appended || n.thumbnails.startImageRenderer || forceRender)) {
// check pending list
if (n.thumbnails.synchronImages) {
f._pfrL.indexOf(item) == -1 && !forceRender ? f._pfrL.push(item) : null;
if (f._pfrL.length > 1 && !forceRender) {
return;
}
}
// create thumbnail
var load = function(data, fromReader) {
var srcIsImg = data.nodeName && data.nodeName.toLocaleLowerCase() == 'img',
src = !srcIsImg ? data : data.src;
if (n.thumbnails.canvasImage) {
var canvas = document.createElement('canvas'),
img = srcIsImg ? data : new Image(),
onload = function() {
// resize canvas
f.editor.resize(img, canvas, n.thumbnails.canvasImage.width ? n.thumbnails.canvasImage.width : m.width(), n.thumbnails.canvasImage.height ? n.thumbnails.canvasImage.height : m.height(), false, true);
// check if canvas is not blank
if (!f._assets.isBlankCanvas(canvas)) {
setImageThumb(canvas);
} else {
setIconThumb();
}
// render the next pending item
renderNextItem();
},
onerror = function(text) {
setIconThumb(true);
renderNextItem();
img = null;
};
// do not create another image element
if (item.format == 'image' && fromReader && item.reader.node) {
img = item.reader.node;
return onload();
}
// do not create an empty image element
if(!src)
return onerror();
if (srcIsImg)
return onload.call(data);
// create image element
img.onload = onload;
img.onerror = onerror;
if (item.data && item.data.readerCrossOrigin)
img.setAttribute('crossOrigin', item.data.readerCrossOrigin);
img.src = src;
} else {
setImageThumb(srcIsImg ? data : '');
}
};
// choose thumbnail source
if (src)
return load(src);
else
return f.files.read(item, function() {
var fileIsPictureMedia = item.format == 'image' || item.format == 'video';
if (item.reader.node && n.thumbnails.popup)
item.html.addClass('file-has-popup');
if (item.reader.node && fileIsPictureMedia) {
load(item.reader.frame || item.reader.src, true);
} else {
setIconThumb(fileIsPictureMedia);
renderNextItem();
}
});
}
setIconThumb();
},
/**
* popup
* create and show a popup for an item
* appends the popup to parent element
* reset values for the editor
*
* @namespace thumbnails
* @param {Object} item
* @void
*/
popup: function(item) {
if (!n.thumbnails.popup || !n.thumbnails._selectors.popup)
return;
// remove all created popups
if (p.find(n.thumbnails._selectors.popup).length) {
$.each(f._itFl, function(i, a) {
if (a.popup && a.popup.close) {
a.popup.close();
}
});
}
var template = item.popup.html || $(f._assets.textParse(n.thumbnails.popup.template, item)),
popupIsNew = item.popup.html !== template,
windowResizeEvent = function() {
var $parent = item.popup.html.find('.fileuploader-popup-preview'),
$node = $parent.find('.node'),
$tools = $parent.find('.tools'),
$childEl = $node.find('> *'),
height = $parent.height() - $tools.outerHeight(true);
// get child height
$node.css({height: '100%'});
if ($childEl && height > $childEl.outerHeight())
height = $childEl.outerHeight();
$node.css({
height: height
});
},
windowKeyEvent = function(e) {
var key = e.which || e.keyCode;
if (key == 27 && item.popup && item.popup.close)
item.popup.close();
};
template.show().appendTo(p);
item.popup.html = template;
item.popup.close = function() {
if (item.reader.node) {
item.reader.node.pause ? item.reader.node.pause() : null;
}
$(window).off('keyup', windowKeyEvent);
$(window).off('resize', windowResizeEvent);
// hide the cropper
if (item.popup.editor && item.popup.editor.cropper)
item.popup.editor.cropper.hide();
// thumbnails.popup.onHide callback
item.popup.html && n.thumbnails.popup.onHide && $.isFunction(n.thumbnails.popup.onHide) ? n.thumbnails.popup.onHide(item, l, p, o, s) : (item.popup.html ? item.popup.html.remove() : null);
delete item.popup.close;
};
// append item.reader.node to popup
// play video/audio
if (item.reader.node) {
if (popupIsNew)
template.find('.fileuploader-popup-preview .node').html(item.reader.node);
item.reader.node.controls = true;
item.reader.node.currentTime = 0;
item.reader.node.play ? item.reader.node.play() : null;
}
// bind Window functions
$(window).on('keyup', windowKeyEvent);
$(window).on('resize', windowResizeEvent);
windowResizeEvent.call();
// IE dirty fix
setTimeout(function() {
windowResizeEvent.call();
}, 10);
// popup editor
if (item.editor && item.popup.editor && item.popup.editor.hasChanges) {
// set saved rotation
if (item.popup.editor && item.popup.editor.rotation)
f.editor.rotate(item, item.editor.rotation || 0, true);
// set saved crop
if (item.popup.editor && item.popup.editor.cropper) {
item.popup.editor.cropper.hide(true);
setTimeout(function() {
f.editor.crop(item, item.editor.crop ? $.extend({}, item.editor.crop) : item.popup.editor.cropper.setDefaultData());
}, 100);
}
} else {
item.popup.editor = {};
}
// thumbnails.popup.onShow callback
n.thumbnails.popup.onShow && $.isFunction(n.thumbnails.popup.onShow) ? n.thumbnails.popup.onShow(item, l, p, o, s) : null;
}
},
/**
* @namespace editor
*/
editor: {
/**
* rotate
* rotate image action
* animate rotation in popup, only when popup is enabled
*
* @namespace editor
* @param {Object} item
* @param {Number} degrees - rotation degrees
* @param {Boolean} force - force rotation without animation to degrees
* @void
*/
rotate: function(item, degrees, force) {
var inPopup = item.popup && typeof item.popup.html !== "undefined";
if (!inPopup) {
var rotation = item.editor.rotation || 0;
return item.editor.rotation = degrees ? degrees : rotation + 90;
} else {
// prevent animation issues
if (item.popup.editor.isAnimating)
return;
item.popup.editor.isAnimating = true;
var $popup = item.popup.html,
$node = $popup.find('.node'),
$imageEl = $node.find('> img'),
rotation = item.popup.editor.rotation || 0,
scale = item.popup.editor.scale || 1,
animationObj = {
rotation: rotation,
scale: scale
};
// hide cropper
if (item.popup.editor.cropper)
item.popup.editor.cropper.$template.hide();
// change values
item.popup.editor.rotation = force ? degrees : rotation + 90;
item.popup.editor.scale = ($node.height() / $imageEl[[90,270].indexOf(item.popup.editor.rotation) > -1 ? 'width' : 'height']()).toFixed(3);
if ($imageEl.height() * item.popup.editor.scale > $node.width() && [90,270].indexOf(item.popup.editor.rotation) > -1)
item.popup.editor.scale = $node.width() / $imageEl.height();
if (item.popup.editor.scale > 1)
item.popup.editor.scale = 1;
// animate
$(animationObj).animate({
rotation: item.popup.editor.rotation,
scale: item.popup.editor.scale
}, {
duration: force ? 1 : 300,
easing: 'swing',
step: function(now, fx) {
var matrix = $imageEl.css('-webkit-transform') || $imageEl.css('-moz-transform') || $imageEl.css('transform') || 'none',
rotation = 0,
scale = 1,
prop = fx.prop;
// get css matrix
if (matrix !== 'none') {
var values = matrix.split('(')[1].split(')')[0].split(','),
a = values[0],
b = values[1];
rotation = prop == 'rotation' ? now : Math.round(Math.atan2(b, a) * (180/Math.PI));
scale = prop == 'scale' ? now : Math.round(Math.sqrt(a*a + b*b) * 10) / 10;
}
// set $imageEl css
$imageEl.css({
'-webkit-transform': 'rotate('+ rotation +'deg) scale('+ scale +')',
'-moz-transform': 'rotate('+ rotation +'deg) scale('+ scale +')',
'transform': 'rotate('+ rotation +'deg) scale('+ scale +')'
});
},
always: function() {
delete item.popup.editor.isAnimating;
// re-draw the cropper if exists
if (item.popup.editor.cropper && !force) {
item.popup.editor.cropper.setDefaultData();
item.popup.editor.cropper.init('rotation');
}
}
});
// check if rotation no greater than 360 degrees
if (item.popup.editor.rotation >= 360)
item.popup.editor.rotation = 0;
// register as change
if (item.popup.editor.rotation != item.editor.rotation)
item.popup.editor.hasChanges = true;
}
},
/**
* crop
* crop image action
* show cropping tools, only when popup is enabled
*
* @namespace editor
* @param {Object} item
* @param {Object} data - cropping data
* @void
*/
crop: function(item, data) {
var inPopup = item.popup && typeof item.popup.html !== "undefined";
if (!inPopup) {
return item.editor.crop = data || item.editor.crop;
} else {
if (!item.popup.editor.cropper) {
var template = '
Pasting a file, click here to cancel.',
removeConfirmation: '
Pasting a file, click here to cancel.',
errors: {
filesLimit: 'Only ${limit} files are allowed to be uploaded.',
filesType: 'Only ${extensions} files are allowed to be uploaded.',
fileSize: '${name} is too large! Please choose a file up to ${fileMaxSize}MB.',
filesSizeAll: 'Files that you chose are too large! Please upload files up to ${maxSize} MB.',
fileName: 'File with the name ${name} is already selected.',
folderUpload: 'You are not allowed to upload folders.'
}
}
}
})(jQuery);