用过Juploader上传组件的人应该对其不陌生,详细了解请访问 http://www.kudystudio.com/jUploader/index.html,这个的无刷新上传还是比较好用的,但它有一个缺陷,就是上传只显示一个按钮,选择完文件后立即上传,不能将上传的工作绑定到一个元素上,进行灵活的控制,比如要实现这样的功能:
点击上传按钮,弹出文件浏览器选取文件,选择好后将文件路径显示在文本框中,点击“导入”按钮进行上传操作。
ok,无刷新上传Juploader可以实现,但是其他的功能怎么办?
不用着急,我们把该组件改一下,使其即可以保持原来的功能,还可以实现你要的功能,并可对其扩展,看源码:
/*
* jQuery jUploader 1.0
* http://www.kudystudio.com
* Author: kudy chen (kudychen@gmail.com)
*
* Copyright 2012, kudy studio
* Dual licensed under the MIT or GPL Version 3 licenses.
*
* Last Modified: 2012-03-31
*/
(function ($) {
window.jUploader = $.jUploader = function (options) {
options = $.extend({}, $.jUploader.defaults, options);
options.id = $.jUploader.createId();
options.uploading = false;
var initButton = function () {
options.button = (typeof options.button == 'string') ? $('#' + options.button) : $(options.button);
options.button.css({
cursor: 'pointer',
position: 'relative',
overflow: 'hidden',
// Make sure browse button is in the right side in IE
direction: 'ltr'
})
.addClass('jUploader-button')
.bind('mouseover', function () {
$(this).addClass('jUploader-button-hover');
})
.bind('mouseout', function () {
$(this).removeClass('jUploader-button-hover');
})
.children('span').text(options.messages.upload);
if (options.cancelable) {
options.button.bind('click', cancel)
}
options.button.append(createInput());
return options.button;
};
var createIframe = function () {
var id = 'jUploaderIframe' + options.id;
var iframe = $('<iframe id="' + id + '" name="' + id + '" src="javascript:false;" style="display:none"></iframe>').bind('load', complete);
return iframe;
};
var createForm = function () {
var id = 'jUploaderForm' + options.id;
var form = $('<form id="' + id + '" name="' + id + '" action="' + options.action + '" target="jUploaderIframe' + options.id + '" method="post" enctype="multipart/form-data" style="display:none"></form>');
return form;
};
var createInput = function () {
// οnchange="this.blur();"
// is to aotu-rasie input file onchange event in IE(it is a bug in IE)
var input = $('<input type="file" οnchange="this.blur();" />');
input.unbind("click");
input
.attr("id", 'jUploader-file' + options.id)
.attr("name", 'jUploaderFile')
.css({
position: 'absolute',
right: 0,
top: 0,
margin: 0,
opacity: 0,
padding: 0,
fontFamily: 'Arial',
fontSize: '118px',
verticalAlign: 'baseline',
cursor: 'pointer'
})
.bind('change', function () {
var $_this = this;
fileUrl = $_this.value;
options.fileUrl = fileUrl;
options.fileName = getFileName($_this);
//eventType来确定如何处理事件 1.默认为选择完文件自动上传 2.将上传动作绑定到设置的按钮上
if(options.eventType == 1){
//filenamed为参数设置里用来存放文件名的文本框
$("#"+options.filenamed).val($('#jUploader-file' + options.id).val());
if (validateFile($_this)) {
//进行检查完毕,上传
upload();
}
}else if(options.eventType == 2){
options.fileName = getFileName($_this);
$("#"+options.filenamed).val($('#jUploader-file' + options.id).val());
//在参数给定的按钮上绑定事件,点击该按钮会触发上传动作
$("#"+options.addeventbutton).unbind('click');
$("#"+options.addeventbutton).click(function() {
if (validateFile($_this)) {
upload();
}
});
}
});
// IE and Opera, unfortunately have 2 tab stops on file input
// which is unacceptable in our case, disable keyboard access
if (window.attachEvent) {
// it is IE or Opera
input.attr('tabIndex', "-1");
}
return input;
};
var validateFile = function (file) {
var name = getFileName(file);
if (!isAllowedExtension(name)) {
showMessage('invalidExtension', name);
return false;
} else if (name == '') {
showMessage('emptyFile', name);
return false;
}
return true;
};
var getFileName = function (file) {
// get input value and remove path to normalize
return file.value.replace(/.*(\/|\\)/, "");
};
var formatFileName = function (name) {
if (name.length > 33) {
name = name.slice(0, 19) + '...' + name.slice(-13);
}
return name;
};
var isAllowedExtension = function (fileName) {
var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : '';
if (!options.allowedExtensions.length) { return true; }
for (var i = 0; i < options.allowedExtensions.length; i++) {
if (options.allowedExtensions[i].toLowerCase() == ext) { return true; }
}
return false;
};
var showMessage = function (type, fileName) {
var message = options.messages[type]
.replace('{file}', formatFileName(fileName))
.replace('{extensions}', options.allowedExtensions.join(', '));
options.showMessage(message);
};
var log = function (message) {
if (options.debug && window.console) console.log('[jUploader] ' + message);
};
var upload = function () {
options.uploading = true;
options.onUpload(options.fileName);
// prepare iframe and form for uploading
$(document.body).append(createIframe()).append(createForm());
// move the input to the target form
$('#jUploader-file' + options.id)
.attr('id', 'jUploader-file-uploading' + options.id)
.appendTo('#jUploaderForm' + options.id);
// create new input, and hide it for cancel event
options.button.append(createInput().hide());
if (options.cancelable) {
options.button.children('span').text(options.messages.cancel);
}
// submit it
$('#jUploaderForm' + options.id).get(0).submit();
};
var cancel = function () {
if (options.uploading) {
options.uploading = false;
options.onCancel(options.fileName);
options.button.children('span').text(options.messages.upload);
$('#jUploaderForm' + options.id).remove();
$('#jUploaderIframe' + options.id).attr('src', 'javascript:false;').remove();
$('#jUploader-file' + options.id).show();
}
};
var complete = function () {
var iframe = $('#jUploaderIframe' + options.id).get(0);
// when we remove iframe from dom
// the request stops, but in IE load
// event fires
if (!iframe.parentNode) {
return;
}
// fixing Opera 10.53
if ((iframe.contentDocument &&
iframe.contentDocument.body &&
iframe.contentDocument.body.innerHTML == "false")
|| (iframe.contentWindow.document &&
iframe.contentWindow.document.body &&
iframe.contentWindow.document.body.innerHTML == "false")) {
// In Opera event is fired second time
// when body.innerHTML changed from false
// to server response approx. after 1 sec
// when we upload file with iframe
return;
}
// iframe.contentWindow.document - for IE<7
var doc = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document;
var response;
// fix for chrome
if (doc.body.innerHTML == '') {
return;
}
options.uploading = false;
$('#jUploader-file' + options.id).show();
options.button.children('span').text(options.messages.upload);
log("innerHTML = " + doc.body.innerHTML);
try {
var json = doc.body.innerHTML.replace(/<pre>(.*)<\/pre>/g, '$1');
response = eval("(" + json + ")");
} catch (e) {
response = {};
//throw e;
}
// timeout added to fix busy state in FF3.6
setTimeout(function () {
$('#jUploaderForm' + options.id).remove();
$('#jUploaderIframe' + options.id).remove();
}, 10);
options.onComplete(options.fileName, response);
};
// remind user of uploading
$(window).bind('beforeunload', function (e) {
if (!options.uploading)
return;
var e = e || window.event;
// for ie, ff
e.returnValue = options.messages.onLeave;
// for webkit
return options.messages.onLeave;
});
return initButton();
};
$.jUploader.version = 1.0;
$.jUploader.defaults = {
button: null,
action: 'upload.aspx',
allowedExtensions: [],
cancelable: true,
// events
onUpload: function (fileName) { },
onComplete: function (fileName, response) { },
onCancel: function (fileName) { },
// messages
messages: {
upload: 'Upload',
cancel: 'Cancel',
emptyFile: "{file} is empty, please select files again without it.",
invalidExtension: "{file} has invalid extension. Only {extensions} are allowed.",
onLeave: "The files are being uploaded, if you leave now the upload will be cancelled."
},
showMessage: function (message) {
alert(message);
},
debug: false
};
$.jUploader.setDefaults = function (defaults) {
$.jUploader.defaults = $.extend({}, $.jUploader.defaults, defaults);
};
$.jUploader.createId = (function () {
var id = 0;
return function () { return ++id; };
})();
})(jQuery);
从78行开始看,我们对其进行了改造,用一个“eventType”参数控制他的上传动作的行为,1.默认为选择完文件自动上传 2.将上传动作绑定到设置的按钮上
如果我们需要将出发动作绑定到一个元素上,需要指定一个元素的id,在这里参数为“addeventbutton”;用来显示文件路径的文本框的id 参数为“filenamed”
组件改造完毕,来看在页面中如何使用该组件:
$.jUploader({
button: 'upload_btn', // 这里设置按钮id
action: '<?php echo site_url('role_setup/answer_import/' . $event_id);?>', // 这里设置上传处理接口,这个加了参数test_cancel=1来测试取消
eventType:2,//触发类型
addeventbutton:'import_begin',// 要绑定事件的元素的id
filenamed:'filename',//存放选择的文件路径的文本框的id
onComplete: function (fileName, response) {
// response是json对象,格式可以按自己的意愿来定义,例子为: { success: true, fileUrl:'' }
if (response.success) {
} else {
}
}
});
在传给Juploader方法的参数中,我们增加了eventType,addeventbutton,用于存放路径的元素的id filenamed
大功告成!
文章转自:http://blog.csdn.net/andy1219111/article/details/8057236