Files
think-greaterchiangmai/think-backend.greaterchiangmai.com/public/assets/plugins/fileuploader-2.2/src/jquery.fileuploader.js
T
2025-11-11 14:55:29 +07:00

4977 lines
226 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Fileuploader
* Copyright (c) 2019 Innostudio.de
* Website: https://innostudio.de/fileuploader/
* Version: 2.2 (23-Nov-2019)
* 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('<div class="fileuploader"></div>');
p = s.closest('.fileuploader');
// extend captions object
f.set('language');
// 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);
if (!f._itFl.length)
f.reset();
},
/**
* 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 (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 = $('<div class="fileuploader-input">' +
'<div class="fileuploader-input-caption"><span>' + f._assets.textParse(n.captions.feedback) + '</span></div>' +
'<button type="button" class="fileuploader-input-button"><span>' + f._assets.textParse(n.captions.button) + '</span></button>' +
'</div>');
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 = $('<input type="hidden" name="fileuploader-list-' + s.attr('name').replace('[]', '').split('[').pop().replace(']', '') + '">').insertBefore(s);
}
if (typeof n.listInput == "string" && $(n.listInput).length == 0) {
n.listInput = $('<input type="hidden" name="' + 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;
// extend captions object
case 'language':
var languages = $.fn.fileuploader.languages;
if (typeof n.captions == 'string') {
if (n.captions in languages)
n.captions = languages[n.captions];
else
n.captions = $.extend(true, {}, $.fn.fileuploader.defaults.captions);
}
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($('<input type="file">'), 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($('<input type="file">'), 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] ? f._assets.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.popup && 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 editor rotate method to the selector
if (n.thumbnails._selectors.rotate) {
l.on('click', n.thumbnails._selectors.rotate, function(e) {
e.preventDefault();
if (f.locked)
return false;
var m = $(this).closest(n.thumbnails._selectors.item),
item = f.files.find(m);
if (item && item.editor) {
item.editor.rotate();
item.editor.save();
}
});
}
// 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 && !item.choosed) {
f._assets.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
* @param {HTML} replaceHtml
* @void
*/
item: function(item, replaceHtml) {
item.icon = f.thumbnails.generateFileIcon(item.format, item.extension);
item.image = '<div class="fileuploader-item-image"></div>';
item.progressBar = f.isUploadMode() ? '<div class="fileuploader-progressbar"><div class="bar"></div></div>' : '';
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
if (replaceHtml)
replaceHtml.replaceWith(item.html);
else
item.html[n.thumbnails.itemPrepend ? 'prependTo' : 'appendTo'](l);
// add popup option
if (n.thumbnails.popup && item.data.popup !== false) {
item.html.addClass('file-has-popup');
item.popup = {
open: function() { f.thumbnails.popup(item); }
};
}
// render the image thumbnail
f.thumbnails.renderThumbnail(item);
item.renderThumbnail = function(src) {
if (src && item.popup && item.popup.close) {
item.popup.close();
item.popup = { open: item.popup.open };
}
f.thumbnails.renderThumbnail(item, true, src);
};
// 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 = '<div style="${style}" class="fileuploader-item-icon' + '${class}"><i>' + (extension ? extension : '') + '</i></div>';
// 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);
if (item.html.hasClass('file-will-popup')) item.html.removeClass('file-will-popup').addClass('file-has-popup');
// add onImageLoaded callback
if ($img.is('img'))
$img.attr('draggable', 'false').on('load error', function(e) {
if (e.type == 'error')
setIconThumb();
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() {
m.addClass('fileuploader-no-thumbnail');
m.removeClass('fileuploader-loading').html(item.icon);
if (item.html.hasClass('file-will-popup')) item.html.removeClass('file-will-popup').addClass('file-has-popup');
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) {
setTimeout(function() {
f.thumbnails.renderThumbnail(f._pfrL[i], true);
}, item.format == 'image' && item.size/1000000 > 1.8 ? 200 : 0);
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.html('').addClass('fileuploader-loading');
// create an image thumbnail only if file is an image and if FileReader is supported
if ((['image', 'video', 'audio', 'astext'].indexOf(item.format) > -1 || item.data.thumbnail) && f.isFileReaderSupported() && !readerSkip && (item.appended || n.thumbnails.startImageRenderer || forceRender)) {
// prevent popup before loading
if (item.html.hasClass('file-has-popup'))
item.html.removeClass('file-has-popup').addClass('file-will-popup');
// 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.toLowerCase() == '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(this, 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();
renderNextItem();
img = null;
};
// do not create another image element
if (item.format == 'image' && fromReader && item.reader.node)
return onload.call(item.reader.node);
// 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 : '<img src="'+ src +'">');
}
};
// choose thumbnail source
if (typeof src == 'string' || typeof src == 'object')
return load(src);
else
return f.files.read(item, function() {
if (item.reader.node && (item.reader.frame || item.reader.node.nodeName.toLowerCase() == 'img')) {
load(item.reader.frame || item.reader.src, true);
} else {
setIconThumb();
renderNextItem();
}
}, null, src, true);
}
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
* @param {Boolean} isByAction - popup is called by prev/next buttons
* @void
*/
popup: function(item, isByActions) {
if (f.locked || !n.thumbnails.popup || !n.thumbnails._selectors.popup)
return;
var container = $(n.thumbnails.popup.container),
box = container.find('.fileuploader-popup'),
hasArrowsClass = 'fileuploader-popup-has-arrows',
renderPopup = function() {
var template = item.popup.html || $(f._assets.textParse(n.thumbnails.popup.template, item)),
popupIsNew = item.popup.html !== template,
windowKeyEvent = function(e) {
var key = e.which || e.keyCode;
if (key == 27 && item.popup && item.popup.close)
item.popup.close();
if ((key == 37 || key == 39) && n.thumbnails.popup.arrows)
item.popup.move(key == 37 ? 'prev' : 'next');
};
box.removeClass('loading');
// remove all created popups
if (box.children(n.thumbnails._selectors.popup).length) {
$.each(f._itFl, function(i, a) {
if (a != item && a.popup && a.popup.close) {
a.popup.close(isByActions);
}
});
box.find(n.thumbnails._selectors.popup).remove();
}
template.show().appendTo(box);
item.popup.html = template;
item.popup.move = function(to) {
var itemIndex = f._itFl.indexOf(item),
nextItem = null,
itL = false;
to = n.thumbnails.itemPrepend ? to == 'prev' ? 'next' : 'prev' : to;
if (to == 'prev') {
for (var i = itemIndex; i>=0; i--) {
var a = f._itFl[i];
if (a != item && a.popup && a.html.hasClass('file-has-popup')) {
nextItem = a;
break;
}
if (i == 0 && !nextItem && !itL && n.thumbnails.popup.loop) {
i = f._itFl.length;
itL = true;
}
}
} else {
for (var i = itemIndex; i<f._itFl.length; i++) {
var a = f._itFl[i];
if (a != item && a.popup && a.html.hasClass('file-has-popup')) {
nextItem = a;
break;
}
if (i+1 == f._itFl.length && !nextItem && !itL && n.thumbnails.popup.loop) {
i = -1;
itL = true;
}
}
}
if (nextItem)
f.thumbnails.popup(nextItem, true);
};
item.popup.close = function(isByActions) {
if (item.reader.node) {
item.reader.node.pause ? item.reader.node.pause() : null;
}
$(window).off('keyup', windowKeyEvent);
container.css({
overflow: '',
width: ''
});
// hide the cropper
if (item.popup.editor && item.popup.editor.cropper)
item.popup.editor.cropper.hide();
// hide the zoomer
if (item.popup.zoomer)
item.popup.zoomer.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);
if (!isByActions)
box.fadeOut(400, function() {
box.remove();
});
delete item.popup.close;
};
// append item.reader.node to popup
// play video/audio
if (item.reader.node) {
if (popupIsNew)
template.html(template.html().replace(/\$\{reader\.node\}/, '<div class="reader-node"></div>')).find('.reader-node').html(item.reader.node);
item.reader.node.controls = true;
item.reader.node.currentTime = 0;
item.reader.node.play ? item.reader.node.play() : null;
} else {
if (popupIsNew)
template.find('.fileuploader-popup-node').html('<div class="reader-node"><div class="fileuploader-popup-file-icon">' + item.icon + '</div></div>');
}
// bind Window functions
$(window).on('keyup', windowKeyEvent);
// freeze the container
container.css({
overflow: 'hidden',
width: container.innerWidth()
});
// popup arrows
item.popup.html.find('[data-action="prev"], [data-action="next"]').removeAttr('style');
item.popup.html[f._itFl.length == 1 || !n.thumbnails.popup.arrows ? 'removeClass' : 'addClass'](hasArrowsClass);
if (!n.thumbnails.popup.loop) {
if (f._itFl.indexOf(item) == 0)
item.popup.html.find('[data-action="prev"]').hide();
if (f._itFl.indexOf(item) == f._itFl.length-1)
item.popup.html.find('[data-action="next"]').hide();
}
// popup zoomer
f.editor.zoomer(item);
// popup editor
if (item.editor) {
if (!item.popup.editor)
item.popup.editor = {};
// set saved rotation
f.editor.rotate(item, item.popup.editor.rotation || 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);
}
}
// bind actions
item.popup.html.on('click', '[data-action="prev"]', function(e) {
item.popup.move('prev');
}).on('click', '[data-action="next"]', function(e) {
item.popup.move('next');
}).on('click', '[data-action="crop"]', function(e) {
if (item.editor)
item.editor.cropper();
}).on('click', '[data-action="rotate-cw"]', function(e) {
if (item.editor)
item.editor.rotate();
}).on('click', '[data-action="zoom-in"]', function(e) {
if (item.popup.zoomer)
item.popup.zoomer.zoomIn();
}).on('click', '[data-action="zoom-out"]', function(e) {
if (item.popup.zoomer)
item.popup.zoomer.zoomOut();
});
// thumbnails.popup.onShow callback
n.thumbnails.popup.onShow && $.isFunction(n.thumbnails.popup.onShow) ? n.thumbnails.popup.onShow(item, l, p, o, s) : null;
};
if (box.length == 0)
box = $('<div class="fileuploader-popup"></div>').appendTo(container);
box.fadeIn(400).addClass('loading');
if ((['image', 'video', 'audio', 'astext'].indexOf(item.format) > -1 || ['application/pdf'].indexOf(item.type) > -1) && !item.popup.html) {
f.files.read(item, renderPopup);
} else {
renderPopup();
}
}
},
/**
* @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 && item.popup.html && $('html').find(item.popup.html).length;
if (!inPopup) {
var rotation = item.editor.rotation || 0,
deg = degrees ? degrees : rotation + 90;
if (deg >= 360)
deg = 0;
if (item.popup.editor)
item.popup.editor.rotation = deg;
return item.editor.rotation = deg;
} else if (item.reader.node) {
// prevent animation issues
if (item.popup.editor.isAnimating)
return;
item.popup.editor.isAnimating = true;
var $popup = item.popup.html,
$node = $popup.find('.fileuploader-popup-node'),
$readerNode = $node.find('.reader-node'),
$imageEl = $readerNode.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 = ($readerNode.height() / $imageEl[[90,270].indexOf(item.popup.editor.rotation) > -1 ? 'width' : 'height']()).toFixed(3);
if ($imageEl.height() * item.popup.editor.scale > $readerNode.width() && [90,270].indexOf(item.popup.editor.rotation) > -1)
item.popup.editor.scale = $readerNode.height() / $imageEl.width();
if (item.popup.editor.scale > 1)
item.popup.editor.scale = 1;
// animate
$(animationObj).stop().animate({
rotation: item.popup.editor.rotation,
scale: item.popup.editor.scale
}, {
duration: force ? 2 : 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 && item.popup.html && $('html').find(item.popup.html).length;
if (!inPopup) {
return item.editor.crop = data || item.editor.crop;
} else if (item.reader.node) {
if (!item.popup.editor.cropper) {
var template = '<div class="fileuploader-cropper">' +
'<div class="fileuploader-cropper-area">' +
'<div class="point point-a"></div>' +
'<div class="point point-b"></div>' +
'<div class="point point-c"></div>' +
'<div class="point point-d"></div>' +
'<div class="point point-e"></div>' +
'<div class="point point-f"></div>' +
'<div class="point point-g"></div>' +
'<div class="point point-h"></div>' +
'<div class="area-move"></div>' +
'<div class="area-image"></div>' +
'<div class="area-info"></div>' +
'</div>' +
'</div>',
$popup = item.popup.html,
$imageEl = $popup.find('.fileuploader-popup-node .reader-node > img'),
$template = $(template),
$editor = $template.find('.fileuploader-cropper-area');
// define popup cropper tool
item.popup.editor.cropper = {
$imageEl: $imageEl,
$template: $template,
$editor: $editor,
isCropping: false,
crop: data || null,
init: function(data) {
var cropper = item.popup.editor.cropper,
position = cropper.$imageEl.position(),
width = cropper.$imageEl[0].getBoundingClientRect().width,
height = cropper.$imageEl[0].getBoundingClientRect().height,
isInverted = item.popup.editor.rotation && [90,270].indexOf(item.popup.editor.rotation) > -1,
scale = isInverted ? item.popup.editor.scale : 1;
// unbind all events
cropper.hide();
// set default data
if (!cropper.crop)
cropper.setDefaultData();
// hide if image not visible
if (width == 0 || height == 0)
return cropper.hide(true);
// prevent duplicates
if (!cropper.isCropping) {
cropper.$imageEl.clone().appendTo(cropper.$template.find('.area-image'));
cropper.$imageEl.parent().append($template);
}
// animate cropping tool
cropper.$template.hide().css({
left: position.left,
top: position.top,
width: width,
height: height
}).fadeIn(150);
cropper.$editor.hide();
clearTimeout(cropper._editorAnimationTimeout);
cropper._editorAnimationTimeout = setTimeout(function() {
delete cropper._editorAnimationTimeout;
cropper.$editor.fadeIn(250);
// update data with cf and scale
if (item.editor.crop && $.isPlainObject(data)) {
cropper.resize();
cropper.crop.left = cropper.crop.left * cropper.crop.cfWidth * scale;
cropper.crop.width = cropper.crop.width * cropper.crop.cfWidth * scale;
cropper.crop.top = cropper.crop.top * cropper.crop.cfHeight * scale;
cropper.crop.height = cropper.crop.height * cropper.crop.cfHeight * scale;
}
// maxWidth on open
if (n.editor.cropper && (n.editor.cropper.maxWidth || n.editor.cropper.maxHeight)) {
if (n.editor.cropper.maxWidth)
cropper.crop.width = Math.min(n.editor.cropper.maxWidth * cropper.crop.cfWidth, cropper.crop.width);
if (n.editor.cropper.maxHeight)
cropper.crop.height = Math.min(n.editor.cropper.maxHeight * cropper.crop.cfHeight, cropper.crop.height);
if ((!item.editor.crop || data == 'rotation') && data != 'resize') {
cropper.crop.left = (cropper.$template.width() - cropper.crop.width) / 2;
cropper.crop.top = (cropper.$template.height() - cropper.crop.height) / 2;
}
}
// ratio on open
if ((!item.editor.crop || data == 'rotation') && (n.editor.cropper && n.editor.cropper.ratio && data != 'resize')) {
var ratio = n.editor.cropper.ratio,
ratioPx = f._assets.ratioToPx(cropper.crop.width, cropper.crop.height, ratio);
if (ratioPx) {
cropper.crop.width = Math.min(cropper.crop.width, ratioPx[0]);
cropper.crop.left = (cropper.$template.width() - cropper.crop.width) / 2;
cropper.crop.height = Math.min(cropper.crop.height, ratioPx[1]);
cropper.crop.top = (cropper.$template.height() - cropper.crop.height) / 2;
}
}
// draw editor
cropper.drawPlaceHolder(cropper.crop);
}, 400);
// start and bind events
if (n.editor.cropper && n.editor.cropper.showGrid)
cropper.$editor.addClass('has-grid');
cropper.$imageEl.attr('draggable', 'false');
cropper.$template.on('mousedown touchstart', cropper.mousedown);
$(window).on('resize', cropper.resize);
// register as changed
cropper.isCropping = true;
item.popup.editor.hasChanges = true;
},
setDefaultData: function() {
var cropper = item.popup.editor.cropper,
$imageEl = cropper.$imageEl,
width = $imageEl.width(),
height = $imageEl.height(),
isInverted = item.popup.editor.rotation && [90,270].indexOf(item.popup.editor.rotation) > -1,
scale = item.popup.editor.scale || 1;
// set default data
cropper.crop = {
left: 0,
top: 0,
width: isInverted ? height * scale : width,
height: isInverted ? width * scale : height,
cfWidth: width / item.reader.width,
cfHeight: height / item.reader.height
};
return null;
},
hide: function(force) {
var cropper = item.popup.editor.cropper;
// hide editor on force
if (force) {
cropper.$template.hide();
cropper.$editor.hide();
}
// stop and unbind events
cropper.$imageEl.attr('draggable', '');
cropper.$template.off('mousedown touchstart', cropper.mousedown);
$(window).off('resize', cropper.resize);
},
resize: function(e) {
var cropper = item.popup.editor.cropper,
$imageEl = cropper.$imageEl;
// only when image is visible
if ($imageEl.width() > 0) {
if (!e) {
// re-write cf
cropper.crop.cfWidth = $imageEl.width() / item.reader.width;
cropper.crop.cfHeight = $imageEl.height() / item.reader.height;
} else {
// resize $editor
cropper.$template.hide();
clearTimeout(cropper._resizeTimeout);
cropper._resizeTimeout = setTimeout(function() {
delete cropper._resizeTimeout;
var cfWidth = $imageEl.width() / item.reader.width,
cfHeight = $imageEl.height() / item.reader.height;
cropper.crop.left = cropper.crop.left / cropper.crop.cfWidth * cfWidth;
cropper.crop.width = cropper.crop.width / cropper.crop.cfWidth * cfWidth;
cropper.crop.top = cropper.crop.top / cropper.crop.cfHeight * cfHeight;
cropper.crop.height = cropper.crop.height / cropper.crop.cfHeight * cfHeight;
cropper.crop.cfWidth = cfWidth;
cropper.crop.cfHeight = cfHeight;
cropper.init('resize');
}, 500);
}
}
},
drawPlaceHolder: function(css) {
var cropper = item.popup.editor.cropper,
rotation = item.popup.editor.rotation || 0,
scale = item.popup.editor.scale || 1,
translate = [0, 0];
if (!css)
return;
// create new object
css = $.extend({}, css);
// edit width, height and translate values by rotation
if (rotation)
translate = [rotation == 180 || rotation == 270 ? -100 : 0, rotation == 90 || rotation == 180 ? -100 : 0];
// draw cropping-area
cropper.$editor.css(css);
cropper.setAreaInfo();
cropper.$editor.find('.area-image img').removeAttr('style').css({
width: cropper.$imageEl.width(),
height: cropper.$imageEl.height(),
left: cropper.$editor.position().left * -1,
top: cropper.$editor.position().top * -1,
'-webkit-transform': 'rotate('+ rotation +'deg) scale('+ scale +') translateX('+ translate[0] +'%) translateY('+ translate[1] +'%)',
'-moz-transform': 'rotate('+ rotation +'deg) scale('+ scale +') translateX('+ translate[0] +'%) translateY('+ translate[1] +'%)',
'transform': 'rotate('+ rotation +'deg) scale('+ scale +') translateX('+ translate[0] +'%) translateY('+ translate[1] +'%)'
});
},
setAreaInfo: function(type) {
var cropper = item.popup.editor.cropper,
scale = item.popup.editor.scale || 1;
cropper.$editor.find('.area-info').html((cropper.isResizing || type == 'size' ? [
'W: ' + Math.round(cropper.crop.width / cropper.crop.cfWidth / scale) + 'px',
' ',
'H: ' + Math.round(cropper.crop.height / cropper.crop.cfHeight / scale) + 'px'] : [
'X: ' + Math.round(cropper.crop.left / cropper.crop.cfWidth / scale) + 'px',
' ',
'Y: ' + Math.round(cropper.crop.top / cropper.crop.cfHeight / scale) + 'px']).join(''));
},
mousedown: function(e) {
var eventType = e.originalEvent.touches && e.originalEvent.touches[0] ? 'touchstart' : 'mousedown',
$target = $(e.target),
cropper = item.popup.editor.cropper,
points = {
x: (eventType == 'mousedown' ? e.pageX : e.originalEvent.touches[0].pageX) - cropper.$template.offset().left,
y: (eventType == 'mousedown' ? e.pageY : e.originalEvent.touches[0].pageY) - cropper.$template.offset().top
},
callback = function() {
// set current state
cropper.pointData = {
el: $target,
x: points.x,
y: points.y,
xEditor: points.x - cropper.crop.left,
yEditor: points.y - cropper.crop.top,
left: cropper.crop.left,
top: cropper.crop.top,
width: cropper.crop.width,
height: cropper.crop.height
};
// start cropping event
if (cropper.isMoving || cropper.isResizing) {
cropper.setAreaInfo('size');
cropper.$editor.addClass('moving show-info');
$('body').css({
'-webkit-user-select': 'none',
'-moz-user-select': 'none',
'-ms-user-select': 'none',
'user-select': 'none'
});
// bind window mousemove event
$(document).on('mousemove touchmove', cropper.mousemove);
}
};
if (item.popup.zoomer && item.popup.zoomer.hasSpacePressed)
return;
// determinate cropping type
cropper.isMoving = $target.is('.area-move');
cropper.isResizing = $target.is('.point');
// mousedown event
if (eventType == 'mousedown') {
// bind cropping start event
callback();
}
// touchstart event
if (eventType == 'touchstart' && e.originalEvent.touches.length == 1) {
if (cropper.isMoving || cropper.isResizing)
e.preventDefault();
cropper.isTouchLongPress = true;
// check if long press
setTimeout(function() {
if (!cropper.isTouchLongPress)
return;
delete cropper.isTouchLongPress;
callback();
}, n.thumbnails.touchDelay ? n.thumbnails.touchDelay : 0);
}
// bind window mouseup event
$(document).on('mouseup touchend', cropper.mouseup);
},
mousemove: function(e) {
var eventType = e.originalEvent.touches && e.originalEvent.touches[0] ? 'touchstart' : 'mousedown',
$target = $(e.target),
cropper = item.popup.editor.cropper,
points = {
x: (eventType == 'mousedown' ? e.pageX : e.originalEvent.touches[0].pageX) - cropper.$template.offset().left,
y: (eventType == 'mousedown' ? e.pageY : e.originalEvent.touches[0].pageY) - cropper.$template.offset().top
};
if (e.originalEvent.touches && e.originalEvent.touches.length != 1)
return cropper.mouseup(e);
// move
if (cropper.isMoving) {
var left = points.x - cropper.pointData.xEditor,
top = points.y - cropper.pointData.yEditor;
// position
if (left + cropper.crop.width > cropper.$template.width())
left = cropper.$template.width() - cropper.crop.width;
if (left < 0)
left = 0;
if (top + cropper.crop.height > cropper.$template.height())
top = cropper.$template.height() - cropper.crop.height;
if (top < 0)
top = 0;
// set position
cropper.crop.left = left;
cropper.crop.top = top;
}
// resize
if (cropper.isResizing) {
var point = cropper.pointData.el.attr('class').substr("point point-".length),
lastWidth = cropper.crop.left + cropper.crop.width,
lastHeight = cropper.crop.top + cropper.crop.height,
minWidth = (n.editor.cropper && n.editor.cropper.minWidth || 0) * cropper.crop.cfWidth,
minHeight = (n.editor.cropper && n.editor.cropper.minHeight || 0) * cropper.crop.cfHeight,
maxWidth = (n.editor.cropper && n.editor.cropper.maxWidth) * cropper.crop.cfWidth,
maxHeight = (n.editor.cropper && n.editor.cropper.maxHeight) * cropper.crop.cfHeight,
ratio = n.editor.cropper ? n.editor.cropper.ratio : null,
ratioPx;
// set minWidth if greater than image
if (minWidth > cropper.$template.width())
minWidth = cropper.$template.width();
if (minHeight > cropper.$template.height())
minHeight = cropper.$template.height();
// set maxWidth if greater than image
if (maxWidth > cropper.$template.width())
maxWidth = cropper.$template.width();
if (maxHeight > cropper.$template.height())
maxHeight = cropper.$template.height();
// points
if ((point == 'a' || point == 'b' || point == 'c') && !ratioPx) {
cropper.crop.top = points.y;
if (cropper.crop.top < 0)
cropper.crop.top = 0;
cropper.crop.height = lastHeight - cropper.crop.top;
if (cropper.crop.top > cropper.crop.top + cropper.crop.height) {
cropper.crop.top = lastHeight;
cropper.crop.height = 0;
}
// minHeight
if (cropper.crop.height < minHeight) {
cropper.crop.top = lastHeight - minHeight;
cropper.crop.height = minHeight;
}
// maxHeight
if (cropper.crop.height > maxHeight) {
cropper.crop.top = lastHeight - maxHeight;
cropper.crop.height = maxHeight;
}
// ratio
ratioPx = ratio ? f._assets.ratioToPx(cropper.crop.width, cropper.crop.height, ratio) : null;
if (ratioPx) {
cropper.crop.width = ratioPx[0];
if (point == 'a' || point == 'b')
cropper.crop.left = Math.max(0, cropper.pointData.left + ((cropper.pointData.width - cropper.crop.width) / (point == 'b' ? 2 : 1)));
// check
if (cropper.crop.left + cropper.crop.width > cropper.$template.width()) {
var newWidth = cropper.$template.width() - cropper.crop.left;
cropper.crop.width = newWidth;
cropper.crop.height = newWidth / ratioPx[2] * ratioPx[3];
cropper.crop.top = lastHeight - cropper.crop.height;
}
}
}
if ((point == 'e' || point == 'f' || point == 'g') && !ratioPx) {
cropper.crop.height = points.y - cropper.crop.top;
if (cropper.crop.height + cropper.crop.top > cropper.$template.height())
cropper.crop.height = cropper.$template.height() - cropper.crop.top;
// minHeight
if (cropper.crop.height < minHeight)
cropper.crop.height = minHeight;
// maxHeight
if (cropper.crop.height > maxHeight)
cropper.crop.height = maxHeight;
// ratio
ratioPx = ratio ? f._assets.ratioToPx(cropper.crop.width, cropper.crop.height, ratio) : null;
if (ratioPx) {
cropper.crop.width = ratioPx[0];
if (point == 'f' || point == 'g')
cropper.crop.left = Math.max(0, cropper.pointData.left + ((cropper.pointData.width - cropper.crop.width) / (point == 'f' ? 2 : 1)));
// check
if (cropper.crop.left + cropper.crop.width > cropper.$template.width()) {
var newWidth = cropper.$template.width() - cropper.crop.left;
cropper.crop.width = newWidth;
cropper.crop.height = newWidth / ratioPx[2] * ratioPx[3];
}
}
}
if ((point == 'c' || point == 'd' || point == 'e') && !ratioPx) {
cropper.crop.width = points.x - cropper.crop.left;
if (cropper.crop.width + cropper.crop.left > cropper.$template.width())
cropper.crop.width = cropper.$template.width() - cropper.crop.left;
// minWidth
if (cropper.crop.width < minWidth)
cropper.crop.width = minWidth;
// maxWidth
if (cropper.crop.width > maxWidth)
cropper.crop.width = maxWidth;
// ratio
ratioPx = ratio ? f._assets.ratioToPx(cropper.crop.width, cropper.crop.height, ratio) : null;
if (ratioPx) {
cropper.crop.height = ratioPx[1];
if (point == 'c' || point == 'd')
cropper.crop.top = Math.max(0, cropper.pointData.top + ((cropper.pointData.height - cropper.crop.height) / (point == 'd' ? 2 : 1)));
// check
if (cropper.crop.top + cropper.crop.height > cropper.$template.height()) {
var newHeight = cropper.$template.height() - cropper.crop.top;
cropper.crop.height = newHeight;
cropper.crop.width = newHeight / ratioPx[3] * ratioPx[2];
}
}
}
if ((point == 'a' || point == 'g' || point == 'h') && !ratioPx) {
cropper.crop.left = points.x;
if (cropper.crop.left > cropper.$template.width())
cropper.crop.left = cropper.$template.width();
if (cropper.crop.left < 0)
cropper.crop.left = 0;
cropper.crop.width = lastWidth - cropper.crop.left;
if (cropper.crop.left > cropper.crop.left + cropper.crop.width) {
cropper.crop.left = lastWidth;
cropper.crop.width = 0;
}
// minWidth
if (cropper.crop.width < minWidth) {
cropper.crop.left = lastWidth - minWidth;
cropper.crop.width = minWidth;
}
// maxWidth
if (cropper.crop.width > maxWidth) {
cropper.crop.left = lastWidth - maxWidth;
cropper.crop.width = maxWidth;
}
// ratio
ratioPx = ratio ? f._assets.ratioToPx(cropper.crop.width, cropper.crop.height, ratio) : null;
if (ratioPx) {
cropper.crop.height = ratioPx[1];
if (point == 'a' || point == 'h')
cropper.crop.top = Math.max(0, cropper.pointData.top + ((cropper.pointData.height - cropper.crop.height) / (point == 'h' ? 2 : 1)));
// check
if (cropper.crop.top + cropper.crop.height > cropper.$template.height()) {
var newHeight = cropper.$template.height() - cropper.crop.top;
cropper.crop.height = newHeight;
cropper.crop.width = newHeight / ratioPx[3] * ratioPx[2];
cropper.crop.left = lastWidth - cropper.crop.width;
}
}
}
}
// draw cropping-area
cropper.drawPlaceHolder(cropper.crop);
},
mouseup: function(e) {
var cropper = item.popup.editor.cropper;
// check if empty area
if (cropper.$editor.width() == 0 || cropper.$editor.height() == 0)
cropper.init(cropper.setDefaultData());
// clear
delete cropper.isTouchLongPress;
delete cropper.isMoving;
delete cropper.isResizing;
cropper.$editor.removeClass('moving show-info');
$('body').css({
'-webkit-user-select': '',
'-moz-user-select': '',
'-ms-user-select': '',
'user-select': ''
});
// unbind window events
$(document).off('mousemove touchmove', cropper.mousemove);
$(document).off('mouseup touchend', cropper.mouseup);
}
};
// init cropper tool
item.popup.editor.cropper.init();
} else {
if (data)
item.popup.editor.cropper.crop = data;
item.popup.editor.cropper.init(data);
}
}
},
/**
* resize
* resize a canvas image
*
* @namespace editor
* @param {HTML} img
* @param {HTML} canvas
* @param {Number} width - new width
* @param {Number} height - new height
* @param {Boolean} alpha - enable transparency on resize (!not available on smooth resize)
* @param {Boolean} fixedSize - fixed canvas size
* @void
*/
resize: function(img, canvas, width, height, alpha, fixedSize) {
var context = canvas.getContext('2d'),
width = !width && height ? height * img.width / img.height : width,
height = !height && width ? width * img.height / img.width : height,
ratio = img.width / img.height,
optimalWidth = ratio >= 1 ? width : height * ratio,
optimalHeight = ratio < 1 ? height : width / ratio;
if (fixedSize && optimalWidth < width) {
optimalHeight = optimalHeight * (width/optimalWidth);
optimalWidth = width;
}
if (fixedSize && optimalHeight < height) {
optimalWidth = optimalWidth * (height/optimalHeight);
optimalHeight = height;
}
var steps = Math.min(Math.ceil(Math.log(img.width / optimalWidth) / Math.log(2)), 12);
canvas.width = optimalWidth;
canvas.height = optimalHeight;
// if image is smaller than canvas or there are no resizing steps
if (img.width < canvas.width || img.height < canvas.height || steps < 2) {
// set canvas size as image size if size is not fixed
if (!fixedSize) {
canvas.width = Math.min(img.width, canvas.width);
canvas.height = Math.min(img.height, canvas.height);
}
// alight image to center
var x = img.width < canvas.width ? (canvas.width - img.width)/2 : 0,
y = img.height < canvas.height ? (canvas.height - img.height)/2 : 0;
// draw image
if (!alpha) {
context.fillStyle = "#fff";
context.fillRect(0, 0, canvas.width, canvas.height);
}
context.drawImage(img, x, y, Math.min(img.width, canvas.width), Math.min(img.height, canvas.height));
} else {
var oc = document.createElement('canvas'),
octx = oc.getContext('2d'),
factor = 2;
// smooth resize
oc.width = img.width/factor;
oc.height = img.height/factor;
octx.fillStyle = "#fff";
octx.fillRect(0, 0, oc.width, oc.height);
octx.drawImage(img, 0, 0, oc.width, oc.height);
while(steps > 2) {
var factor2 = factor + 2,
widthFactor = img.width/factor,
heightFactor = img.height/factor;
if (widthFactor > oc.width)
widthFactor = oc.width;
if (heightFactor > oc.height)
heightFactor = oc.height;
octx.drawImage(oc, 0, 0, widthFactor, heightFactor, 0, 0, img.width/factor2, img.height/factor2);
factor = factor2;
steps--;
}
// draw image
var widthFactor = img.width/factor,
heightFactor = img.height/factor;
if (widthFactor > oc.width)
widthFactor = oc.width;
if (heightFactor > oc.height)
heightFactor = oc.height;
context.drawImage(oc, 0, 0, widthFactor, heightFactor, 0, 0, optimalWidth, optimalHeight);
oc = octx = null;
}
context = null;
},
zoomer: function(item) {
var inPopup = item.popup && item.popup.html && $('html').find(item.popup.html).length;
if (!inPopup)
return;
if (!item.popup.zoomer) {
var $popup = item.popup.html,
$node = $popup.find('.fileuploader-popup-node'),
$readerNode = $node.find('.reader-node'),
$imageEl = $readerNode.find('> img').attr('draggable', 'false').attr('ondragstart', 'return false;');
item.popup.zoomer = {
html: $popup.find('.fileuploader-popup-zoomer'),
isActive: item.format == 'image' && item.reader.node && n.thumbnails.popup.zoomer,
scale: 100,
zoom: 100,
init: function() {
var zoomer = this;
// disable plugin no images and IE
if (!zoomer.isActive || f._assets.isIE() || f._assets.isMobile())
return zoomer.html.hide() && $node.addClass('has-node-centered');
// init
zoomer.hide();
zoomer.resize();
$(window).on('resize', zoomer.resize);
$(window).on('keyup keydown', zoomer.keyPress);
zoomer.html.find('input').on('input change', zoomer.range);
$readerNode.on('mousedown touchstart', zoomer.mousedown);
$node.on('mousewheel DOMMouseScroll', zoomer.scroll);
},
hide: function() {
var zoomer = this;
$(window).off('resize', zoomer.resize);
$(window).off('keyup keydown', zoomer.keyPress);
zoomer.html.find('input').off('input change', zoomer.range);
$readerNode.off('mousedown', zoomer.mousedown);
$node.off('mousewheel DOMMouseScroll', zoomer.scroll);
},
center: function(prevDimensions) {
var zoomer = this,
left = 0,
top = 0;
if (!prevDimensions) {
left = Math.round(($node.width() - $readerNode.width()) / 2);
top = Math.round(($node.height() - $readerNode.height()) / 2);
} else {
left = zoomer.left;
top = zoomer.top;
left -= (($node.width() / 2 - zoomer.left) * (($readerNode.width()/prevDimensions[0])-1));
top -= (($node.height() / 2 - zoomer.top) * (($readerNode.height()/prevDimensions[1])-1));
if ($readerNode.width() <= $node.width())
left = Math.round(($node.width() - $readerNode.width()) / 2);
if ($readerNode.height() <= $node.height())
top = Math.round(($node.height() - $readerNode.height()) / 2);
if ($readerNode.width() > $node.width()) {
if (left > 0)
left = 0;
else if (left + $readerNode.width() < $node.width())
left = $node.width() - $readerNode.width();
}
if ($readerNode.height() > $node.height()) {
if (top > 0)
top = 0;
else if (top + $readerNode.height() < $node.height())
top = $node.height() - $readerNode.height();
}
top = Math.min(top, 0);
}
// set styles
$readerNode.css({
left: (zoomer.left = left) + 'px',
top: (zoomer.top = top) + 'px',
width: $readerNode.width(),
height: $readerNode.height()
});
},
resize: function() {
var zoomer = item.popup.zoomer;
$node.removeClass('is-zoomed');
$readerNode.removeAttr('style');
zoomer.scale = zoomer.getImageScale();
zoomer.updateView();
},
range: function(e) {
var zoomer = item.popup.zoomer,
$input = $(this),
val = parseFloat($input.val());
if (zoomer.scale >= 100) {
e.preventDefault();
$input.val(zoomer.scale);
return;
}
if (val < zoomer.scale) {
e.preventDefault();
val = zoomer.scale;
$input.val(val);
}
zoomer.updateView(val, true);
},
scroll: function(e) {
var zoomer = item.popup.zoomer,
delta = -100;
if (e.originalEvent) {
if (e.originalEvent.wheelDelta)
delta = e.originalEvent.wheelDelta / -40;
if (e.originalEvent.deltaY)
delta = e.originalEvent.deltaY;
if (e.originalEvent.detail)
delta = e.originalEvent.detail;
}
zoomer[delta < 0 ? 'zoomIn' : 'zoomOut'](3);
},
keyPress: function(e) {
var zoomer = item.popup.zoomer,
type = e.type,
key = e.keyCode || e.which;
if (key != 32)
return;
zoomer.hasSpacePressed = type == 'keydown';
if (zoomer.hasSpacePressed && zoomer.isZoomed())
$readerNode.addClass('is-amoving');
else
$readerNode.removeClass('is-amoving');
},
mousedown: function(e) {
var zoomer = item.popup.zoomer,
$target = $(e.target),
eventType = e.originalEvent.touches && e.originalEvent.touches[0] ? 'touchstart' : 'mousedown',
points = {
x: eventType == 'mousedown' ? e.pageX : e.originalEvent.touches[0].pageX,
y: eventType == 'mousedown' ? e.pageY : e.originalEvent.touches[0].pageY
},
callback = function() {
// set current state
zoomer.pointData = {
x: points.x,
y: points.y,
xTarget: points.x - zoomer.left,
yTarget: points.y - zoomer.top,
};
$('body').css({
'-webkit-user-select': 'none',
'-moz-user-select': 'none',
'-ms-user-select': 'none',
'user-select': 'none'
});
$readerNode.addClass('is-moving');
// bind window mousemove event
$(document).on('mousemove', zoomer.mousemove);
};
if (e.which != 1)
return;
if (zoomer.scale == 100 || zoomer.zoom == zoomer.scale)
return;
// check e.target
if (!zoomer.hasSpacePressed && $target[0] != $imageEl[0] && !$target.is('.fileuploader-cropper'))
return;
// mousedown event
if (eventType == 'mousedown') {
callback();
}
// touchstart event
if (eventType == 'touchstart') {
zoomer.isTouchLongPress = true;
// check if long press
setTimeout(function() {
if (!zoomer.isTouchLongPress)
return;
delete zoomer.isTouchLongPress;
callback();
}, n.thumbnails.touchDelay ? n.thumbnails.touchDelay : 0);
}
// bind window mouseup event
$(document).on('mouseup touchend', zoomer.mouseup);
},
mousemove: function(e) {
var zoomer = item.popup.zoomer,
eventType = e.originalEvent.touches && e.originalEvent.touches[0] ? 'touchstart' : 'mousedown',
points = {
x: eventType == 'mousedown' ? e.pageX : e.originalEvent.touches[0].pageX,
y: eventType == 'mousedown' ? e.pageY : e.originalEvent.touches[0].pageY
},
left = points.x - zoomer.pointData.xTarget,
top = points.y - zoomer.pointData.yTarget;
// fix the positon
if (top > 0)
top = 0;
if (top < $node.height() - $readerNode.height())
top = $node.height() - $readerNode.height();
if ($readerNode.height() < $node.height()) {
top = $node.height()/2 - $readerNode.height()/2;
}
if ($readerNode.width() > $node.width()) {
if (left > 0)
left = 0;
if (left < $node.width() - $readerNode.width())
left = $node.width() - $readerNode.width();
} else {
left = $node.width()/2 - $readerNode.width()/2;
}
// set styles
$readerNode.css({
left: (zoomer.left = left) + 'px',
top: (zoomer.top = top) + 'px'
});
},
mouseup: function(e) {
var zoomer = item.popup.zoomer;
delete zoomer.pointData;
$('body').css({
'-webkit-user-select': '',
'-moz-user-select': '',
'-ms-user-select': '',
'user-select': ''
});
$readerNode.removeClass('is-moving');
$(document).off('mousemove', zoomer.mousemove);
$(document).off('mouseup', zoomer.mouseup);
},
zoomIn: function(val) {
var zoomer = item.popup.zoomer,
step = val || 20;
if (zoomer.zoom >= 100)
return;
zoomer.zoom = Math.min(100, zoomer.zoom + step);
zoomer.updateView(zoomer.zoom);
},
zoomOut: function(val) {
var zoomer = item.popup.zoomer,
step = val || 20;
if (zoomer.zoom <= zoomer.scale)
return;
zoomer.zoom = Math.max(zoomer.scale, zoomer.zoom - step);
zoomer.updateView(zoomer.zoom);
},
updateView: function(val, input) {
var zoomer = this,
width = zoomer.getImageSize().width / 100 * val,
height = zoomer.getImageSize().height / 100 * val,
curWidth = $readerNode.width(),
curHeight = $readerNode.height(),
valueChanged = val && val != zoomer.scale;
if (!zoomer.isActive)
return zoomer.center();
if (valueChanged) {
$node.addClass('is-zoomed');
$readerNode.addClass('is-movable').css({
width: width + 'px',
height: height + 'px',
maxWidth: 'none',
maxHeight: 'none'
});
} else {
$node.removeClass('is-zoomed');
$readerNode.removeClass('is-movable is-amoving').removeAttr('style');
}
zoomer.zoom = val || zoomer.scale;
zoomer.center(valueChanged ? [curWidth, curHeight, zoomer.left, zoomer.top] : null);
zoomer.html.find('span').html(zoomer.zoom + '%');
if (!input)
zoomer.html.find('input').val(zoomer.zoom);
if (val && item.popup.editor && item.popup.editor.cropper)
item.popup.editor.cropper.resize(true);
},
isZoomed: function() {
var zoomer = this;
return zoomer.zoom > zoomer.scale;
},
getImageSize: function() {
var zoomer = this;
return {
width: $imageEl.prop('naturalWidth'),
height: $imageEl.prop('naturalHeight')
};
},
getImageScale: function() {
var zoomer = this;
return Math.round(100 / ($imageEl.prop('naturalWidth') / $imageEl.width()));
}
};
}
item.popup.zoomer.init();
},
/**
* save
* save edited image
* show cropping tools, only when popup is enabled
*
* @namespace editor
* @param {Object} item
* @void
*/
save: function(item, toBlob, mimeType, callback, preventThumbnailRender) {
var inPopup = item.popup && item.popup.html && $('html').find(item.popup.html).length,
image = new Image(),
onload = function() {
if (!item.reader.node)
return;
// update thumbnail
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
image = this,
rotationCf = [0, 180];
// set canvas size and image
canvas.width = item.reader.width;
canvas.height = item.reader.height;
ctx.drawImage(image, 0, 0, item.reader.width, item.reader.height);
// rotate image
if (typeof item.editor.rotation != 'undefined') {
item.editor.rotation = item.editor.rotation || 0;
canvas.width = rotationCf.indexOf(item.editor.rotation) > -1 ? item.reader.width : item.reader.height;
canvas.height = rotationCf.indexOf(item.editor.rotation) > -1 ? item.reader.height : item.reader.width;
var angle = item.editor.rotation*Math.PI/180,
cw = canvas.width * 0.5,
ch = canvas.height * 0.5;
// clear context
ctx.clearRect(0, 0, canvas.width, canvas.height);
// rotate context
ctx.translate(cw, ch);
ctx.rotate(angle);
ctx.translate(-item.reader.width * 0.5, -item.reader.height * 0.5);
// draw image and reset transform
ctx.drawImage(image, 0, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
// crop image
if (item.editor.crop) {
var cut = ctx.getImageData(item.editor.crop.left, item.editor.crop.top, item.editor.crop.width, item.editor.crop.height);
canvas.width = item.editor.crop.width;
canvas.height = item.editor.crop.height;
// put image
ctx.putImageData(cut, 0, 0);
}
// export image
var type = mimeType || item.type || 'image/jpeg',
quality = n.editor.quality || 90,
exportDataURI = canvas.toDataURL(type, quality/100),
nextStep = function(exportDataURI, img) {
var data = !toBlob ? exportDataURI : f._assets.dataURItoBlob(exportDataURI, type);
!preventThumbnailRender ? f.thumbnails.renderThumbnail(item, true, img || exportDataURI) : null;
callback ? callback(data, item, l, p, o, s) : null;
n.editor.onSave != null && typeof n.editor.onSave == "function" ? n.editor.onSave(data, item, l, p, o, s) : null;
f.set('listInput', null);
};
// resize image if maxWidth
if (n.editor.maxWidth || n.editor.maxHeight) {
var img = new Image();
img.src = exportDataURI;
img.onload = function() {
var canvas2 = document.createElement('canvas');
// resize canvas
f.editor.resize(img, canvas2, n.editor.maxWidth, n.editor.maxHeight, true, false);
exportDataURI = canvas2.toDataURL(type, quality/100);
nextStep(exportDataURI, img);
canvas = ctx = canvas2 = null;
};
} else {
nextStep(exportDataURI);
canvas = ctx = null;
}
};
if (inPopup) {
if (!item.popup.editor.hasChanges)
return;
var scale = item.popup.editor.scale || 1;
item.editor.rotation = item.popup.editor.rotation || 0;
if (item.popup.editor.cropper) {
item.editor.crop = item.popup.editor.cropper.crop;
item.editor.crop.width = item.editor.crop.width / item.popup.editor.cropper.crop.cfWidth / scale;
item.editor.crop.left = item.editor.crop.left / item.popup.editor.cropper.crop.cfWidth / scale;
item.editor.crop.height = item.editor.crop.height / item.popup.editor.cropper.crop.cfHeight / scale;
item.editor.crop.top = item.editor.crop.top / item.popup.editor.cropper.crop.cfHeight / scale;
}
}
if (f._assets.isMobile()) {
image.onload = onload;
image.src = item.reader.src;
} else if(item.reader.node) {
onload.call(item.reader.node);
} else {
item.reader.read(function() {
onload.call(item.reader.node);
});
}
}
},
/**
* @namespace sorter
*/
sorter: {
init: function() {
p.on('mousedown touchstart', n.thumbnails._selectors.sorter, f.sorter.mousedown);
},
destroy: function() {
p.off('mousedown touchstart', n.thumbnails._selectors.sorter, f.sorter.mousedown);
},
findItemAtPos: function(points) {
var sort = f.sorter.sort,
$list = sort.items.not(sort.item.html),
$item = null;
$list.each(function(i, el) {
var $el = $(el);
if (points.x > $el.offset().left && points.x < $el.offset().left + $el.outerWidth() &&
points.y > $el.offset().top && points.y < $el.offset().top + $el.outerHeight()) {
$item = $el;
return false;
}
});
return $item;
},
mousedown: function(e) {
var eventType = e.originalEvent.touches && e.originalEvent.touches[0] ? 'touchstart' : 'mousedown',
$target = $(e.target),
$item = $target.closest(n.thumbnails._selectors.item),
item = f.files.find($item),
points = {
x: eventType == 'mousedown' || !$item.length ? e.pageX : e.originalEvent.touches[0].pageX,
y: eventType == 'mousedown' || !$item.length ? e.pageY : e.originalEvent.touches[0].pageY
},
callback = function() {
// set current state
f.sorter.sort = {
el: $target,
item: item,
items: l.find(n.thumbnails._selectors.item),
x: points.x,
y: points.y,
xItem: points.x - $item.offset().left,
yItem: points.y - $item.offset().top,
left: $item.position().left,
top: $item.position().top,
width: $item.outerWidth(),
height: $item.outerHeight(),
placeholder: n.sorter.placeholder ? $(n.sorter.placeholder) : item.html.clone().addClass('fileuploader-sorter-placeholder').html('')
};
// disable user-select
$('body').css({
'-webkit-user-select': 'none',
'-moz-user-select': 'none',
'-ms-user-select': 'none',
'user-select': 'none'
});
// bind window mousemove event
$(document).on('mousemove touchmove', f.sorter.mousemove);
};
e.preventDefault();
// off
if (f.sorter.sort)
f.sorter.mouseup();
// prevent if there is no item
if (!item)
return;
// prevent if target is selectorExclude
if (n.sorter.selectorExclude && ($target.is(n.sorter.selectorExclude) || $target.closest(n.sorter.selectorExclude).length))
return;
// preventDefault();
$(n.thumbnails._selectors.sorter).on('click drop dragend dragleave dragover dragenter dragstart touchstart touchmove touchend touchcancel', function(e){ e.preventDefault(); });
// mousedown event
if (eventType == 'mousedown') {
// bind cropping start event
callback();
}
// touchstart event
if (eventType == 'touchstart') {
f.sorter.isTouchLongPress = true;
// check if long press
setTimeout(function() {
if (!f.sorter.isTouchLongPress)
return;
delete f.sorter.isTouchLongPress;
callback();
}, n.thumbnails.touchDelay ? n.thumbnails.touchDelay : 0);
}
// bind window mouseup event
$(document).on('mouseup touchend', f.sorter.mouseup);
},
mousemove: function(e) {
var eventType = e.originalEvent.touches && e.originalEvent.touches[0] ? 'touchstart' : 'mousedown',
sort = f.sorter.sort,
item = sort.item,
$list = l.find(n.thumbnails._selectors.item),
$container = $(n.sorter.scrollContainer || window),
scroll = {
left: $(document).scrollLeft(),
top: $(document).scrollTop(),
containerLeft: $container.scrollLeft(),
containerTop: $container.scrollTop()
},
points = {
x: eventType == 'mousedown' ? e.clientX : e.originalEvent.touches[0].clientX,
y: eventType == 'mousedown' ? e.clientY : e.originalEvent.touches[0].clientY
};
e.preventDefault();
// drag
var left = points.x - sort.xItem,
top = points.y - sort.yItem,
leftContainer = points.x - ($container.prop('offsetLeft') || 0),
topContainer = points.y - ($container.prop('offsetTop') || 0);
// fix position
if (left + sort.xItem > $container.width())
left = $container.width() - sort.xItem;
if (left + sort.xItem < 0)
left = 0 - sort.xItem;
if (top + sort.yItem > $container.height())
top = $container.height() - sort.yItem;
if (top + sort.yItem < 0)
top = 0 - sort.yItem;
// scroll
if (topContainer <= 0)
$container.scrollTop(scroll.containerTop - 10);
if (topContainer > $container.height())
$container.scrollTop(scroll.containerTop + 10);
if (leftContainer < 0)
$container.scrollLeft(scroll.containerLeft - 10);
if (leftContainer > $container.width())
$container.scrollLeft(scroll.containerLeft + 10);
// set style
item.html.addClass('sorting').css({
position: 'fixed',
left: left,
top: top,
width: f.sorter.sort.width,
height: f.sorter.sort.height
});
// position placeholder
if (!l.find(sort.placeholder).length)
item.html.after(sort.placeholder);
sort.placeholder.css({
width: f.sorter.sort.width,
height: f.sorter.sort.height,
});
// set new position
var $hoverEl = f.sorter.findItemAtPos({x: left + sort.xItem + scroll.left, y: top + sort.yItem + scroll.top});
if ($hoverEl) {
// prevent drag issue
var directionX = sort.placeholder.offset().left != $hoverEl.offset().left,
directionY = sort.placeholder.offset().top != $hoverEl.offset().top;
if (f.sorter.sort.lastHover) {
if (f.sorter.sort.lastHover.el == $hoverEl[0]) {
if (directionY && f.sorter.sort.lastHover.direction == 'before' && points.y < f.sorter.sort.lastHover.y)
return;
if (directionY && f.sorter.sort.lastHover.direction == 'after' && points.y > f.sorter.sort.lastHover.y)
return;
if (directionX && f.sorter.sort.lastHover.direction == 'before' && points.x < f.sorter.sort.lastHover.x)
return;
if (directionX && f.sorter.sort.lastHover.direction == 'after' && points.x > f.sorter.sort.lastHover.x)
return;
}
}
// insert element before/after in HTML
var index = $list.index(item.html),
hoverIndex = $list.index($hoverEl),
direction = index > hoverIndex ? 'before' : 'after';
$hoverEl[direction](sort.placeholder);
$hoverEl[direction](item.html);
// save last hover data
f.sorter.sort.lastHover = {
el: $hoverEl[0],
x: points.x,
y: points.y,
direction: direction
};
}
},
mouseup: function() {
var sort = f.sorter.sort,
item = sort.item;
// clear
$('body').css({
'-webkit-user-select': '',
'-moz-user-select': '',
'-ms-user-select': '',
'user-select': ''
});
item.html.removeClass('sorting').css({
position: '',
left: '',
top: '',
width: '',
height: ''
});
$(document).off('mousemove touchmove', f.sorter.mousemove);
$(document).off('mouseup touchend', f.sorter.mouseup);
sort.placeholder.remove();
delete f.sorter.sort;
f.sorter.save();
},
save: function(isFromList) {
var index = 0,
list = [],
cachedList = [],
items = isFromList ? f._itFl : (n.thumbnails.itemPrepend) ? l.children().get().reverse() : l.children(),
hasChanges;
// set index for all files
$.each(items, function(i, el) {
var item = el.file ? el : f.files.find($(el));
if (item) {
// continue if not uploaded
if (item.upload && !item.uploaded)
return;
// check for changes
if (f.rendered && item.index != index && ((f._itSl && f._itSl.indexOf(item.id) != index) || true))
hasChanges = true;
item.index = index;
list.push(item);
cachedList.push(item.id);
index++;
}
});
// check for changes
if (f._itSl && f._itSl.length != cachedList.length)
hasChanges = true;
f._itSl = cachedList;
// replace list
if (hasChanges && list.length == f._itFl.length)
f._itFl = list;
// update listInput
if (!isFromList)
f.set('listInput', 'ignoreSorter');
// onSort callback
hasChanges && n.sorter.onSort != null && typeof n.sorter.onSort == "function" ? n.sorter.onSort(list, l, p, o, s) : null;
}
},
/**
* @namespace upload
*/
upload: {
/**
* prepare
* prepare item ajax data and also item ajax methods
*
* @namespace upload
* @param {Object} item
* @param {bool} force_send - force ajax sending after prepare
* @void
*/
prepare: function(item, force_send) {
// create item upload object
item.upload = {
url: n.upload.url,
data: $.extend({}, n.upload.data),
formData: new FormData(),
type: n.upload.type || 'POST',
enctype: n.upload.enctype || 'multipart/form-data',
cache: false,
contentType: false,
processData: false,
chunk: item.upload ? item.upload.chunk : null,
status: null,
send: function() {
f.upload.send(item, true);
},
cancel: function(isFromRemove) {
f.upload.cancel(item, isFromRemove);
}
};
// add file to formData
item.upload.formData.append(s.attr('name'), item.file, (item.name ? item.name : false));
if (n.upload.start || force_send)
f.upload.send(item, force_send);
},
/**
* send
* send item ajax
*
* @namespace upload
* @param {Object} item
* @param {bool} force_send - skip the synchron functions and force ajax sending
* @void
*/
send: function(item, force_send) {
// skip if upload settings were not prepared
// only made for safety
if (!item.upload)
return;
var setItemUploadStatus = function(status) {
if (item.html)
item.html.removeClass('upload-pending upload-loading upload-cancelled upload-failed upload-successful').addClass('upload-' + (status || item.upload.status));
},
loadNextItem = function() {
var i = 0;
if (f._pfuL.length > 0) {
f._pfuL.indexOf(item) > -1 ? f._pfuL.splice(f._pfuL.indexOf(item), 1) : null;
while (i < f._pfuL.length) {
if (f._itFl.indexOf(f._pfuL[i]) > -1 && f._pfuL[i].upload && !f._pfuL[i].upload.$ajax) {
f.upload.send(f._pfuL[i], true);
break;
} else {
f._pfuL.splice(i, 1);
}
i++;
}
}
};
// synchron upload
if (n.upload.synchron && !item.upload.chunk) {
// add pending status to item
item.upload.status = 'pending';
if (item.html)
setItemUploadStatus();
// check pending list
if (force_send) {
f._pfuL.indexOf(item) > -1 ? f._pfuL.splice(f._pfuL.indexOf(item), 1) : null;
} else {
f._pfuL.indexOf(item) == -1 ? f._pfuL.push(item) : null;
if (f._pfuL.length > 1) {
return;
}
}
}
// chunk upload
if (n.upload.chunk && item.file.slice) {
var chunkSize = f._assets.toBytes(n.upload.chunk),
chunks = Math.ceil(item.size/chunkSize, chunkSize);
if (chunks > 1 && !item.upload.chunk)
item.upload.chunk = {
name: item.name,
size: item.file.size,
type: item.file.type,
chunkSize: chunkSize,
temp_name: item.name,
loaded: 0,
total: chunks,
i: -1
};
if (item.upload.chunk) {
item.upload.chunk.i++;
delete item.upload.chunk.isFirst;
delete item.upload.chunk.isLast;
if (item.upload.chunk.i == 0)
item.upload.chunk.isFirst = true;
if (item.upload.chunk.i == item.upload.chunk.total - 1)
item.upload.chunk.isLast = true;
if (item.upload.chunk.i <= item.upload.chunk.total - 1) {
var offset = item.upload.chunk.i * item.upload.chunk.chunkSize,
filePart = item.file.slice(offset, offset + item.upload.chunk.chunkSize);
item.upload.formData = new FormData();
item.upload.formData.append(s.attr('name'), filePart);
item.upload.data._chunkedd = JSON.stringify(item.upload.chunk);
} else {
delete item.upload.chunk;
}
}
}
// upload.beforeSend callback
if (n.upload.beforeSend && $.isFunction(n.upload.beforeSend) && n.upload.beforeSend(item, l, p, o, s) === false) {
delete item.upload.chunk;
setItemUploadStatus();
loadNextItem();
return;
}
// add uploading class to parent element
p.addClass('fileuploader-is-uploading');
// add loading status to item
if (item.upload.$ajax)
item.upload.$ajax.abort();
delete item.upload.$ajax;
delete item.upload.send;
item.upload.status = 'loading';
if (item.html) {
if (n.thumbnails._selectors.start)
item.html.find(n.thumbnails._selectors.start).remove();
setItemUploadStatus();
}
// add upload data to formData
if (item.upload.data) {
for (var k in item.upload.data) {
if (!item.upload.data.hasOwnProperty(k))
continue;
item.upload.formData.append(k, item.upload.data[k]);
}
}
item.upload.data = item.upload.formData;
item.upload.xhr = function() {
var xhr = $.ajaxSettings.xhr(),
xhrStartedAt = item.upload.chunk && item.upload.chunk.xhrStartedAt ? item.upload.chunk.xhrStartedAt : new Date();
if (xhr.upload) {
xhr.upload.addEventListener("progress", function(e) {
if (item.upload.$ajax) {
item.upload.$ajax.total = item.upload.chunk ? item.upload.chunk.size : e.total;
item.upload.$ajax.xhrStartedAt = xhrStartedAt;
}
f.upload.progressHandling(e, item, xhrStartedAt);
}, false);
}
return xhr;
};
item.upload.complete = function(jqXHR, textStatus) {
if (item.upload.chunk && !item.upload.chunk.isLast && textStatus == 'success')
return f.upload.prepare(item, true);
loadNextItem();
var g = true;
$.each(f._itFl, function(i, a) {
if (a.upload && a.upload.$ajax)
g = false;
});
if (g) {
p.removeClass('fileuploader-is-uploading');
n.upload.onComplete != null && typeof n.upload.onComplete == "function" ? n.upload.onComplete(l, p, o, s, jqXHR, textStatus) : null;
}
};
item.upload.success = function(data, textStatus, jqXHR) {
if (item.upload.chunk && !item.upload.chunk.isLast) {
try {
var json = JSON.parse(data);
item.upload.chunk.temp_name = json.fileuploader.temp_name;
} catch (e) { }
return;
}
delete item.upload.chunk;
f.upload.progressHandling(null, item, item.upload.$ajax.xhrStartedAt, true);
item.uploaded = true;
delete item.upload;
item.upload = {status: 'successful', resend: function() { f.upload.retry(item); }};
if (item.html)
setItemUploadStatus();
n.upload.onSuccess != null && $.isFunction(n.upload.onSuccess) ? n.upload.onSuccess(data, item, l, p, o, s, textStatus, jqXHR) : null;
f.set('listInput', null);
};
item.upload.error = function(jqXHR, textStatus, errorThrown) {
if (item.upload.chunk)
item.upload.chunk.i = Math.max(-1, item.upload.chunk.i - 1);
item.uploaded = false;
item.upload.status = item.upload.status == 'cancelled' ? item.upload.status : 'failed';
item.upload.retry = function() { f.upload.retry(item); };
delete item.upload.$ajax;
if (item.html)
setItemUploadStatus();
n.upload.onError != null && $.isFunction(n.upload.onError) ? n.upload.onError(item, l, p, o, s, jqXHR, textStatus, errorThrown) : null;
};
// send
item.upload.$ajax = $.ajax(item.upload);
},
/**
* cancel
* cancel item ajax request
*
* @namespace upload
* @param {Object} item
* @void
*/
cancel: function(item, isFromRemove) {
if (item && item.upload) {
item.upload.status = 'cancelled';
delete item.upload.chunk;
item.upload.$ajax ? item.upload.$ajax.abort() : null;
delete item.upload.$ajax;
!isFromRemove ? f.files.remove(item) : null;
}
},
/**
* retry
* retry item ajax upload
*
* @namespace upload
* @param {Object} item
* @void
*/
retry: function(item) {
if (item && item.upload) {
if (item.html && n.thumbnails._selectors.retry)
item.html.find(n.thumbnails._selectors.retry).remove();
f.upload.prepare(item, true);
}
},
/**
* progressHandling
* item ajax progress function
*
* @namespace upload
* @param {Event} e - xhr event
* @param {Object} item
* @param {Date} xhrStartedAt - request started Date()
* @param {Boolean} isManual - check if function was manually called
* @void
*/
progressHandling: function(e, item, xhrStartedAt, isManual) {
if (!e && isManual && item.upload.$ajax)
e = {total: item.upload.$ajax.total, loaded: item.upload.$ajax.total, lengthComputable: true};
if (e.lengthComputable) {
var date = new Date(),
loaded = e.loaded + (item.upload.chunk ? item.upload.chunk.loaded : 0),
total = item.upload.chunk ? item.upload.chunk.size : e.total,
percentage = Math.round(loaded * 100 / total),
timeStarted = item.upload.chunk && item.upload.chunk.xhrStartedAt ? item.upload.chunk.xhrStartedAt : xhrStartedAt,
secondsElapsed = (date.getTime() - timeStarted.getTime()) / 1000,
bytesPerSecond = secondsElapsed ? loaded / secondsElapsed : 0,
remainingBytes = Math.max(0, total - loaded),
secondsRemaining = Math.max(0, secondsElapsed ? remainingBytes / bytesPerSecond : 0),
data = {
loaded: loaded,
loadedInFormat: f._assets.bytesToText(loaded),
total: total,
totalInFormat: f._assets.bytesToText(total),
percentage: percentage,
secondsElapsed: secondsElapsed,
secondsElapsedInFormat: f._assets.secondsToText(secondsElapsed, true),
bytesPerSecond: bytesPerSecond,
bytesPerSecondInFormat: f._assets.bytesToText(bytesPerSecond) + '/s',
remainingBytes: remainingBytes,
remainingBytesInFormat: f._assets.bytesToText(remainingBytes),
secondsRemaining: secondsRemaining,
secondsRemainingInFormat: f._assets.secondsToText(secondsRemaining, true)
};
if (item.upload.chunk) {
if (item.upload.chunk.isFirst)
item.upload.chunk.xhrStartedAt = xhrStartedAt;
if (e.loaded == e.total && !item.upload.chunk.isLast)
item.upload.chunk.loaded += Math.max(e.total, item.upload.chunk.total/item.upload.chunk.chunkSize);
}
if (data.percentage > 99 && !isManual)
data.percentage = 99;
// upload.onProgress callback
n.upload.onProgress && $.isFunction(n.upload.onProgress) ? n.upload.onProgress(data, item, l, p, o, s) : null;
}
}
},
/**
* @namespace dragDrop
*/
dragDrop: {
/**
* onDragEnter
* on dragging file on the drag container
*
* @namespace dragDrop
* @param {Event} e - jQuery event
* @void
*/
onDragEnter: function(e) {
clearTimeout(f.dragDrop._timer);
// add dragging class to parent element
n.dragDrop.container.addClass('fileuploader-dragging');
// set feedback caption
f.set('feedback', f._assets.textParse(n.captions.drop));
// dragDrop.onDragEnter callback
n.dragDrop.onDragEnter != null && $.isFunction(n.dragDrop.onDragEnter) ? n.dragDrop.onDragEnter(e, l, p, o, s) : null;
},
/**
* onDragLeave
* on dragging leave from the drag container
*
* @namespace dragDrop
* @param {Event} e - jQuery event
* @void
*/
onDragLeave: function(e) {
clearTimeout(f.dragDrop._timer);
f.dragDrop._timer = setTimeout(function(e) {
// check if not the childNodes from dragging container are hovered
if (!f.dragDrop._dragLeaveCheck(e)) {
return false;
}
// remove dragging class from parent element
n.dragDrop.container.removeClass('fileuploader-dragging');
// set feedback caption
f.set('feedback', null);
// dragDrop.onDragLeave callback
n.dragDrop.onDragLeave != null && $.isFunction(n.dragDrop.onDragLeave) ? n.dragDrop.onDragLeave(e, l, p, o, s) : null;
}, 100, e);
},
/**
* onDrop
* on drop files
*
* @namespace dragDrop
* @param {Event} e - jQuery event
* @void
*/
onDrop: function(e) {
clearTimeout(f.dragDrop._timer);
// remove dragging class from parent element
n.dragDrop.container.removeClass('fileuploader-dragging');
// set feedback caption
f.set('feedback', null);
// check if event has dropped files and use them
if (e && e.originalEvent && e.originalEvent.dataTransfer && e.originalEvent.dataTransfer.files && e.originalEvent.dataTransfer.files.length) {
if (f.isUploadMode()) {
f.onChange(e, e.originalEvent.dataTransfer.files);
} else {
s.prop('files', e.originalEvent.dataTransfer.files).trigger('change');
}
}
// dragDrop.onDrop callback
n.dragDrop.onDrop != null && $.isFunction(n.dragDrop.onDrop) ? n.dragDrop.onDrop(e, l, p, o, s) : null;
},
/**
* _dragLeaveCheck
* check by the living from drag container if not the childNodes are hovered
*
* @namespace dragDrop
* @param {Event} e - jQuery event
* @return {bool} return the leaving statement
*/
_dragLeaveCheck: function(e) {
var related = $(e.currentTarget),
insideEls;
if (!related.is(n.dragDrop.container)) {
insideEls = n.dragDrop.container.find(related);
if (insideEls.length) {
return false;
}
}
return true;
}
},
/**
* @namespace clipboard
*/
clipboard: {
/**
* paste
* on pasting a file from clipboard on page
*
* @namespace clipboard
* @param {Event} e - jQuery event
* @void
*/
paste: function(e) {
// check if the input is into view and if clipboard is supported and if there are files in the clipboard
if (!f._assets.isIntoView(o) || !e.originalEvent.clipboardData || !e.originalEvent.clipboardData.items || !e.originalEvent.clipboardData.items.length)
return;
var items = e.originalEvent.clipboardData.items;
// extra clean
f.clipboard.clean();
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1 || items[i].type.indexOf("text/uri-list") !== -1) {
var blob = items[i].getAsFile(),
ms = n.clipboardPaste > 1 ? n.clipboardPaste : 2000;
if (blob) {
// create clipboard file name
blob._name = f._assets.generateFileName(blob.type.indexOf("/") != -1 ? blob.type.split("/")[1].toString().toLowerCase() : 'png', 'Clipboard ');
// set clipboard timer
f.set('feedback', f._assets.textParse(n.captions.paste, {ms: ms/1000}));
f.clipboard._timer = setTimeout(function() {
f.set('feedback', null);
f.onChange(e, [blob]);
}, ms-2);
}
}
}
},
/**
* clean
* clean the clipboard timer
*
* @namespace clipboard
* @void
*/
clean: function() {
if (f.clipboard._timer) {
clearTimeout(f.clipboard._timer);
delete f.clipboard._timer;
// set feedback caption
f.set('feedback', null);
}
}
},
/**
* @namespace files
*/
files: {
/**
* add
* add a file to memory
*
* @namespace files
* @param {Object} file
* @param {String} prop - type of adding a file to memory
* @return {Number} index - index of the item in memory array
*/
add: function(file, prop) {
var name = file._name || file.name,
size = file.size,
size2 = f._assets.bytesToText(size),
type = file.type,
format = type ? type.split('/', 1).toString().toLowerCase() : '',
extension = name.indexOf('.') != -1 ? name.split('.').pop().toLowerCase() : '',
title = name.substr(0, name.length - (name.indexOf('.') != -1 ? extension.length+1 : extension.length)),
data = file.data || {},
src = file.file || file,
id = prop == 'updated' ? file.id : Date.now(),
index,
item,
data = {
name: name,
title: title,
size: size,
size2: size2,
type: type,
format: format,
extension: extension,
data: data,
file: src,
reader: {
read: function(callback, type, force) { return f.files.read(item, callback, type, force); }
},
id: id,
input: prop == 'choosed' ? s : null,
html: null,
choosed: prop == 'choosed',
appended: prop == 'appended' || prop == 'updated',
uploaded: prop == 'uploaded'
};
if (prop != 'updated') {
f._itFl.push(data);
index = f._itFl.length - 1;
item = f._itFl[index];
} else {
index = f._itFl.indexOf(file);
f._itFl[index] = item = data;
}
item.remove = function() {
f.files.remove(item);
};
if (n.editor && format == 'image')
item.editor = {
rotate: n.editor.rotation !== false ? function(deg) {
f.editor.rotate(item, deg);
} : null,
cropper: n.editor.cropper !== false ? function(data) {
f.editor.crop(item, data);
} : null,
save: function(callback, toBlob, mimeType, preventThumbnailRender) {
f.editor.save(item, toBlob, mimeType, callback, preventThumbnailRender);
}
};
if (file.local)
item.local = file.local;
return index;
},
/**
* read
* read choosed file and sends the information to callback
*
* @namespace files
* @param {Object} item
* @param {Function} callback
* @param {String} type - FileReader readAs type
* @param {Boolean} force - force a new file read and ignore the existing
* @param {Boolean} isThumb - is thumbnail
* @return {null}
*/
read: function(item, callback, type, force, isThumb) {
if (f.isFileReaderSupported() && !item.data.readerSkip) {
var reader = new FileReader(),
URL = window.URL || window.webkitURL,
hasThumb = isThumb && item.data.thumbnail,
useFile = typeof item.file != 'string',
execute_callbacks = function() {
var _callbacks = item.reader._callbacks || [];
if (item.reader._timer) {
clearTimeout(item.reader._timer);
delete item.reader._timer;
}
delete item.reader._callbacks;
delete item.reader._FileReader;
for(var i = 0; i<_callbacks.length; i++) {
$.isFunction(_callbacks[i]) ? _callbacks[i](item, l, p, o, s) : null;
}
n.onFileRead && $.isFunction(n.onFileRead) ? n.onFileRead(item, l, p, o, s) : null;
};
if ((!item.reader.src && !item.reader._FileReader) || force)
item.reader = {
_FileReader: reader,
_callbacks: [],
read: item.reader.read
};
if (item.reader.src && !force)
return callback && $.isFunction(callback) ? callback(item, l, p, o, s) : null;
if (callback && item.reader._callbacks) {
item.reader._callbacks.push(callback);
if (item.reader._callbacks.length > 1)
return;
}
if (item.format == 'astext') {
reader.onload = function(e) {
var node = document.createElement('div');
item.reader.node = node;
item.reader.src = e.target.result;
item.reader.length = e.target.result.length;
node.innerHTML = item.reader.src.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
execute_callbacks();
};
reader.onerror = function() {
execute_callbacks();
item.reader = { read: item.reader.read };
};
if (useFile)
reader.readAsText(item.file);
else
$.ajax({
url : item.file,
success : function(result){
reader.onload({target: {result: result}});
},
error: function() {
reader.onerror();
}
});
} else if (item.format == 'image' || hasThumb) {
var src;
reader.onload = function(e) {
var node = new Image(),
loadNode = function() {
if (item.data && item.data.readerCrossOrigin)
node.setAttribute('crossOrigin', item.data.readerCrossOrigin);
node.src = e.target.result + ((item.data.readerForce || force) && !useFile && !hasThumb && e.target.result.indexOf('data:image') == -1 ? (e.target.result.indexOf('?') == -1 ? '?' : '&') + 'd=' + Date.now() : '');
node.onload = function() {
// exif rotate image
if (item.reader.exifOrientation) {
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
image = node,
rotation = Math.abs(item.reader.exifOrientation),
flip = item.reader.exifOrientation < 0 ? item.reader.exifOrientation : 0,
rotationCf = [0, 180];
// remove the rotaiton for flip -1
if (rotation == 1)
rotation = 0;
// set canvas size and image
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx.drawImage(image, 0, 0);
// rotate image
canvas.width = rotationCf.indexOf(rotation) > -1 ? image.naturalWidth : image.naturalHeight;
canvas.height = rotationCf.indexOf(rotation) > -1 ? image.naturalHeight : image.naturalWidth;
var angle = rotation*Math.PI/180,
cw = canvas.width * 0.5,
ch = canvas.height * 0.5;
// clear context
ctx.clearRect(0, 0, canvas.width, canvas.height);
// rotate context
ctx.translate(cw, ch);
ctx.rotate(angle);
ctx.translate(-image.naturalWidth * 0.5, -image.naturalHeight * 0.5);
if (flip) {
if ([-1, -180].indexOf(flip) > -1) {
ctx.translate(canvas.width, 0);
ctx.scale(-1, 1);
} else if([-90, -270].indexOf(flip) > -1) {
ctx.translate(0, canvas.width);
ctx.scale(1, -1);
}
}
// draw image and reset transform
ctx.drawImage(image, 0, 0);
ctx.setTransform(1, 0, 0, 1, 0, 0);
node.src = canvas.toDataURL(item.type, 1);
delete item.reader.exifOrientation;
return;
}
item.reader.node = node;
item.reader.src = node.src;
item.reader.width = node.width;
item.reader.height = node.height;
item.reader.ratio = f._assets.pxToRatio(item.reader.width, item.reader.height);
if (src)
URL.revokeObjectURL(src);
execute_callbacks();
if (hasThumb)
item.reader = { read: item.reader.read };
};
node.onerror = function() {
execute_callbacks();
item.reader = { read: item.reader.read };
};
};
// exif rotation
if (n.thumbnails.exif && item.choosed) {
f._assets.getExifOrientation(item.file, function(orientation) {
if (orientation)
item.reader.exifOrientation = orientation;
loadNode();
});
} else {
loadNode();
}
};
reader.onerror = function() {
execute_callbacks();
item.reader = { read: item.reader.read };
};
if (!hasThumb && item.size > f._assets.toBytes(n.reader.maxSize))
return reader.onerror();
if (useFile) {
if (n.thumbnails.useObjectUrl && n.thumbnails.canvasImage && URL)
reader.onload({target: {result: src = URL.createObjectURL(item.file)}});
else
reader.readAsDataURL(item.file);
} else {
reader.onload({target: {result: (hasThumb ? item.data.thumbnail : item.file)}});
}
} else if (item.format == 'video' || item.format == 'audio') {
var node = document.createElement(item.format),
canPlay = node.canPlayType(item.type),
src;
reader.onerror = function() {
item.reader.node = null;
execute_callbacks();
item.reader = { read: item.reader.read };
};
if (URL && canPlay !== '') {
if (isThumb && !n.thumbnails.videoThumbnail) {
item.reader.node = node;
execute_callbacks();
item.reader = { read: item.reader.read };
return;
}
src = useFile ? URL.createObjectURL(item.file) : item.file;
node.onloadedmetadata = function() {
item.reader.node = node;
item.reader.src = node.src;
item.reader.duration = node.duration;
item.reader.duration2 = f._assets.secondsToText(node.duration);
if (item.format == 'video') {
item.reader.width = node.videoWidth;
item.reader.height = node.videoHeight;
item.reader.ratio = f._assets.pxToRatio(item.reader.width, item.reader.height);
}
};
node.onerror = function() {
execute_callbacks();
item.reader = { read: item.reader.read };
};
node.onloadeddata = function() {
if (item.format == 'video') {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
canvas.width = node.videoWidth;
canvas.height = node.videoHeight;
context.drawImage(node, 0, 0, canvas.width, canvas.height);
item.reader.frame = !f._assets.isBlankCanvas(canvas) ? canvas.toDataURL() : null;
canvas = context = null;
}
execute_callbacks();
};
// dirty fix
setTimeout(function() {
if (item.data && item.data.readerCrossOrigin)
node.setAttribute('crossOrigin', item.data.readerCrossOrigin);
node.src = src + '#t=1';
}, 100);
} else {
reader.onerror();
}
} else if(item.type == 'application/pdf' && n.thumbnails.pdf) {
var node = document.createElement('iframe'),
src = useFile ? URL.createObjectURL(item.file) : (n.thumbnails.pdf.urlPrefix || '') + item.file;
if (n.thumbnails.pdf.viewer || f._assets.hasPlugin('pdf')) {
node.onload = function() {
item.reader.node = node;
item.reader.src = node.src;
node.style.display = '';
execute_callbacks();
};
node.src = (n.thumbnails.pdf.viewer || '') + src;
node.style.display = 'none';
document.body.appendChild(node);
} else {
execute_callbacks();
}
} else {
reader.onload = function(e) {
item.reader.src = e.target.result;
item.reader.length = e.target.result.length;
execute_callbacks();
};
reader.onerror = function(e) {
execute_callbacks();
item.reader = { read: item.reader.read };
};
useFile ? reader[type || 'readAsBinaryString'](item.file) : execute_callbacks();
}
item.reader._timer = setTimeout(reader.onerror, isThumb ? n.reader.thumbnailTimeout : n.reader.timeout);
} else {
if (callback)
callback(item, l, p, o, s);
}
return null;
},
/**
* list
* generate a list of files
*
* @namespace files
* @param {bool} toJSON - generate a JSON list
* @param {String} customKey - use a custom item attribute by generating
* @param {Boolean} triggered - function was triggered from the API
* @param {String} additional - additional settings
* @return {String|Object}
*/
list: function(toJson, customKey, triggered, additional) {
var files = [];
// save sorter
if (n.sorter && !triggered && (!additional || additional != 'ignoreSorter'))
f.sorter.save(true);
$.each(f._itFl, function(i, a) {
var file = a;
if (file.upload && !file.uploaded)
return true;
if (customKey || toJson)
file = (file.choosed && !file.uploaded ? '0:/' : '') + (customKey && f.files.getItemAttr(a, customKey) !== null ? f.files.getItemAttr(file, customKey) : (file.local || file[typeof file.file == "string" ? "file" : "name"]));
if (toJson) {
file = {file: file};
// editor properties
// add only if file was cropped or rotated
if (a.editor && (a.editor.crop || a.editor.rotation)) {
file.editor = {};
if (a.editor.rotation)
file.editor.rotation = a.editor.rotation;
if (a.editor.crop)
file.editor.crop = a.editor.crop;
}
// sorting property
if (typeof a.index !== 'undefined') {
file.index = a.index;
}
// custom properties
if (a.data && a.data.listProps) {
for (var key in a.data.listProps) {
file[key] = a.data.listProps[key];
}
}
}
files.push(file);
});
files = n.onListInput && $.isFunction(n.onListInput)? n.onListInput(files, f._itFl, n.listInput, l, p, o, s) : files;
return !toJson ? files : JSON.stringify(files);
},
/**
* check
* check the files
*
* @namespace files
* @param {Object} item
* @param {Array} files
* @param {bool} fullCheck - check some parameters that should be checked only once
* @return {bool|Array} r
*/
check: function(item, files, fullCheck) {
var r = ["warning", null, false, false];
if (n.limit != null && fullCheck && files.length + f._itFl.length - 1 > n.limit) {
r[1] = f._assets.textParse(n.captions.errors.filesLimit);
r[3] = true;
return r;
}
if (n.maxSize != null && fullCheck) {
var g = 0;
$.each(f._itFl, function(i, a) {
g += a.size;
}); g -= item.size;
$.each(files, function(i, a) {
g += a.size;
});
if (g > f._assets.toBytes(n.maxSize)) {
r[1] = f._assets.textParse(n.captions.errors.filesSizeAll);
r[3] = true;
return r;
}
}
if (n.onFilesCheck != null && $.isFunction(n.onFilesCheck) && fullCheck) {
var onFilesCheck = n.onFilesCheck(files, n, l, p, o, s);
if (onFilesCheck === false) {
r[3] = true;
return r;
}
}
if (n.extensions != null && $.inArray(item.extension, n.extensions) == -1 && !n.extensions.filter(function(val) { return item.type.length && (val.indexOf(item.type) > -1 || val.indexOf(item.format + '/*') > -1) }).length) {
r[1] = f._assets.textParse(n.captions.errors.filesType, item);
return r;
}
if (n.disallowedExtensions != null && ($.inArray(item.extension, n.disallowedExtensions) > -1 || n.disallowedExtensions.filter(function(val) { return !item.type.length || val.indexOf(item.type) > -1 || val.indexOf(item.format + '/*') > -1 }).length)) {
r[1] = f._assets.textParse(n.captions.errors.filesType, item);
return r;
}
if (n.fileMaxSize != null && item.size > f._assets.toBytes(n.fileMaxSize)) {
r[1] = f._assets.textParse(n.captions.errors.fileSize, item);
return r;
}
if (item.size == 0 && item.type == "") {
r[1] = f._assets.textParse(n.captions.errors.remoteFile, item);
return r;
}
if (item.size == 4096 && item.type == "") {
r[1] = f._assets.textParse(n.captions.errors.folderUpload, item);
return r;
}
if (!n.skipFileNameCheck) {
var g = false;
$.each(f._itFl, function(i, a) {
if (a != item && a.choosed == true && a.file && a.name == item.name) {
g = true;
if (a.file.size == item.size && a.file.type == item.type && (item.file.lastModified && a.file.lastModified ? a.file.lastModified == item.file.lastModified : true) && files.length > 1) {
r[2] = true;
} else {
r[1] = f._assets.textParse(n.captions.errors.fileName, item);
r[2] = false;
}
return false;
}
});
if (g) {
return r;
}
}
return true;
},
/**
* append
* check the files
*
* @namespace files
* @param {Array} files
* @return {bool|Object}
*/
append: function(files) {
files = $.isArray(files) ? files : [files];
if (files.length) {
var item;
for (var i = 0; i < files.length; i++) {
if (!f._assets.keyCompare(files[i], ['name', 'file', 'size', 'type'])) {
continue;
}
item = f._itFl[f.files.add(files[i], 'appended')];
n.thumbnails ? f.thumbnails.item(item) : null;
}
// set feedback caption
f.set('feedback', null);
// set listInput value
f.set('listInput', null);
// afterSelect callback
n.afterSelect && $.isFunction(n.afterSelect) ? n.afterSelect(l, p, o, s) : null;
return files.length == 1 ? item : true;
}
},
/**
* update
* update an item using new information
*
* @namespace files
* @param {Object} item
* @param {Object} data
* @return void
*/
update: function(item, data) {
if (f._itFl.indexOf(item) == -1 || (item.upload && item.upload.$ajax))
return;
var oldItem = item,
index = f.files.add($.extend(item, data), 'updated'),
item = f._itFl[index];
if (item.popup && item.popup.close)
item.popup.close();
if (n.thumbnails && oldItem.html)
f.thumbnails.item(item, oldItem.html);
f.set('listInput', null);
},
/**
* find
* find an item in memory using html element
*
* @namespace files
* @param {jQuery Object} html
* @return {null,Object}
*/
find: function(html) {
var item = null;
$.each(f._itFl, function(i, a) {
if (a.html && a.html.is(html)) {
item = a;
return false;
}
});
return item;
},
/**
* remove
* remove an item from memory and html
*
* @namespace files
* @param {Object} item
* @param {bool} isFromCheck - if removing function was triggered by checking a file
* @return {null,Object}
*/
remove: function(item, isFromCheck) {
// onRemove callback
if (!isFromCheck && n.onRemove && $.isFunction(n.onRemove) && n.onRemove(item, l, p, o, s) === false)
return;
// thumbnails.onItemRemove callback
if (item.html)
n.thumbnails.onItemRemove && $.isFunction(n.thumbnails.onItemRemove) && !isFromCheck ? n.thumbnails.onItemRemove(item.html, l, p, o, s) : item.html.remove();
// cancel file upload
if (item.upload && item.upload.$ajax && item.upload.cancel)
item.upload.cancel(true);
// remove popup
if (item.popup && item.popup.close)
item.popup.close();
// remove filereader
if (item.reader.src) {
item.reader.node = null;
URL.revokeObjectURL(item.reader.src);
}
// check if any file is in the same input like item.input
if (item.input) {
var g = true;
$.each(f._itFl, function(i, a) {
if (item != a && (item.input == a.input || (isFromCheck && item.input.get(0).files.length > 1))) {
g = false;
return false;
}
});
if (g) {
if (f.isAddMoreMode() && sl.length > 1) {
f.set('nextInput');
sl.splice(sl.indexOf(item.input), 1);
item.input.remove();
} else {
f.set('input', '');
}
}
}
// remove data from memory
f._pfrL.indexOf(item) > -1 ? f._pfrL.splice(f._pfrL.indexOf(item), 1) : null;
f._pfuL.indexOf(item) > -1 ? f._pfuL.splice(f._pfuL.indexOf(item), 1) : null;
f._itFl.indexOf(item) > -1 ? f._itFl.splice(f._itFl.indexOf(item), 1) : null;
item = null;
// reset the plugin if there are no any files in the memory
f._itFl.length == 0 ? f.reset() : null;
// set feedback caption
f.set('feedback', null);
// set listInput value
f.set('listInput', null);
},
/**
* getItemAttr
* get an attribute from item or item.data
*
* @namespace files
* @param {Object} item
* @param {String} attr - attribute key
* @return {null,String}
*/
getItemAttr: function(item, attr) {
var result = null;
if (item) {
if (typeof item[attr] != "undefined") {
result = item[attr];
} else if (item.data && typeof item.data[attr] != "undefined") {
result = item.data[attr];
}
}
return result;
},
/**
* clear
* clear files from the memory
* delete also item.html and item.upload data
*
* @namespace files
* @param {bool} all - delete also appended files?
* @void
*/
clear: function(all) {
var i = 0;
while (i < f._itFl.length) {
var a = f._itFl[i];
if (!all && a.appended) {
i++;
continue;
}
if (a.html)
a.html ? f._itFl[i].html.remove() : null;
if (a.upload && a.upload.$ajax)
f.upload.cancel(a);
f._itFl.splice(i, 1);
}
// set feedback caption
f.set('feedback', null);
// set listInput value
f.set('listInput', null);
// onEmpty callback
f._itFl.length == 0 && n.onEmpty && $.isFunction(n.onEmpty) ? n.onEmpty(l, p, o, s) : null;
}
},
/**
* reset
* reset the plugin
*
* @param {bool} all - remove also appended files?
* @void
*/
reset: function(all) {
if (all) {
if (f.clipboard._timer)
f.clipboard.clean();
$.each(sl, function(i, a) {
if (i < sl.length)
a.remove();
});
sl = [];
f.set('input', '');
}
f._itRl = [];
f._pfuL = [];
f._pfrL = [];
f.files.clear(all);
},
/**
* destroy
* destroy the plugin
*
* @void
*/
destroy: function() {
f.reset(true);
f.bindUnbindEvents(false);
s.removeAttr('style');
p.before(s);
delete s.get(0).FileUploader;
p.remove();
p = o = l = null;
},
/**
* @namespace _assets
*/
_assets: {
toBytes: function(mb) {
return parseInt(mb) * 1048576;
},
bytesToText: function(bytes) {
if (bytes == 0)
return '0 Byte';
var k = 1024,
sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
},
escape: function(str) {
return ('' + str).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;")
},
secondsToText: function(seconds, textFormat) {
seconds = parseInt(Math.round(seconds), 10);
var hours = Math.floor(seconds / 3600),
minutes = Math.floor((seconds - (hours * 3600)) / 60),
seconds = seconds - (hours * 3600) - (minutes * 60),
result = "";
if (hours > 0 || !textFormat) {
result += (hours < 10 ? "0" : "") + hours + (textFormat ? "h " : ":");
}
if (minutes > 0 || !textFormat) {
result += (minutes < 10 && !textFormat ? "0" : "") + minutes + (textFormat ? "m " : ":");
}
result += (seconds < 10 && !textFormat ? "0" : "") + seconds + (textFormat ? "s" : "");
return result;
},
pxToRatio: function(width, height) {
var gcd = function(a, b) {
return (b == 0) ? a : gcd (b, a%b);
},
r = gcd(width, height);
return [width/r, height/r];
},
ratioToPx: function(width, height, ratio) {
ratio = (ratio+'').split(':');
if (ratio.length < 2)
return null;
var rWidth = height / ratio[1] * ratio[0],
rHeight = width / ratio[0] * ratio[1];
return [rWidth, rHeight, ratio[0], ratio[1]];
},
hasAttr: function(attr, el) {
var el = !el ? s : el,
a = el.attr(attr);
if (!a || typeof a == 'undefined') {
return false;
} else {
return true;
}
},
copyAllAttributes: function(newEl, oldEl) {
$.each(oldEl.get(0).attributes, function() {
if (this.name == 'required' || this.name == 'type') return;
newEl.attr(this.name, this.value);
});
if (oldEl.get(0).FileUploader)
newEl.get(0).FileUploader = oldEl.get(0).FileUploader;
return newEl;
},
getAllEvents: function(el) {
var el = !el ? s : el,
result = [];
el = el.get ? el.get(0) : el;
for (var key in el) {
if (key.indexOf('on') === 0) {
result.push(key.slice(2));
}
}
if (result.indexOf('change') == -1)
result.push('change');
return result.join(' ');
},
isIntoView: function(el) {
var windowTop = $(window).scrollTop(),
windowBottom = windowTop + window.innerHeight,
elTop = el.offset().top,
elBottom = elTop + el.outerHeight();
return ((windowTop < elTop) && (windowBottom > elBottom));
},
isBlankCanvas: function(canvas) {
var blank = document.createElement('canvas'),
result = false;
blank.width = canvas.width;
blank.height = canvas.height;
try {
result = canvas.toDataURL() == blank.toDataURL();
} catch(e) {}
blank = null;
return result;
},
generateFileName: function(extension, prefix) {
var date = new Date(),
addZero = function(x) {
if (x < 10)
x = "0" + x;
return x;
},
prefix = prefix ? prefix : '',
extension = extension ? '.' + extension : '';
return prefix + date.getFullYear() + '-' + addZero(date.getMonth()+1) + '-' + addZero(date.getDate()) + ' ' + addZero(date.getHours()) + '-' + addZero(date.getMinutes()) + '-' + addZero(date.getSeconds()) + extension;
},
arrayBufferToBase64: function(buffer) {
var binary = '',
bytes = new Uint8Array(buffer);
for (var i = 0; i < bytes.byteLength; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
},
dataURItoBlob: function(dataURI, type) {
var byteString = atob(dataURI.split(',')[1]),
mimeType = dataURI.split(',')[0].split(':')[1].split(';')[0],
arrayBuffer = new ArrayBuffer(byteString.length),
_ia = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteString.length; i++) {
_ia[i] = byteString.charCodeAt(i);
}
var dataView = new DataView(arrayBuffer),
blob = new Blob([dataView.buffer], { type: type || mimeType });
return blob;
},
getExifOrientation: function(file, callback) {
var reader = new FileReader(),
rotation = {
1: 0,
2: -1,
3: 180,
4: -180,
5: -90,
6: 90,
7: -270,
8: 270
};
reader.onload = function(e) {
var scanner = new DataView(e.target.result),
val = 1;
if (scanner.byteLength && scanner.getUint16(0, false) == 0xFFD8) {
var length = scanner.byteLength,
offset = 2;
while (offset < length) {
if (scanner.getUint16(offset + 2, false) <= 8)
break;
var uint16 = scanner.getUint16(offset, false);
offset += 2;
if (uint16 == 0xFFE1) {
if (scanner.getUint32(offset += 2, false) != 0x45786966)
break;
var little = scanner.getUint16(offset += 6, false) == 0x4949,
tags;
offset += scanner.getUint32(offset + 4, little);
tags = scanner.getUint16(offset, little);
offset += 2;
for (var i = 0; i < tags; i++) {
if (scanner.getUint16(offset + (i * 12), little) == 0x0112) {
val = scanner.getUint16(offset + (i * 12) + 8, little);
length = 0;
break;
}
}
} else if ((uint16 & 0xFF00) != 0xFF00) {
break;
} else {
offset += scanner.getUint16(offset, false);
}
}
}
callback ? callback(rotation[val] || 0) : null;
};
reader.onerror = function() {
callback ? callback('') : null;
};
reader.readAsArrayBuffer(file);
},
textParse: function(text, opts, noOptions) {
opts = noOptions ? (opts || {}) : $.extend({}, {
limit: n.limit,
maxSize: n.maxSize,
fileMaxSize: n.fileMaxSize,
extensions: n.extensions ? n.extensions.join(', ') : null,
captions: n.captions
}, opts);
switch (typeof(text)) {
case 'string':
for (var key in opts) {
if (['name', 'file', 'type', 'size'].indexOf(key) > -1)
opts[key] = f._assets.escape(opts[key]);
}
text = text.replace(/\$\{(.*?)\}/g, function(match, a) {
var a = a.replace(/ /g, ''),
r = typeof opts[a] != "undefined" && opts[a] != null ? opts[a] : '';
if (['reader.node'].indexOf(a) > -1)
return match;
if (a.indexOf('.') > -1 || a.indexOf('[]') > -1) {
var x = a.substr(0, a.indexOf('.') > -1 ? a.indexOf('.') : a.indexOf('[') > -1 ? a.indexOf('[') : a.length),
y = a.substring(x.length);
if (opts[x]) {
try {
r = eval('opts["' + x + '"]' + y);
} catch(e) {
r = '';
}
}
}
r = $.isFunction(r) ? f._assets.textParse(r) : r;
return r || '';
});
break;
case 'function':
text = f._assets.textParse(text(opts, l, p, o, s, f._assets.textParse), opts, noOptions);
break;
}
opts = null;
return text;
},
textToColor: function(str) {
if (!str || str.length == 0)
return false;
for (var i = 0, hash = 0; i < str.length; hash = str.charCodeAt(i++) + ((hash << 5) - hash));
for (var i = 0, colour = '#'; i < 3; colour += ('00' + ((hash >> i++ * 2) & 0xFF)
.toString(16))
.slice(-2));
return colour;
},
isBrightColor: function(color) {
var getRGB = function(b) {
var a;
if (b && b.constructor == Array && b.length == 3) return b;
if (a = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b)) return [parseInt(a[1]), parseInt(a[2]), parseInt(a[3])];
if (a = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b)) return [parseFloat(a[1]) * 2.55, parseFloat(a[2]) * 2.55, parseFloat(a[3]) * 2.55];
if (a = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b)) return [parseInt(a[1], 16), parseInt(a[2], 16), parseInt(a[3],
16)];
if (a = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b)) return [parseInt(a[1] + a[1], 16), parseInt(a[2] + a[2], 16), parseInt(a[3] + a[3], 16)];
return (typeof(colors) != "undefined") ? colors[$.trim(b).toLowerCase()] : null
},
luminance_get = function(color) {
var rgb = getRGB(color);
if (!rgb) return null;
return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
};
return luminance_get(color) > 194;
},
keyCompare: function(obj, structure) {
for(var i = 0; i<structure.length; i++) {
if (!$.isPlainObject(obj) || !obj.hasOwnProperty(structure[i])) {
throw new Error('Could not find valid *strict* attribute "'+ structure[i] +'" in ' + JSON.stringify(obj, null, 4));
}
}
return true;
},
dialogs: {
alert: n.dialogs.alert,
confirm: n.dialogs.confirm
},
hasPlugin: function(name) {
if (navigator.plugins && navigator.plugins.length)
for (var key in navigator.plugins) {
if (navigator.plugins[key].name.toLowerCase().indexOf(name) > -1)
return true;
}
return false;
},
isIE: function() {
return navigator.userAgent.indexOf("MSIE ") > -1 || navigator.userAgent.indexOf("Trident/") > -1 || navigator.userAgent.indexOf("Edge") > -1;
},
isMobile: function() {
return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1);
}
},
isSupported: function() {
return s && s.get(0).files;
},
isFileReaderSupported: function() {
return window.File && window.FileList && window.FileReader;
},
isDefaultMode: function() {
return !n.upload && (!n.addMore || n.limit == 1);
},
isAddMoreMode: function() {
return !n.upload && n.addMore && n.limit != 1;
},
isUploadMode: function() {
return n.upload;
},
// fileuploader file list
_itFl: [],
// fileuploader file upload pending list
_pfuL: [],
// fileuploader file render pending list
_pfrL: [],
// disabled
disabled: false,
// locked
locked: false,
// rendered
rendered: false
};
// set FileUploader property to the input
if (n.enableApi) {
s.get(0).FileUploader = {
open: function() {
s.trigger('click');
},
getOptions: function() {
return n;
},
getParentEl: function() {
return p;
},
getInputEl: function() {
return s;
},
getNewInputEl: function() {
return o;
},
getListEl: function() {
return l;
},
getListInputEl: function() {
return n.listInput;
},
getFiles: function() {
return f._itFl;
},
getChoosedFiles: function() {
return f._itFl.filter(function(a) {
return a.choosed;
});
},
getAppendedFiles: function() {
return f._itFl.filter(function(a) {
return a.appended;
});
},
getUploadedFiles: function() {
return f._itFl.filter(function(a) {
return a.uploaded;
});
},
getFileList: function(toJson, customKey) {
return f.files.list(toJson, customKey, true);
},
updateFileList: function() {
f.set('listInput', null);
return true;
},
setOption: function(option, value) {
n[option] = value;
return true;
},
findFile: function(html) {
return f.files.find(html);
},
add: function(data, type, name) {
if (!f.isUploadMode())
return false;
var blob;
if (data instanceof Blob) {
blob = data;
} else {
var dataURI = /data:[a-z]+\/[a-z]+\;base64\,/.test(data) ? data : 'data:' + type + ';base64,' + btoa(data);
blob = f._assets.dataURItoBlob(dataURI, type);
}
blob._name = name || f._assets.generateFileName(blob.type.indexOf("/") != -1 ? blob.type.split("/")[1].toString().toLowerCase() : 'File ');
f.onChange(null, [blob]);
return true;
},
append: function(files) {
return f.files.append(files);
},
update: function(item, data) {
return f.files.update(item, data);
},
remove: function(item) {
item = item.jquery ? f.files.find(item) : item;
if (f._itFl.indexOf(item) > -1) {
f.files.remove(item);
return true;
}
return false;
},
uploadStart: function() {
var choosedFiles = this.getChoosedFiles() || [];
if (f.isUploadMode() && choosedFiles.length > 0 && !choosedFiles[0].uploaded) {
for(var i = 0; i<choosedFiles.length; i++) {
f.upload.send(choosedFiles[i]);
}
}
},
reset: function() {
f.reset(true);
return true;
},
disable: function(lock) {
f.set('disabled', true);
if (lock)
f.locked = true;
return true;
},
enable: function() {
f.set('disabled', false);
f.locked = false;
return true;
},
destroy: function() {
f.destroy();
return true;
},
isEmpty: function() {
return f._itFl.length == 0;
},
isDisabled: function() {
return f.disabled;
},
isRendered: function() {
return f.rendered;
},
assets: f._assets,
getPluginMode: function() {
if (f.isDefaultMode())
return 'default';
if (f.isAddMoreMode())
return 'addMore';
if (f.isUploadMode())
return 'upload';
}
};
}
// initialize the plugin
f.init();
return this;
});
};
$.fileuploader = {
getInstance: function(input) {
var $input = input.prop ? input : $(input);
return $input.length ? $input.get(0).FileUploader : null;
}
};
$.fn.fileuploader.languages = {
cz: {
button: function(options) {
return 'Procházet ' + (options.limit == 1 ? 'soubor': 'soubory')
},
feedback: function(options) {
return 'Vyberte ' + (options.limit == 1 ? 'soubor' : 'soubory') + ', který chcete nahrát' },
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'vybráno souborů' : 'vybrán soubor')
},
confirm: 'Potvrdit',
cancel: 'Zrušeni',
name: 'Jméno',
type: 'Format',
size: 'Velikost',
dimensions: 'Rozměry',
duration: 'Trvání',
crop: 'Oříznout',
rotate: 'Otočit',
sort: 'Roztřídit',
open: 'Otevřít',
download: 'Stáhnout',
remove: 'Odstranit',
drop: 'Pro nahrání přetahněte soubor sem',
paste: '<div class="fileuploader-pending-loader"></div> Vkládání souboru, klikněte zde pro zrušeni',
removeConfirmation: 'Jste si jisti, že chcete odstranit tento soubor?',
errors: {
filesLimit: function(options) {
return 'Pouze ${limit} ' + (options.limit == 1 ? 'soubor může být nahrán' : 'soubory mohou byt nahrané') + '.'
},
filesType: 'Pouze ${extensions} soubory mohou byt nahrané.',
fileSize: '${name} příliš velký! Prosím, vyberte soubor do velikosti ${fileMaxSize} MB.',
filesSizeAll: 'Vybraný soubor je příliš velký! Prosím, vyberte soubor do velikosti ${maxSize} MB.',
fileName: 'Soubor s tímto názvem ${name} byl už vybran.',
remoteFile: 'Vzdálené soubory nejsou povoleny.',
folderUpload: 'Složky nejsou povolené.',
}
},
de: {
button: function(options) {
return (options.limit == 1 ? 'Datei' : 'Dateien') + ' durchsuchen'
},
feedback: function(options) {
return (options.limit == 1 ? 'Datei' : 'Dateien') + ' zum Hochladen auswählen'
},
feedback2: function(options) {
return options.length + ' ' + (options.length == 1 ? 'Datei' : 'Dateien') + ' ausgewählt'
},
confirm: 'Speichern',
cancel: 'Schließen',
name: 'Name',
type: 'Typ',
size: 'Größe',
dimensions: 'Format',
duration: 'Länge',
crop: 'Crop',
rotate: 'Rotieren',
sort: 'Sortieren',
open: 'Öffnen',
download: 'Herunterladen',
remove: 'Löschen',
drop: 'Die Dateien hierher ziehen, um sie hochzuladen',
paste: '<div class="fileuploader-pending-loader"></div> Eine Datei wird eingefügt. Klicken Sie hier zum abzubrechen',
removeConfirmation: 'Möchten Sie diese Datei wirklich löschen?',
errors: {
filesLimit: function(options) {
return 'Nur ${limit} ' + (options.limit == 1 ? 'Datei darf' : 'Dateien dürfen') + ' hochgeladen werden.'
},
filesType: 'Nur ${extensions} Dateien dürfen hochgeladen werden.',
fileSize: '${name} ist zu groß! Bitte wählen Sie eine Datei bis zu ${fileMaxSize} MB.',
filesSizeAll: 'Die ausgewählten Dateien sind zu groß! Bitte wählen Sie Dateien bis zu ${maxSize} MB.',
fileName: 'Eine Datei mit demselben Namen ${name} ist bereits ausgewählt.',
remoteFile: 'Remote-Dateien sind nicht zulässig.',
folderUpload: 'Ordner sind nicht erlaubt.',
}
},
dk: {
button: function(options) {
return 'Gennemse ' + (options.limit == 1 ? 'fil' : 'filer')
},
feedback: function(options) {
return 'Vælg ' + (options.limit == 1 ? 'fil' : 'filer') + ' til upload'
},
feedback2: function(options) {
return options.length + ' ' + (options.length == 1 ? 'fil' : 'filer') + ' er valgt'
},
confirm: 'Bekræft',
cancel: 'Fortrydl',
name: 'Navn',
type: 'Type',
size: 'Størrelse',
dimensions: 'Dimensioner',
duration: 'Varighed’',
crop: 'Tilpas',
rotate: 'Rotér',
sort: 'Sorter',
open: 'Åben',
download: 'Hent',
remove: 'Slet',
drop: 'Drop filer her til upload',
paste: 'Overfør fil, klik her for at afbryde',
removeConfirmation: 'Er du sikker på, du ønsker at slette denne fil?',
errors: {
filesLimit: function(options) {
return 'Du kan kun uploade ${limit} ' + (options.limit == 1 ? 'fil' : 'filer') + ' ad gangen.'
},
filesType: 'Det er kun tilladt at uploade ${extensions} filer.',
fileSize: '${name} er for stor! Vælg venligst en fil på højst ${fileMaxSize} MB.',
filesSizeAll: 'De valgte filer er for store! Vælg venligst filer op til ${maxSize} MB ialt.',
fileName: 'Du har allerede valgt en fil med navnet ${name}.',
remoteFile: 'Fremmede filer er ikke tilladt.',
folderUpload: 'Mapper er ikke tilladt.',
}
},
en: {
button: function(options) {
return 'Browse ' + (options.limit == 1 ? 'file' : 'files')
},
feedback: function(options) {
return 'Choose ' + (options.limit == 1 ? 'file' : 'files') + ' to upload'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? ' files were' : ' file was') + ' chosen'
},
confirm: 'Confirm',
cancel: 'Cancel',
name: 'Name',
type: 'Type',
size: 'Size',
dimensions: 'Dimensions',
duration: 'Duration',
crop: 'Crop',
rotate: 'Rotate',
sort: 'Sort',
open: 'Open',
download: 'Download',
remove: 'Delete',
drop: 'Drop the files here to upload',
paste: '<div class="fileuploader-pending-loader"></div> Pasting a file, click here to cancel',
removeConfirmation: 'Are you sure you want to delete this file?',
errors: {
filesLimit: function(options) {
return 'Only ${limit} ' + (options.limit == 1 ? 'file' : 'files') + ' can 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: 'The chosen files are too large! Please select files up to ${maxSize} MB.',
fileName: 'A file with the same name ${name} is already selected.',
remoteFile: 'Remote files are not allowed.',
folderUpload: 'Folders are not allowed.',
}
},
es: {
button: function(options) {
return 'Examinar ' + (options.limit == 1 ? 'archivo' : 'archivos')
},
feedback: function(options) {
return 'Selecciona ' + (options.limit == 1 ? 'archivos' : 'archivos') + ' para subir'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'archivos seleccionados' : 'archivo seleccionado')
},
confirm: 'Guardar',
cancel: 'Anular',
name: 'Nombre',
type: 'Tipo',
size: 'Tamaño',
dimensions: 'Dimensiones',
duration: 'Duracion',
crop: 'Corta',
rotate: 'Rotar',
sort: 'Ordenar',
open: 'Abierto',
download: 'Descargar',
remove: 'Eliminar',
drop: 'Suelta los archivos aquí para subirlos',
paste: '<div class="fileuploader-pending-loader"></div> Pegar un archivo, haga clic aquí para cancelar',
removeConfirmation: '¿Estás seguro de que deseas eliminar este archivo?',
errors: {
filesLimit: function(options) {
return 'Solo se pueden seleccionar ${limit} ' + (options.limit == 1 ? 'archivo' : 'archivos') + '.'
},
filesType: 'Solo se pueden seleccionar archivos ${extensions}.',
fileSize: '${name} es demasiado grande! Por favor, seleccione un archivo hasta ${fileMaxSize} MB.',
filesSizeAll: '¡Los archivos seleccionados son demasiado grandes! Por favor seleccione archivos de hasta ${maxSize} MB.',
fileName: 'Un archivo con el mismo nombre ${name} ya está seleccionado.',
remoteFile: 'Los archivos remotos no están permitidos.',
folderUpload: 'No se permiten carpetas.',
}
},
fr: {
button: function(options) {
return 'Parcourir ' + (options.limit == 1 ? 'le fichier' : 'les fichiers')
},
feedback: function(options) {
return 'Choisir ' + (options.limit == 1 ? 'le fichier ' : 'les fichiers') + ' à télécharger'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'fichiers ont été choisis' : 'fichier a été choisi')
},
confirm: 'Confirmer',
cancel: 'Annuler',
name: 'Nom',
type: 'Type',
size: 'Taille',
dimensions: 'Dimensions',
duration: 'Durée',
crop: 'Recadrer',
rotate: 'Pivoter',
sort: 'Trier',
download: 'Télécharger',
remove: 'Supprimer',
drop: 'Déposez les fichiers ici pour les télécharger',
paste: '<div class="fileuploader-pending-loader"></div> Collant un fichier, cliquez ici pour annuler.',
removeConfirmation: 'Êtes-vous sûr de vouloir supprimer ce fichier ?',
errors: {
filesLimit: 'Seuls les fichiers ${limit} peuvent être téléchargés.',
filesType: 'Seuls les fichiers ${extensions} peuvent être téléchargés.',
fileSize: '${name} est trop lourd, la limite est de ${fileMaxSize} MB.',
filesSizeAll: 'Les fichiers que vous avez choisis sont trop lourd, la limite totale est de ${maxSize} MB.',
fileName: 'Le fichier portant le nom ${name} est déjà sélectionné.',
folderUpload: 'Vous n\'êtes pas autorisé à télécharger des dossiers.'
}
},
it: {
button: function(options) {
return 'Sfoglia' + (options.limit == 1 ? 'il file' : 'i file')
},
feedback: function(options) {
return 'Seleziona ' + (options.limit == 1 ? 'file' : 'i file') + ' per caricare'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'i file sono scelti' : 'il file è scelto')
},
confirm: 'Conferma',
cancel: 'Cancella',
name: 'Nome',
type: 'Tipo file',
size: 'Dimensione file',
dimensions: 'Dimensioni',
duration: 'Durata',
crop: 'Taglia',
rotate: 'Ruota',
sort: 'Ordina',
open: 'Apri',
download: 'Scarica',
remove: 'Elimina',
drop: 'Posiziona il file qui per caricare',
paste: '<div class="fileuploader-pending-loader"></div> Incolla file, clicca qui per cancellare',
removeConfirmation: 'Sei sicuro di voler eliminare il file?',
errors: {
filesLimit: 'Solo ${limit} file possono essere caricati.',
filesType: 'Solo ${extensions} file possono essere caricati.',
fileSize: '${name} è troppo grande! Scegli un file fino a ${fileMaxSize} MB.',
filesSizeAll: 'I file selezioni sono troppo grandi! Scegli un file fino a ${maxSize} MB.',
fileName: 'Un file con lo stesso nome ${name} è già selezionato.',
remoteFile: 'I file remoti non sono consentiti.',
folderUpload: 'Le cartelle non sono consentite.',
}
},
lv: {
button: function(options) {
return 'Izvēlieties ' + (options.limit == 1 ? 'fails' : 'faili')
},
feedback: function(options) {
return 'Izvēliejaties ' + (options.limit == 1 ? 'fails' : 'faili') + ' lejupielādēt'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'failus izvelēts' : 'fails izvēlēts')
},
confirm: 'Saglabāt',
cancel: 'Atcelt',
name: 'Vārds',
type: 'Formāts',
size: 'Izmērs',
dimensions: 'Izmēri',
duration: 'Ilgums',
crop: 'Nogriezt',
rotate: 'Pagriezt',
sort: 'Kārtot',
open: 'Atvērt',
download: 'Lejupielādēt',
remove: 'Dzēst',
drop: 'Lai augšupielādētu, velciet failus šeit',
paste: '<div class="fileuploader-pending-loader"></div> Ievietojiet failu, noklikšķiniet šeit, lai atceltu',
removeConfirmation: 'Vai tiešām vēlaties izdzēst šo failu?',
errors: {
filesLimit: function(options) {
return 'Tikai ${limit} ' + (options.limit == 1 ? 'failu var augšupielādēt' : 'failus var augšupielādēt') + '.'
},
filesType: 'Tikai ${extensions} failus var augšupielādēt.',
fileSize: '${name} ir par lielu! Lūdzu, atlasiet failu līdz ${fileMaxSize} MB.',
filesSizeAll: 'Atlasītie faili ir pārāk lieli! Lūdzu, atlasiet failus līdz ${maxSize} MB.',
fileName: 'Fails ar tādu pašu nosaukumu ${name} jau ir atlasīts.',
remoteFile: 'Attālie faili nav atļauti.',
folderUpload: 'Mapes nav atļautas.',
}
},
nl: {
button: function(options) {
return (options.limit == 1 ? 'Bestand' : 'Bestanden') + ' kiezen'
},
feedback: function(options) {
return 'Kies ' + (options.limit == 1 ? 'een bestand' : 'bestanden') + ' om te uploaden'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'bestanden' : 'bestand') + ' gekozen'
},
confirm: 'Opslaan',
cancel: 'Annuleren',
name: 'Naam',
type: 'Type',
size: 'Grootte',
dimensions: 'Afmetingen',
duration: 'Duur',
crop: 'Uitsnijden',
rotate: 'Draaien',
sort: 'Sorteren',
open: 'Open',
download: ' Downloaden',
remove: 'Verwijderen',
drop: 'Laat de bestanden hier vallen om te uploaden',
paste: '<div class="fileuploader-pending-loader"></div> Een bestand wordt geplakt, klik hier om te annuleren',
removeConfirmation: 'Weet u zeker dat u dit bestand wilt verwijderen?',
errors: {
filesLimit: function(options) {
return 'Er ' + (options.limit == 1 ? 'mag' : 'mogen') + ' slechts ${limit} ' + (options.limit == 1 ? 'bestand' : 'bestanden') + ' worden geüpload.'
},
filesType: 'Alleen ${extensions} mogen worden geüpload.',
fileSize: '${name} is te groot! Kies een bestand tot ${fileMaxSize} MB.',
filesSizeAll: 'De gekozen bestanden zijn te groot! Kies bestanden tot ${maxSize} MB.',
fileName: 'Een bestand met dezelfde naam ${name} is al gekozen.',
remoteFile: 'Externe bestanden zijn niet toegestaan.',
folderUpload: 'Mappen zijn niet toegestaan.',
}
},
pl: {
button: function(options) {
return 'Wybierz ' + (options.limit == 1 ? 'plik' : 'pliki')
},
feedback: function(options) {
return 'Wybierz ' + (options.limit == 1 ? 'plik' : 'pliki') + ' do przesłania'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'pliki zostały wybrane' : 'plik został wybrany')
},
confirm: 'Potwierdź',
cancel: 'Anuluj',
name: 'Nazwa',
type: 'Typ',
size: 'Rozmiar',
dimensions: 'Wymiary',
duration: 'Czas trwania',
crop: 'Przytnij',
rotate: 'Obróć',
sort: 'Sortuj',
open: 'Otwórz',
download: 'Pobierz',
remove: 'Usuń',
drop: 'Upuść pliki tutaj do przesłania',
paste: '<div class="fileuploader-pending-loader"></div> Wklejając plik, kliknij tutaj, aby anulować',
removeConfirmation: 'Czy jesteś pewien, że chcesz usunąć ten plik?',
errors: {
filesLimit: function(options) {
return 'Tylko ${limit} ' + (options.limit == 1 ? 'plik' : 'pliki') + ' można wybrać.'
},
filesType: 'Tylko pliki ${extensions} mogą zostać pobrane.',
fileSize: 'Plik ${name} jest za duży! Proszę wybrać plik do ${fileMaxSize} MB.',
filesSizeAll: 'Wybrane pliki są za duże! Proszę wybrać pliki do ${maxSize} MB.',
fileName: ', Plik o tej samej nazwie ${name} już został wybrany.',
remoteFile: 'Zdalne pliki nie są dozwolone.',
folderUpload: 'Foldery nie są dozwolone.',
}
},
pt: {
button: function(options) {
return 'Escolher ' + (options.limit == 1 ? 'arquivo' : 'arquivos')
},
feedback: function(options) {
return 'Escolha ' + (options.limit == 1 ? 'arquivo' : 'arquivos') + ' a carregar'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'arquivos foram escolhidos' : 'arquivo foi escolhido')
},
confirm: 'Confirmar',
cancel: 'Cancelar',
name: 'Nome',
type: 'Tipo',
size: 'Tamanho',
dimensions: 'Dimensões',
duration: 'Duração',
crop: 'Recorte',
rotate: 'Girar',
sort: 'Ordenar',
open: 'Abrir',
download: 'Baixar',
remove: 'Excluir',
drop: 'Solte os arquivos aqui para fazer o upload',
paste: '<div class="fileuploader-pending-loader"></div> Colando um arquivo, clique aqui para cancelar',
removeConfirmation: 'Tem certeza de que deseja excluir este arquivo?',
errors: {
filesLimit: function(options) {
return 'Apenas ${limit} ' + (options.limit == 1 ? 'arquivo a ser carregado' : 'arquivos a serem carregados') + '.'
},
filesType: 'Somente arquivos ${extensions} podem ser carregados.',
fileSize: '${name} é muito grande! Selecione um arquivo de até ${fileMaxSize} MB.',
filesSizeAll: 'Os arquivos selecionados são muito grandes! Selecione arquivos de até ${maxSize} MB.',
fileName: 'Um arquivo com o mesmo nome ${name} já está selecionado.',
remoteFile: 'Arquivos remotos não são permitidos.',
folderUpload: 'Pastas não são permitidas.',
}
},
ro: {
button: function(options) {
return 'Atașează ' + (options.limit == 1 ? 'fișier' : 'fișiere')
},
feedback: function(options) {
return 'Selectează ' + (options.limit == 1 ? 'fișier' : 'fișiere') + ' pentru încărcare'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? ' fișiere' : ' fișier') + ' selectate'
},
confirm: 'Confirmă',
cancel: 'Anulează',
name: 'Nume',
type: 'Tip',
size: 'Mărimea',
dimensions: 'Dimensiunea',
duration: 'Durata',
crop: 'Crop',
rotate: 'Rotire',
sort: 'Sortare',
open: 'Deschide',
download: 'Download',
remove: 'Șterge',
drop: 'Aruncați fișierele aici pentru a le încărca',
paste: '<div class="fileuploader-pending-loader"></div> Se atașează fișier, faceți click aici pentru anulare',
removeConfirmation: 'Sigur doriți să ștergeți acest fișier?',
errors: {
filesLimit: function(options) {
return 'Doar ${limit} ' + (options.limit == 1 ? 'fișier poate fi selectat' : 'fișiere pot fi selectat') + '.'
},
filesType: 'Doar fișierele ${extensions} pot fi încărcate.',
fileSize: '${name} este prea mare! Vă rugăm să selectați un fișier până la ${fileMaxSize} MB.',
filesSizeAll: 'Fișierele selectate sunt prea mari! Vă rugăm să selectați fișiere până la ${maxSize} MB.',
fileName: 'Fișierul cu același numele ${nume} a fost deja selectat.',
remoteFile: 'Fișierele remote nu sunt permise.',
folderUpload: 'Folderele nu sunt permise.',
}
},
ru: {
button: function(options) {
return 'Выбрать ' + (options.limit == 1 ? 'файл' : 'файлы')
},
feedback: function(options) {
return 'Выберите ' + (options.limit == 1 ? 'файл' : 'файлы') + ' для загрузки'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'файлов выбрано' : 'файл выбран')
},
confirm: 'Сохранить',
cancel: 'Отмена',
name: 'Имя',
type: 'Формат',
size: 'Размер',
dimensions: 'Размеры',
duration: 'Длительность',
crop: 'Обрезать',
rotate: 'Повернуть',
sort: 'Сортировть',
open: 'Открыть',
download: 'Скачать',
remove: 'Удалить',
drop: 'Перетащите файлы сюда для загрузки',
paste: '<div class="fileuploader-pending-loader"></div> Вставка файла, нажмите здесь, чтобы отменить',
removeConfirmation: 'Вы уверены, что хотите удалить этот файл?',
errors: {
filesLimit: function(options) {
return 'Только ${limit} ' + (options.limit == 1 ? 'файл может быть загружен' : 'файлов могут быть загружены') + '.'
},
filesType: 'Только ${extensions} файлы могут быть загружены.',
fileSize: '${name} слишком большой! Пожалуйста, выберите файл до ${fileMaxSize} МБ.',
filesSizeAll: 'Выбранные файлы слишком большие! Пожалуйста, выберите файлы до ${maxSize} МБ.',
fileName: 'Файл с таким именем ${name} уже выбран.',
remoteFile: 'Удаленные файлы не допускаются.',
folderUpload: 'Папки не допускаются.',
}
},
tr: {
button: function(options) {
return (options.limit == 1 ? 'Dosya' : 'Dosyaları') + ' seç'
},
feedback: function(options) {
return 'Yüklemek istediğiniz ' + (options.limit == 1 ? 'dosyayı' : 'dosyaları') + ' seçin.'
},
feedback2: function(options) {
return options.length + ' ' + (options.length > 1 ? 'dosyalar' : 'dosya') + ' seçildi.'
},
confirm: 'Onayla',
cancel: 'İptal',
name: 'İsim',
type: 'Tip',
size: 'Boyut',
dimensions: 'Boyutlar',
duration: 'Süre',
crop: 'Kırp',
rotate: 'Döndür',
sort: 'Sırala',
open: 'Aç',
download: 'İndir',
remove: 'Sil',
drop: 'Yüklemek için dosyaları buraya bırakın',
paste: '<div class="fileuploader-pending-loader"></div> Bir dosyayı yapıştırmak veya iptal etmek için buraya tıklayın',
removeConfirmation: 'Bu dosyayı silmek istediğinizden emin misiniz?',
errors: {
filesLimit: function(options) {
return 'Sadece ${limit} ' + (options.limit == 1 ? 'dosya' : 'dosyalar') + ' yüklenmesine izin verilir.'
},
filesType: 'Sadece ${extensions} dosyaların yüklenmesine izin verilir.',
fileSize: '${name} çok büyük! Lütfen ${fileMaxSize} MB\'a kadar bir dosya seçin.',
filesSizeAll: 'Seçilen dosyalar çok büyük! Lütfen ${maxSize} MB\'a kadar dosyaları seçin',
fileName: 'Aynı ada sahip bir dosya ${name} zaten seçilmiştir.',
remoteFile: 'Uzak dosyalara izin verilmez.',
folderUpload: 'Klasörlere izin verilmez.',
}
}
};
$.fn.fileuploader.defaults = {
limit: null,
maxSize: null,
fileMaxSize: null,
extensions: null,
disallowedExtensions: null,
changeInput: true,
inputNameBrackets: true,
theme: 'default',
thumbnails: {
box: '<div class="fileuploader-items">' +
'<ul class="fileuploader-items-list"></ul>' +
'</div>',
boxAppendTo: null,
item: '<li class="fileuploader-item">' +
'<div class="columns">' +
'<div class="column-thumbnail">${image}<span class="fileuploader-action-popup"></span></div>' +
'<div class="column-title">' +
'<div title="${name}">${name}</div>' +
'<span>${size2}</span>' +
'</div>' +
'<div class="column-actions">' +
'<button type="button" class="fileuploader-action fileuploader-action-remove" title="${captions.remove}"><i class="fileuploader-icon-remove"></i></a>' +
'</div>' +
'</div>' +
'<div class="progress-bar2">${progressBar}<span></span></div>' +
'</li>',
item2: '<li class="fileuploader-item">' +
'<div class="columns">' +
'<div class="column-thumbnail">${image}<span class="fileuploader-action-popup"></span></div>' +
'<div class="column-title">' +
'<a href="${file}" target="_blank">' +
'<div title="${name}">${name}</div>' +
'<span>${size2}</span>' +
'</a>' +
'</div>' +
'<div class="column-actions">' +
'<a href="${data.url}" class="fileuploader-action fileuploader-action-download" title="${captions.download}" download><i class="fileuploader-icon-download"></i></a>' +
'<button type="button" class="fileuploader-action fileuploader-action-remove" title="${captions.remove}"><i class="fileuploader-icon-remove"></i></a>' +
'</div>' +
'</div>' +
'</li>',
popup: {
container: 'body',
loop: true,
arrows: true,
zoomer: true,
template: function(data) { return '<div class="fileuploader-popup-preview">' +
'<button type="button" class="fileuploader-popup-move" data-action="prev"><i class="fileuploader-icon-arrow-left"></i></button>' +
'<div class="fileuploader-popup-node ${format}">' +
'${reader.node}' +
'</div>' +
'<div class="fileuploader-popup-content">' +
'<div class="fileuploader-popup-footer">' +
'<ul class="fileuploader-popup-tools">' +
(data.format == 'image' && data.reader.node && data.editor ? (data.editor.cropper ? '<li>' +
'<button type="button" data-action="crop">' +
'<i class="fileuploader-icon-crop"></i> ${captions.crop}' +
'</button>' +
'</li>' : '') +
(data.editor.rotate ? '<li>' +
'<button type="button" data-action="rotate-cw">' +
'<i class="fileuploader-icon-rotate"></i> ${captions.rotate}' +
'</button>' +
'</li>' : '') : ''
) +
(data.format == 'image' ?
'<li class="fileuploader-popup-zoomer">' +
'<button type="button" data-action="zoom-out">&minus;</button>' +
'<input type="range" min="0" max="100">' +
'<button type="button" data-action="zoom-in">&plus;</button>' +
'<span></span> ' +
'</li>' : ''
) +
(data.data.url ? '<li>' +
'<a href="'+ data.data.url +'" data-action target="_blank">' +
'<i class="fileuploader-icon-external"></i> ${captions.open}' +
'</a>' +
'</li>' : ''
) +
'<li>' +
'<button type="button" data-action="remove">' +
'<i class="fileuploader-icon-trash"></i> ${captions.remove}' +
'</button>' +
'</li>' +
'</ul>' +
'</div>' +
'<div class="fileuploader-popup-header">' +
'<ul class="fileuploader-popup-meta">' +
'<li>' +
'<span>${captions.name}:</span>' +
'<h5>${name}</h5>' +
'</li>' +
'<li>' +
'<span>${captions.type}:</span>' +
'<h5>${extension.toUpperCase()}</h5>' +
'</li>' +
'<li>' +
'<span>${captions.size}:</span>' +
'<h5>${size2}</h5>' +
'</li>' +
(data.reader && data.reader.width ? '<li>' +
'<span>${captions.dimensions}:</span>' +
'<h5>${reader.width}x${reader.height}px</h5>' +
'</li>' : ''
) +
(data.reader && data.reader.duration ? '<li>' +
'<span>${captions.duration}:</span>' +
'<h5>${reader.duration2}</h5>' +
'</li>' : ''
) +
'</ul>' +
'<div class="fileuploader-popup-info"></div>' +
'<ul class="fileuploader-popup-buttons">' +
'<li><button type="button" class="fileuploader-popup-button" data-action="cancel">${captions.cancel}</a></li>' +
(data.editor ? '<li><button type="button" class="fileuploader-popup-button button-success" data-action="save">${captions.confirm}</button></li>' : ''
) +
'</ul>' +
'</div>' +
'</div>' +
'<button type="button" class="fileuploader-popup-move" data-action="next"><i class="fileuploader-icon-arrow-right"></i></button>' +
'</div>'; },
onShow: function(item) {
item.popup.html.on('click', '[data-action="remove"]', function(e) {
item.popup.close();
item.remove();
}).on('click', '[data-action="cancel"]', function(e) {
item.popup.close();
}).on('click', '[data-action="save"]', function(e) {
if (item.editor)
item.editor.save();
if (item.popup.close)
item.popup.close();
});
},
onHide: null
},
itemPrepend: false,
removeConfirmation: true,
startImageRenderer: true,
synchronImages: true,
useObjectUrl: false,
canvasImage: true,
videoThumbnail: true,
pdf: true,
exif: true,
touchDelay: 0,
_selectors: {
list: '.fileuploader-items-list',
item: '.fileuploader-item',
start: '.fileuploader-action-start',
retry: '.fileuploader-action-retry',
remove: '.fileuploader-action-remove',
sorter: '.fileuploader-action-sort',
rotate: '.fileuploader-action-rotate',
popup: '.fileuploader-popup-preview',
popup_open: '.fileuploader-action-popup'
},
beforeShow: null,
onItemShow: null,
onItemRemove: function(html) {
html.children().animate({'opacity': 0}, 200, function() {
setTimeout(function() {
html.slideUp(200, function() {
html.remove();
});
}, 100);
});
},
onImageLoaded: null
},
editor: false,
sorter: false,
reader: {
thumbnailTimeout: 5000,
timeout: 12000,
maxSize: 20
},
files: null,
upload: null,
dragDrop: true,
addMore: false,
skipFileNameCheck: false,
clipboardPaste: true,
listInput: true,
enableApi: false,
listeners: null,
onSupportError: null,
beforeRender: null,
afterRender: null,
beforeSelect: null,
onFilesCheck: null,
onFileRead: null,
onSelect: null,
afterSelect: null,
onListInput: null,
onRemove: null,
onEmpty: null,
dialogs: {
alert: function(text) {
return alert(text);
},
confirm: function(text, callback) {
confirm(text) ? callback() : null;
}
},
captions: $.fn.fileuploader.languages.en
}
})(jQuery);