提交 528bfbfc 编写于 作者: C Catouse

+ add uploader.

上级 88f735a6
/* ========================================================================
* ZUI: uploader.js
* http://zui.sexy
* ========================================================================
* Copyright (c) 2014-2016 cnezsoft.com; Licensed MIT
* ======================================================================== */
(function($, window, Plupload, Moxie, undefined) {
'use strict';
var NAME = 'zui.uploader'; // modal name
var pluploadEvents = [''];
var FILE_TEMPLATE = '<div class="file"><div class="file-progress-bar"></div><div class="file-wrapper"><div class="file-icon"><i class="icon icon-file-o"></i></div><div class="content"><div class="file-name"></div><div class="file-size small text-muted">0KB</div></div><div class="actions"><div class="file-status" data-toggle="tooltip"><i class="icon"></i> <span class="text"></span></div><button type="button" data-toggle="tooltip" class="btn btn-link btn-reset-file" title="Repeat"><i class="icon icon-repeat"></i></button><button type="button" data-toggle="tooltip" class="btn btn-link btn-rename-file" title="Rename"><i class="icon icon-pencil"></i></button><button type="button" data-toggle="tooltip" title="Remove" class="btn btn-link btn-delete-file"><i class="icon icon-trash text-danger"></i></button></div></div></div>';
var STATUS = {};
STATUS[Plupload.QUEUED] = 'queue';
STATUS[Plupload.UPLOADING] = 'uploading';
STATUS[Plupload.FAILED] = 'failed';
STATUS[Plupload.DONE] = 'done';
// The uploader modal class
var Uploader = function(element, options) {
var that = this;
that.name = NAME;
that.$ = $(element).addClass('uploader');
options = that.getOptions(options);
// Init lang
var lang = $.isPlainObject(options.lang) ? ($.extend({}, Uploader.LANG[lang.lang || $.zui.clientLang()], options.lang)) : Uploader.LANG[options.lang];
that.lang = lang;
// Init file list element
var $this = that.$;
var fileList = options.fileList;
var $list;
if(!fileList || fileList == 'large' || fileList == 'grid') {
$list = $this.find('.file-list');
} else if(fileList.indexOf('>') === 0) $list = $this.find(fileList.substr(1));
else $list = $(fileList);
if(!$list || !$list.length) $list = $('<div class="file-list"></div>');
if(!$list.parent().length) $this.append($list);
if(fileList == 'large') $list.addClass('file-list-lg');
else if(fileList == 'grid') $list.addClass('file-list-grid');
that.$list = $list;
// Init file template
var template = options.fileTemplate;
if(!template) {
var $template = $list.find('.template');
if($template.length) {
template = $template.first().clone().removeClass('template');
$template.remove();
}
if(!template) template = FILE_TEMPLATE;
}
if(typeof template === 'string') {
template = $(template);
if(template.parent()) template = template.clone().removeClass('template');
}
that.template = template;
// Init browse button element
var browseBtn = options.browse_button;
var $btn;
if(browseBtn.indexOf('>') === 0) $btn = $this.find(browseBtn.substr(1));
else $btn = $(browseBtn);
that.$button = $btn.first();
// Init drop element
var dropElement = options.drop_element;
var $dropElement = (dropElement == 'fileList' ? that.$list : (dropElement == 'self' ? that.$ : $(dropElement))).first().addClass('file-drag-area');
var dropPlaceholder = options.dropPlaceholder;
if(dropPlaceholder == true) dropPlaceholder = lang.dropPlaceholder;
if(dropPlaceholder) $dropElement.attr('data-drop-placeholder', dropPlaceholder);
that.$dropElement = $dropElement;
// Init message
that.$message = $this.find('.uploader-message').on('click', '.close', function() {
that.hideMessage();
});
that.$status = $this.find('.uploader-status');
// Init actions
$this.toggleClass('uploader-rename', !!options.rename);
// Init plupload
that.initPlupload();
// Bind events
$this.on('click.' + NAME, '.btn-uploader-start', function(e) {
that.start();
}).on('click.' + NAME, '.btn-uploader-browse', function(e) {
if($(this).is(that.$button)) return;
that.$button.trigger('click');
}).on('click.' + NAME, '.btn-uploader-stop', function(e) {
that.stop();
});
$('body').on('dragleave.' + NAME + ' drop.' + NAME, function(e) {
$this.removeClass('file-dragable');
}).on('dragover.' + NAME + ' dragenter.' + NAME, function(e) {
$this.addClass('file-dragable');
});
$dropElement.on('dragleave.' + NAME + ' drop.' + NAME, function(e) {
$this.removeClass('file-drag-enter');
}).on('dragover.' + NAME + ' dragenter.' + NAME, function(e) {
$this.addClass('file-drag-enter');
});
$list.on('click.' + NAME, '.btn-delete-file', function() {
var $file = $(this).closest('.file');
var file = $file.data('file');
if(file.status === Plupload.QUEUED || file.status === Plupload.FAILED) {
var removeFile = function() {
that.plupload.removeFile(file);
};
var deleteConfirmOption = options.deleteConfirm;
if(deleteConfirmOption) {
var confirmMessage = $.isFunction(deleteConfirmOption) ? deleteConfirmOption(file) : (deleteConfirmOption === true ? lang.deleteConfirm : deleteConfirmOption);
confirmMessage = confirmMessage.format(file);
if(window.bootbox) {
window.bootbox.confirm(confirmMessage, function(result) {
if(result) removeFile();
});
} else {
if(window.confirm(confirmMessage)) removeFile();
}
} else {
removeFile();
}
}
}).on('click.' + NAME, '.btn-reset-file', function() {
var $file = $(this).closest('.file');
var file = that.plupload.getFile($file.data('id'));
if(file.status === Plupload.FAILED) {
file.status = Plupload.QUEUED;
that.showFile(file);
}
});
if(options.rename) {
if(options.renameByClick) $list.addClass('file-rename-by-click');
$list.on('click.' + NAME, '.btn-rename-file' + (options.renameByClick ? ',.file-name' : ''), function() {
var $file = $(this).closest('.file');
if($file.hasClass('file-renaming')) return;
var file = that.plupload.getFile($file.data('id'));
if(file.status === Plupload.QUEUED) {
var $filename = $file.find('.file-name').first();
$file.addClass('file-renaming');
$filename.attr('contenteditable', 'true').one('blur', function() {
var filename = $.trim($filename.text());
if(filename !== undefined && filename !== null && filename !== '') {
var ext = file.ext;
if(ext.length && !options.renameExtension && filename.lastIndexOf('.' + ext) !== (filename.length - ext.length - 1)) {
filename += '.' + ext;
}
file.name = filename;
}
that.showFile(file);
$file.removeClass('file-renaming')
$filename.off('keydown.' + NAME).attr('contenteditable', null);
}).on('keydown.' + NAME, function(e) {
if(e.keyCode === 13) {
$filename.blur();
e.preventDefault();
}
}).focus();
that.showFile(file);
}
});
}
};
// default options
Uploader.DEFAULTS = {
// filesList: '', // 'default', 'large', 'grid', '>.file-list', '#myFileList', '<div class="file-list"></div>'
// fileTemplate: '',
// fileFormater: null,
// fileIconCreator: null,
rename: true,
// autoUpload: false,
// renameExtension: false,
renameByClick: true,
dropPlaceholder: true,
// messageCreator: null,
previewImageIcon: true,
deleteConfirm: false,
removeUploaded: false,
statusCreator: null, // Function
// previewImageSize: {width: 200, height: 200},
// plupload options
drop_element: 'self', // 'self', 'fileList', String or jQuery object,
browse_button: '>.btn-uploader-browse', // String or jQuery object
// url: '', // String
filters: {prevent_duplicates: true}, // {mime_types, max_file_size, prevent_duplicates}
// headers: null, // Object
// multipart: true, // true, false
// multipart_params: null, // Object
// max_retries: 0,
chunk_size: '1mb', // Number, String
// resize: {}, // {width, height, crop, quality, preserve_headers},
// multi_selection: true, // true, false,
// required_features: null, // String
// unique_names: false, // true, false
// runtimes: 'html5,flash,silverlight,html4', // String
// file_data_name: 'file', // String
flash_swf_url: 'lib/uploader/Moxie.swf', // String
silverlight_xap_url: 'lib/uploader/Moxie.xap' // String
};
Uploader.prototype.showMessage = function(message, type, time) {
var that = this;
var $msg = that.$message;
if(!message) that.hideMessage();
else clearTimeout(that.lastDismissMessage);
type = type || 'danger';
if(time === undefined) time = type === 'danger' ? 8 : 5;
if(time < 20) time *= 1000;
var $content = $msg.find('.content');
if($content.length) $content.text(message);
else $msg.text(message);
$msg.attr('data-type', type).slideDown('fast');
if(time) {
that.lastDismissMessage = setTimeout(function() {
that.hideMessage();
}, time);
}
};
Uploader.prototype.hideMessage = function() {
clearTimeout(this.lastDismissMessage);
this.$message.slideUp('fast');
};
Uploader.prototype.start = function() {
return this.plupload.start();
};
Uploader.prototype.stop = function() {
return this.plupload.stop();
};
Uploader.prototype.disableBrowse = function(disable) {
$this.find('.btn-uploader-browse').attr('disable', disable ? 'disable' : null).toggle('disable', !!disable);
return this.plupload.disableBrowse();
};
Uploader.prototype.getFile = function(id) {
return this.plupload.getFile(id);
};
Uploader.prototype.removeFile = function(file) {
return this.plupload.removeFile(file);
};
Uploader.prototype.destroy = function() {
var that = this;
var eventNamespace = '.' + NAME;
that.$.off(eventNamespace);
that.$list.off(eventNamespace);
that.$dropElement.off(eventNamespace);
$('body').off(eventNamespace);
that.plupload.destroy();
};
// see https://github.com/moxiecode/moxie/wiki/API
Uploader.prototype.previewImageSrc = function(file, callback) {
if(!file || !/image\//.test(file.type)) return;
var size = $.extend({width: 200, height: 200}, this.options.previewImageSize);
if(file.type == 'image/gif') {
//mOxie.Image only support jpg and png
var fr = new Moxie.file.FileReader();
fr.onload = function() {
callback && callback(fr.result);
fr.destroy();
fr = null;
}
fr.readAsDataURL(file.getSource());
} else {
var preloader = new Moxie.image.Image();
preloader.onload = function() {
// compressImage
preloader.downsize(size.width, size.height);
var imgsrc = preloader.type == 'image/jpeg' ? preloader.getAsDataURL('image/jpeg', 80) : preloader.getAsDataURL(); // return base64 data
callback && callback(imgsrc);
preloader.destroy();
preloader = null;
};
preloader.load(file.getSource());
}
};
Uploader.prototype.createFileIcon = function(file) {
var fileType = file.type;
var ext = file.ext;
var icon = 'file-o';
var types = fileType.split('/');
var type = types.length ? types[0] : '', subType = types.length > 1 ? types[1] : '';
if(type == 'image') icon = 'file-image';
else if(ext == 'doc' || ext == 'docx' || ext == 'pages') icon = 'file-word';
else if(ext == 'ppt' || ext == 'pptx' || ext == 'key') icon = 'file-powerpoint';
else if(ext == 'xls' || ext == 'xlsx' || ext == 'numbers') icon = 'file-excel';
else if(ext == 'html' || ext == 'htm') icon = 'globe';
else if(ext == 'js' || ext == 'php' || ext == 'cs' || ext == 'jsx' || ext == 'css' || ext == 'less' || ext == 'json' || ext == 'java' || ext == 'lua' || ext == 'py' || ext == 'c' || ext == 'cpp' || ext == 'swift' || ext == 'h' || ext == 'sh' || ext == 'rb' || ext == 'yml' || ext == 'ini' || ext == 'sql') icon = 'file-code';
else if(ext == 'apk') icon = 'android';
else if(ext == 'exe') icon = 'windows';
else if(subType == 'zip' || subType == 'x-rar' || subType == 'x-7z-compressed') icon = 'file-archive';
else if(subType == 'pdf') icon = 'file-pdf';
else if(type == 'video') icon = 'file-movie';
else if(type == 'audio') icon = 'file-audio';
else if(type == 'text') icon = 'file-text-o';
return '<i class="icon icon-' + icon + ' file-icon-' + ext + '" data-type="' + fileType + '"' + (ext ? ' data-ext="' + ext + '"' : '') + '></i>';
};
Uploader.prototype.getFileItem = function(file) {
var that = this;
if(typeof file == 'string') {
file = that.plupload.getFile(file);
}
if(!file) return null;
var filename = file.name;
if(filename && file.ext === undefined) {
var ext = filename.lastIndexOf('.');
if(ext > -1) ext = filename.substr(ext + 1);
else ext = '';
file.ext = ext;
if(/image\//.test(file.type)) {
file.isImage = file.ext;
}
}
var $file = $('#file-' + file.id);
if(!$file.length) {
if($.isFunction(that.template)) {
$file = $(that.template(file, that));
} else {
$file = $(that.template).clone();
$file.find('.btn-rename-file').attr('title', that.lang.rename);
$file.find('.btn-delete-file').attr('title', that.lang.remove);
$file.find('.btn-reset-file').attr('title', that.lang.repeat);
}
$file.data('id', file.id)
.attr('id', 'file-' + file.id)
.appendTo(that.$list);
if($.fn.tooltip) $file.find('[data-toggle="tooltip"]').tooltip({container: 'body'});
}
return $file;
};
Uploader.prototype.showFile = function(file) {
var that = this;
if($.isArray(file)) {
$.each(file, function(idx, f) {
that.showFile(f);
});
return;
}
if(typeof file == 'string') {
file = that.plupload.getFile(file);
}
if(!file) return;
var $file = that.getFileItem(file);
if(!$file || !$file.length) {
return;
}
var options = that.options;
var status = STATUS[file.status];
if(options.fileFormater) {
options.fileFormater($file, file);
} else {
$file.find('.file-name').text(file.name);
$file.find('.file-size').text((status == 'uploading' ? (Plupload.formatSize(Math.floor(file.size*file.percent/100)).toUpperCase() + '/') : '') + Plupload.formatSize(file.size).toUpperCase());
$file.find('.file-icon').html(options.fileIconCreator ? options.fileIconCreator(file.type, file, that) : that.createFileIcon(file)).css('color', 'hsl(' + $.zui.strCode(file.type) + ', 70%, 40%)');
$file.find('.file-progress-bar').css('width', file.percent + '%');
var $status = $file.find('.file-status').attr('title', that.lang[status]);
$status.find('.text').text(status == 'uploading' ? (file.percent + '%') : ((status == 'failed') ? that.lang[status] : ''));
if($.fn.tooltip) $file.find('[data-toggle="tooltip"]').tooltip('fixTitle');
}
if(options.previewImageIcon && file.isImage) {
var setPreviewImage = function() {
$file.find('.file-icon').html('<div class="file-icon-image" style="background-image: url(' + file.previewImage + ')"></div>');
};
if(file.previewImage) {
setPreviewImage();
} else {
that.previewImageSrc(file, function(src) {
file.previewImage = src;
setPreviewImage();
});
}
}
$file.attr('data-status', status)
.data('file', file);
};
Uploader.prototype.showStatus = function() {
var that = this;
var plupload = that.plupload;
var $status = that.$status;
var state = plupload.state, total = plupload.total, statusText = '', totalCount = plupload.files.length;
if(that.options.statusCreator) {
statusText = that.options.statusCreator(total, state, that);
} else {
var stateObj = {
uploading: Math.max(0, Math.min(totalCount, total.uploaded + 1)),
total: totalCount,
size: Plupload.formatSize(total.size).toUpperCase(),
queue: total.queued,
failed: total.failed,
uploaded: total.uploaded,
uploadedSize: Plupload.formatSize(total.loaded).toUpperCase(),
percent: total.percent,
speed: Plupload.formatSize(total.bytesPerSec).toUpperCase() + '/S'
};
if(state == Plupload.STARTED) {
statusText = that.lang.startedStatusText.format(stateObj);
} else {
if(totalCount < 1) {
status = that.lang.initStatusText;
} else {
statusText = that.lang.stoppedStatusText.format(stateObj);
}
}
}
$status.html(statusText);
if(total.uploaded < 1) $status.find('.uploader-status-uploaded').remove();
if(total.failed < 1) $status.find('.uploader-status-failed').remove();
if(total.queued < 1) $status.find('.uploader-status-queue').remove();
if($.fn.tooltip) $status.find('[data-toggle="tooltip"]').tooltip();
};
Uploader.prototype.delayShowStatus = function(delay) {
var that = this;
if(that.delayStatusTask) return;
that.delayStatusTask = true;
if(delay === undefined) delay = 500;
that.delayStatusTask = setTimeout(function() {
that.showStatus();
that.delayStatusTask = false;
}, delay);
};
Uploader.prototype.initPlupload = function() {
var that = this;
var options = that.options;
var plOptions = $.extend({}, options, {
browse_button: that.$button[0],
container: that.$[0],
drop_element: that.$dropElement[0]
});
Plupload.addI18n(that.lang);
var plupload = new Plupload.Uploader(plOptions);
plupload.init();
plupload.bind('FilesAdded', function(uploader, files) {
that.showFile(files);
if(options.autoUpload) that.start();
that.showStatus();
that.callEvent('onFilesAdded', [files]);
});
plupload.bind('UploadProgress', function(uploader, file) {
that.showFile(file);
that.delayShowStatus();
that.callEvent('onUploadProgress', file);
});
plupload.bind('FileUploaded', function(uploader, file) {
that.showFile(file);
that.showStatus();
that.callEvent('onFileUploaded', file);
var optionRemoveUploaded = options.removeUploaded;
if(optionRemoveUploaded) {
setTimeout(function() {
$('#file-' + file.id).fadeOut(function() {
$(this).remove();
});
}, (typeof optionRemoveUploaded) === 'number' ? optionRemoveUploaded : 2000);
}
});
plupload.bind('UploadComplete', function(uploader, files) {
that.showFile(files);
that.showStatus();
that.callEvent('onUploadComplete', [files]);
});
plupload.bind('FilesRemoved', function(uploader, files) {
$.each(files, function(idx, file) {
var $file = $('#file-' + file.id);
if($.fn.tooltip) {
$file.find('[data-toggle="tooltip"]').tooltip('destroy');
$('.tooltip').remove();
}
$file.fadeOut(function() {
$(this).remove();
});
});
that.showStatus();
that.callEvent('onFilesRemoved', files);
});
plupload.bind('ChunkUploaded', function(uploader, file, responseObject) {
that.callEvent('onChunkUploaded', [file, responseObject]);
});
plupload.bind('UploadFile', function(uploader, file) {
that.showStatus();
that.callEvent('onUploadFile', file);
});
plupload.bind('BeforeUpload', function(uploader, file) {
that.callEvent('onBeforeUpload', file);
});
plupload.bind('Refresh', function(uploader) {
that.showStatus();
that.callEvent('onRefresh');
});
plupload.bind('StateChanged', function(uploader) {
that.$.toggleClass('uploader-started', Plupload.STARTED === uploader.state);
that.hideMessage();
that.showStatus();
that.callEvent('onStateChanged');
});
plupload.bind('QueueChanged', function(uploader) {
that.showStatus();
that.callEvent('onQueueChanged');
});
plupload.bind('Error', function(uploader, error) {
var type = 'danger';
if(error.code === Plupload.FILE_SIZE_ERROR
|| error.code === Plupload.FILE_SIZE_ERROR
|| error.code === Plupload.FILE_EXTENSION_ERROR
|| error.code === Plupload.FILE_DUPLICATE_ERROR
|| error.code === Plupload.MAGE_FORMAT_ERROR) type = 'warning';
that.showMessage(error.message, type);
that.callEvent('onError', error);
});
that.plOptions = plOptions;
that.plupload = plupload;
};
// Get and init options
Uploader.prototype.getOptions = function(options) {
this.options = $.extend({
lang: $.zui.clientLang()
}, Uploader.DEFAULTS, this.$.data(), options);
return this.options;
};
// Call event helper
Uploader.prototype.callEvent = function(name, params) {
var result = this.$.callEvent(name + '.' + this.name, params, this);
return !(result.result !== undefined && (!result.result));
};
// Extense jquery element
$.fn.uploader = function(option, params) {
return this.each(function() {
var $this = $(this);
var data = $this.data(NAME);
var options = typeof option == 'object' && option;
if(!data) $this.data(NAME, (data = new Uploader(this, options)));
if(typeof option == 'string') data[option](params);
});
};
Uploader.NAME = NAME;
Uploader.LANG = {
zh_cn: {"startedStatusText": "正在上传第 <strong>{uploading}</strong> 个文件,共 <strong title=\"总大小:{size}\" data-toggle=\"tooltip\" class=\"text-primary\">{total}</strong> 个文件,<span class=\"uploader-status-uploaded\">已上传 <strong title=\"总大小:{uploadedSize}\" data-toggle=\"tooltip\" class=\"text-primary\">{uploaded}</strong> 个文件,</span><span class=\"uploader-status-failed\"><strong>{failed}</strong> 个上传失败,</span>进度 <strong>{percent}%</strong>,平均速度 <strong>{speed}</strong>。", "initStatusText": "添加文件或拖放文件来上传。", "stoppedStatusText": "共 <strong title=\"总大小:{size}\" data-toggle=\"tooltip\" class=\"text-primary\">{total}</strong> 个文件<span class=\"uploader-status-queue\">,<strong>{queue}</strong> 个文件等待上传</span><span class=\"uploader-status-uploaded\">,已上传 <strong title=\"总大小:{uploadedSize}\" data-toggle=\"tooltip\" class=\"text-primary\">{uploaded}</strong> 个文件</span><span class=\"uploader-status-failed\">,<strong>{failed}</strong> 个上传失败</span><span class=\"uploader-status-uploaded\">,平均速度 <strong>{speed}</strong></span>。", "deleteConfirm": "确定移除文件【{name}】?", "rename": "重命名", "repeat": "重新上传", "remove": "移除", "dropPlaceholder": "将文件拖放至在此处。", "queue": "待上传", "uploading": "正在上传", "failed": "失败", "done": "已上传","Stop Upload":"停止上传","Upload URL might be wrong or doesn't exist.":"上传的URL可能是错误的或不存在。","tb":"tb","Size":"大小","Close":"关闭","You must specify either browse_button or drop_element.":"您必须指定 browse_button 或者 drop_element。","Init error.":"初始化错误。","Add files to the upload queue and click the start button.":"将文件添加到上传队列,然后点击”开始上传“按钮。","List":"列表","Filename":"文件名","%s specified, but cannot be found.":"%s 已指定,但是没有找到。","Image format either wrong or not supported.":"图片格式错误或者不支持。","Status":"状态","HTTP Error.":"HTTP 错误。","Start Upload":"开始上传","Error: File too large:":"错误: 文件太大:","kb":"kb","Duplicate file error.":"无法添加重复文件。","File size error.":"文件大小错误。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"错误:无效的文件扩展名:","Select files":"选择文件","%s already present in the queue.":"%s 已经在当前队列里。","Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.":"超限。<b>%s</b> 支持最大 %wx%hpx 的图片。","File: %s":"文件: %s","b":"b","Uploaded %d/%d files":"已上传 %d/%d 个文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只接受同时上传 %d 个文件,多余的文件将会被删除。","%d files queued":"%d 个文件加入到队列","File: %s, size: %d, max file size: %d":"文件: %s, 大小: %d, 最大文件大小: %d","Thumbnails":"缩略图","Drag files here.":"把文件拖到这里。","Runtime ran out of available memory.":"运行时已消耗所有可用内存。","File count error.":"文件数量错误。","File extension error.":"文件扩展名错误。","mb":"mb","Add Files":"增加文件"},
zh_tw: {"startedStatusText": "正在上傳第<strong>{uploading}</strong> 個文件,共<strong title=\"總大小:{size}\" data-toggle=\"tooltip\" class=\"text -primary\">{total}</strong> 個文件,<span class=\"uploader-status-uploaded\">已上傳<strong title=\"總大小:{uploadedSize}\" data-toggle=\"tooltip\" class=\"text-primary\">{uploaded}</strong> 個文件,</span><span class=\"uploader-status-failed\"><strong>{failed}</ strong> 個上傳失敗,</span>進度<strong>{percent}%</strong>,平均速度<strong>{speed}</strong>。", "initStatusText": "添加文件或拖放文件來上傳。", "stoppedStatusText": "共<strong title=\"總大小:{size}\" data-toggle=\"tooltip\" class=\"text-primary\">{total}</strong> 個文件<span class=\"uploader-status-queue\">,<strong>{queue}</strong> 個文件等待上傳</span><span class=\"uploader-status-uploaded\">,已上傳<strong title=\"總大小:{uploadedSize}\" data-toggle=\"tooltip\" class=\"text-primary\">{uploaded}</strong> 個文件</span><span class=\" uploader-status-failed\">,<strong>{failed}</strong> 個上傳失敗</span><span class=\"uploader-status-uploaded\">,平均速度<strong>{speed}< /strong></span>。", "deleteConfirm": "確定移除文件【{name}】?", "rename": "重命名", "repeat": "重新上傳", "remove": "移除", "dropPlaceholder": "將文件拖放至在此處。", "queue": "待上傳", "uploading": "正在上傳", "failed": "失敗", "done": "已上傳","Stop Upload":"停止上傳","Upload URL might be wrong or doesn't exist.":"檔案URL可能有誤或者不存在。","tb":"tb","Size":"大小","Close":"關閉","You must specify either browse_button or drop_element.":"您必須指定 browse_button 或 drop_element。","Init error.":"初始化錯誤。","Add files to the upload queue and click the start button.":"將檔案加入上傳序列,然後點選”開始上傳“按鈕。","List":"清單","Filename":"檔案名稱","%s specified, but cannot be found.":"找不到已選擇的 %s。","Image format either wrong or not supported.":"圖片格式錯誤或者不支援。","Status":"狀態","HTTP Error.":"HTTP 錯誤。","Start Upload":"開始上傳","Error: File too large:":"錯誤: 檔案大小太大:","kb":"kb","Duplicate file error.":"錯誤:檔案重複。","File size error.":"錯誤:檔案大小超過限制。","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"錯誤:不接受的檔案格式:","Select files":"選擇檔案","%s already present in the queue.":"%s 已經存在目前的檔案序列。","Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.":"圖片解析度超出範圍! <b>%s</b> 最高只支援到 %wx%hpx。","File: %s":"檔案: %s","b":"b","Uploaded %d/%d files":"已上傳 %d/%d 個文件","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"每次只能上傳 %d 個檔案,超過限制數量的檔案將被忽略。","%d files queued":"%d 個檔案加入到序列","File: %s, size: %d, max file size: %d":"檔案: %s, 大小: %d, 檔案大小上限: %d","Thumbnails":"縮圖","Drag files here.":"把檔案拖曳到這裡。","Runtime ran out of available memory.":"執行時耗盡了所有可用的記憶體。","File count error.":"檔案數量錯誤。","File extension error.":"檔案副檔名錯誤。","mb":"mb","Add Files":"增加檔案"},
en: {"startedStatusText": "Uploading NO.<strong>{uploading}</strong> file, total <strong title=\"Total size: {size}\" data-toggle=\"tooltip\" class=\"text-primary\">{total}</strong> files, <span class=\"uploader-status-uploaded\">Uploaded <strong title=\"Total size: {uploadedSize}\" data-toggle=\"tooltip\" class=\"text-primary\">{uploaded}</strong> files, </span><span class=\"uploader-status-failed\"><strong>{failed}</strong> failed, </span>progress <strong>{percent}%</strong>, average spped <strong>{speed}</strong>。", "initStatusText": "Append or drag file here.", "stoppedStatusText": "Total <strong title=\"Total size: {size}\" data-toggle=\"tooltip\" class=\"text-primary\">{total}</strong> files<span class=\"uploader-status-queue\">, <strong>{queue}</strong> files in queue</span><span class=\"uploader-status-uploaded\">, uploaded <strong title=\"Total size: {uploadedSize}\" data-toggle=\"tooltip\" class=\"text-primary\">{uploaded}</strong> files</span><span class=\"uploader-status-failed\">, <strong>{failed}</strong> failed</span><span class=\"uploader-status-uploaded\">, average spped <strong>{speed}</strong></span>。", "deleteConfirm": "Remove file \"{name}\" form upload queue?", "rename": "Rename", "repeat": "Repeat", "remove": "Remove", "dropPlaceholder": "Drop file here.", "queue": "Wait", "uploading": "Uploading", "failed": "Failed", "done": "Done","Stop Upload":"Stop Upload","Upload URL might be wrong or doesn't exist.":"Upload URL might be wrong or doesn't exist.","tb":"tb","Size":"Size","Close":"Close","You must specify either browse_button or drop_element.":"You must specify either browse_button or drop_element.","Init error.":"Init error.","Add files to the upload queue and click the start button.":"Add files to the upload queue and click the start button.","List":"List","Filename":"Filename","%s specified, but cannot be found.":"%s specified, but cannot be found.","Image format either wrong or not supported.":"Image format either wrong or not supported.","Status":"Status","HTTP Error.":"HTTP Error.","Start Upload":"Start Upload","Error: File too large:":"Error: File too large:","kb":"kb","Duplicate file error.":"Duplicate file error.","File size error.":"File size error.","N/A":"N/A","gb":"gb","Error: Invalid file extension:":"Error: Invalid file extension:","Select files":"Select files","%s already present in the queue.":"%s already present in the queue.","Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.":"Resoultion out of boundaries! <b>%s</b> runtime supports images only up to %wx%hpx.","File: %s":"File: %s","b":"b","Uploaded %d/%d files":"Uploaded %d/%d files","Upload element accepts only %d file(s) at a time. Extra files were stripped.":"Upload element accepts only %d file(s) at a time. Extra files were stripped.","%d files queued":"%d files queued","File: %s, size: %d, max file size: %d":"File: %s, size: %d, max file size: %d","Thumbnails":"Thumbnails","Drag files here.":"Drag files here.","Runtime ran out of available memory.":"Runtime ran out of available memory.","File count error.":"File count error.","File extension error.":"File extension error.","mb":"mb","Add Files":"Add Files"}
};
$.zui.plupload = Plupload;
$.zui.moxie = Moxie;
$.fn.uploader.Constructor = Uploader;
// Auto call uploader after document load complete
$(function() {
$('[data-ride="uploader"]').uploader();
});
}(jQuery, window, plupload, moxie, undefined));
/// ========================================================================
/// ZUI: tree.less
/// http://zui.sexy
/// ========================================================================
/// Copyright 2016 cnezsoft.com; Licensed MIT
/// ========================================================================
// Uploader container style
.uploader {
margin-bottom: @line-height-computed;
position: relative;
}
// File drag and drop
.file-dragable {position: relative}
[data-drop-placeholder]:before {
content: attr(data-drop-placeholder);
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 2px dashed @color-warning;
background-color: rgba(255,255,255,.7);
z-index: 10;
font-size: 16px;
transition: all @animation-speed-fast;
text-align: center;
pointer-events: none;
.opacity(0);
transform: scale(.95);
}
.file-dragable[data-drop-placeholder]:before {
.opacity(1);
transform: scale(1);
}
.file-drag-enter[data-drop-placeholder]:before {
background-color: @color-warning-pale;
}
// File list
.file-list {
min-height: 32px;
position: relative;
border: 1px solid @color-gray-light;
margin-bottom: @line-height-computed/2;
&[data-drag-placeholder] {
&:before {
display: block;
position: absolute;
right: 0;
left: 0;
content: attr(data-drag-placeholder);
text-align: center;
color: @color-gray-light;
line-height: 32px;
top: 50%;
margin-top: -15px;
transition: all @animation-speed-normal;
}
&:hover:before {
color: @color-gray;
}
}
}
// Uploader actions
.uploader-actions {
background-color: @color-gray-pale;
.file-list + & {
border: 1px solid @color-gray-light;
border-top: none;
margin-top: -@line-height-computed/2;
}
.uploader-status {
line-height: 20px;
padding: 5px 10px;
}
}
// Uploader message
.uploader-message {
color: @color-white;
background: @color-primary;
padding: 5px 10px;
display: none;
height: 30px;
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 1;
.opacity(.95);
> .close {
position: absolute;
top: 3px;
right: 10px;
color: inherit;
opacity: .4;
text-shadow: none;
&:hover {opacity: 1;}
}
&[data-type="danger"] {background: @color-danger;}
&[data-type="warning"] {background: @color-warning;}
&[data-type="info"] {background: @color-info;}
&[data-type="success"] {background: @color-success;}
}
// File in file list
.file-list {
.file {
position: relative;
z-index: 0;
transition: background @animation-speed-normal;
background-color: @color-white;
+ .file {
border-top: 1px solid @color-gray-light;
}
}
.file-wrapper {
position: relative;
z-index: 2;
display: table;
table-layout: fixed;
width: 100%;
transition: background @animation-speed-normal;
&:hover {
background-color: rgba(0,0,0,.05);
}
> .file-icon,
> .content,
> .actions {
display: table-cell;
vertical-align: middle;
}
> .actions {
width: 150px;
text-align: right;
> .btn {
padding: 5px 8px;
&:hover {
background-color: rgba(0,0,0,.07);
}
}
}
}
.file-icon {
position: relative;
width: 32px;
line-height: 32px;
text-align: center;
.opacity(.7);
transition: opacity @animation-speed-normal;
}
.file-icon-image {
position: absolute;
top: 5px;
left: 5px;
right: 5px;
bottom: 5px;
background-color: @color-white;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.file-name {
transition: all @animation-speed-fast;
&[contenteditable] {
background-color: @color-white;
outline: 1px solid @color-primary;
padding: 0 5px;
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@color-primary, 20%);
}
}
.file-name,
.file-size {
.nobr();
text-overflow: ellipsis;
}
.file-renaming {
.file-name[contenteditable] {text-overflow: initial;}
}
.file:hover .file-name {color: @color-primary;}
.file:hover .file-icon {opacity: 1;}
.file-wrapper > .content > .file-name {float: left;}
.file-wrapper > .content > .file-size {float: right; margin-top: 2px;}
.file-status {
display: inline-block;
text-align: right;
line-height: 20px;
padding: 5px;
&:hover {
background-color: rgba(0,0,0,.07);
}
> .icon {
vertical-align: middle;
line-height: 20px;
transition: all @animation-speed-slow .2s;
transform: scale(1);
opacity: 1;
&:before {content: @icon-check-circle;}
}
> .text {
display: inline-block;
padding: 0 6px;
line-height: 20px;
font-size: 12px;
&:empty {display: none}
}
}
.file[data-status="uploading"] .file-status {
> .icon {
transform: scale(0);
.opacity(0);
}
> .text {
border-radius: 10px;
background-color: @color-primary;
color: #fff;
}
}
.file[data-status="queue"] .file-status {color: @color-warning;}
.file[data-status="queue"] .file-status > .icon:before {content: @icon-cloud-upload;}
.file[data-status="failed"] .file-status {color: @color-danger;}
.file[data-status="failed"] .file-status > .icon:before {content: @icon-warning-sign;}
.file[data-status="done"] .file-status {color: @color-success;}
.file .actions > .btn-reset-file,
.file[data-status="failed"] .actions > .btn-rename-file,
.file[data-status="uploading"] .actions > .btn,
.file[data-status="done"] .actions > .btn {display: none}
.file[data-status="failed"] .actions > .btn-reset-file {display: inline-block;}
&.file-rename-by-click [data-status="queue"] .file-name:hover {
background-color: rgba(255,255,255,.5);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@color-primary, 20%);
}
.file-progress-bar {
position: absolute;
z-index: 10;
background-color: fade(@color-primary, 10%);
left: 0;
top: 0;
bottom: 0;
.opacity(0);
box-shadow: inset 0 -2px @color-primary;
transition: width .6s ease, opacity @animation-speed-normal;
}
.file[data-status="uploading"] .file-progress-bar {.opacity(1);}
.file[data-status="queue"] {background-color: @color-warning-pale;}
.file[data-status="failed"] {background-color: @color-danger-pale;}
.file[data-status="done"] {background-color: @color-white;}
}
// Large file list
.file-list-lg {
.file {min-height: 50px;}
.file-icon {
width: 50px;
line-height: 50px;
.icon {
display: block;
font-size: 28px;
width: 50px;
line-height: 50px;
text-align: center;
position: relative;
}
.icon-file-o {
position: relative;
left: -2px;
}
}
.file-status {line-height: 40px;}
.file-status > .icon {font-size: 20px;}
.file[data-status="done"] .file-status {padding: 5px 12px;}
.file-wrapper > .content > .file-name {
float: none;
line-height: 20px;
}
.file-wrapper > .content > .file-size {
float: none;
line-height: 14px;
}
.file-wrapper > .actions > .btn {
padding: 14px 8px;
}
.file-renaming {
.file-name[contenteditable] {
line-height: 34px;
font-size: 14px;
}
.file-wrapper > .content > .file-size {display: none}
}
}
// File list grid
.file-list-grid {
margin-left: -8px;
margin-right: -8px;
border: none;
.clearfix();
.file {
float: left;
width: 120px;
height: 120px;
margin: 8px 8px 35px 8px;
display: block;
border: 1px solid @color-gray-light;
border-radius: @border-radius-base;
}
.file .file-icon {
display: block;
width: 118px;
height: 118px;
overflow: hidden;
}
.file-icon > .icon {
font-size: 70px;
line-height: 118px;
}
.file-icon-image {
top: -1px;
left: -1px;
right: -1px;
bottom: -1px;
}
.file-wrapper {
display: block;
width: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.file-wrapper > .content {
display: block;
left: -1px;
right: -1px;
text-align: center;
position: absolute;
bottom: -24px;
transition: all @animation-speed-fast;
}
.file-wrapper > .content > .file-name {
float: none;
line-height: 16px;
padding: 4px 0;
position: relative;
z-index: 5;
border: 1px solid transparent;
}
.file-wrapper > .content > .file-size {
line-height: 18px;
display: block;
position: absolute;
top: -26px;
left: 8px;
padding: 0 5px;
border-radius: 9px;
background-color: #808080;
background-color: rgba(0,0,0,.5);
color: #fff;
.opacity(0);
transition: opacity @animation-speed-normal;
}
.file-renaming .file-wrapper > .content > .file-name,
.file-wrapper > .content:hover > .file-name {
word-break: break-all;
text-overflow: initial;
white-space: normal;
border-color: @color-gray-light;
background-color: @color-white;
box-shadow: none;
}
.file-renaming .file-wrapper > .content > .file-name {
padding: 4px;
text-align: left;
}
.file:hover .file-wrapper > .content > .file-size {.opacity(1);}
.file-wrapper > .actions {
display: block;
position: absolute;
top: 0;
right: 0;
left: 0;
width: 118px;
}
.file-wrapper:hover > .actions {background: rgba(255,255,255,.85)}
.file-wrapper > .actions > .file-status {
position: absolute;
left: 0;
top: 0;
padding: 4px 5px;
height: 28px;
> .icon {
display: inline-block;
position: relative;
font-size: 21px;
top: -1px;
text-shadow: -1px -1px 0 @color-white, 1px -1px 0 @color-white, -1px 1px 0 @color-white, 1px 1px 0 @color-white;
}
> .text {padding: 0;}
}
.file[data-status="uploading"] .file-wrapper > .actions > .file-status > .text {
position: absolute;
top: 4px;
left: 4px;
padding: 0 8px;
}
.file[data-status="failed"] .file-wrapper > .actions > .file-status {
background-color: @color-danger;
color: @color-white;
padding: 0 8px;
border-radius: 10px;
height: 20px;
top: 4px;
left: 4px;
}
.file-wrapper > .actions > .btn {
padding: 3px 6px;
.opacity(0);
}
.file-wrapper:hover > .actions > .btn {.opacity(1);}
.file-progress-bar {
box-shadow: inset 0 -4px @color-primary;
}
+ .uploader-actions {border: none}
}
......@@ -46,7 +46,7 @@
"resource": ["assets/respond.js"]
},
"desc": "min/max-width media query polyfill",
"Souce": "Scott Jehl",
"souce": "Scott Jehl",
"license": "MIT",
"licenseFile": "https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT",
"website": "https://github.com/scottjehl/Respond"
......@@ -1229,6 +1229,16 @@
"js": ["src/js/selectable.js"]
},
"ver": "1.5.0"
},
"uploader": {
"name": "文件上传",
"src": {
"js": ["src/js/uploader.js"],
"less": ["src/less/views/uploader.less"]
},
"dpds": ["plupload"],
"ver": "1.6.0",
"ignoreDpds": false
}
},
"builds": {
......@@ -1265,7 +1275,7 @@
},
"seperate": {
"title": "Seperate bundles",
"bundles": ["jquery", "calendar", "kindeditor", "datetimepicker", "chosen", "chosenicons", "imgcutter", "datatable", "ieonly", "chart", "array", "hotkey", "board", "migrate1.2", "clipboard", "prettify", "sortable", "selectable", "colorpicker", "colorset.js", "imgready", "dashboard", "bootbox", "ueditor"]
"bundles": ["jquery", "calendar", "kindeditor", "datetimepicker", "chosen", "chosenicons", "imgcutter", "datatable", "ieonly", "chart", "array", "hotkey", "board", "migrate1.2", "clipboard", "prettify", "sortable", "selectable", "colorpicker", "colorset.js", "imgready", "dashboard", "bootbox", "ueditor", "uploader"]
},
"dist": {
"title": "Dist bundles",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册