本文介绍如何在bootstrap-wysiwyg编辑器中集成ajaxFileUpload插件,解决原生FileApi仅生成Base64字符串的问题。通过重写insertFiles函数并修改监听器,实现图片上传至服务器后获取真实URL并实时插入编辑器的功能,确保存储路径的有效性与用户体验。
插件选型与需求分析
近期项目要求实现一个前端文本编辑框,并具备图片上传后实时查看的功能。对比市面上几款插件后,首先排除了百度UEditor,因其框架过于庞大,引入过多文件不符合精简需求;其次考虑jQuery的easyUI,虽个人版免费,但鉴于项目为公司业务,使用商业版框架存在合规风险。考虑到项目前端主要基于Bootstrap构建,最终选定bootstrap-wysiwyg插件,该插件精简、轻量且具备较强的扩展性。
引入bootstrap-wysiwyg并实现文本编辑功能较为便捷,但注意到其图片上传机制基于FileApi。尽管FileApi实现的无刷新预览体验良好,但在实际存入数据库时,通常希望存储图片在服务器的静态路径,而非字符串化的Base64数据。因此,需要对bootstrap-wysiwyg(以下简称WY)进行适当改写以满足需求。
源码分析与功能改写
首先观察页面上的图片控件,忽略其他控件,通过查阅源码可以发现如下结构:
<div class="btn-group">
<a class="btn" title="Insert picture (or just drag & drop)" id="pictureBtn">
<i class="icon-picture"></i></a>
<input type="file" data-role="magic-overlay"
data-target="#pictureBtn"
data-edit="insertImage" />
</div>
对此进行说明:data-role和data-target属性是Bootstrap中预定义的事件,在此处主要涉及布局相关逻辑,无需过多关注。关键点在于第三个属性data-edit,Bootstrap本身并未定义此事件。观察bootstrap-wysiwyg.js源码,可以发现相关处理代码:
toolbar.find('input[type=file][data-' + options.commandRole + ']')
.change( ...
...
commandRole : 'edit',
由此可见,该属性主要是为了方便选择器操作而实现,相当于为图片按钮添加了监听器事件。
接下来研究WY图片预览的实现机制。如上述代码所示,监听器捕获fileInput的change事件后做出响应,并调用insertFiles函数。
restoreSelection();
if (this.type === 'file' && this.files && this.files.length > 0) {
insertFiles(this.files);
}
saveSelection();
his.value = '';
定位到insertFiles函数的定义。
insertFiles = function (files) {
editor.focus();
$.each(files, function (idx, fileInfo) {
if (/^image\//.test(fileInfo.type)) {
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
execCommand('insertimage', dataUrl);
}).fail(function (e) {
options.fileUploadError("file-reader", e);
});
} else {
options.fileUploadError("unsupported-file-type", fileInfo.type);
}
});
}
注意到该函数使用了jQuery的$.Deferred()方法,首先调用readFileIntoDataUrl方法,成功后通过自封装的execCommand方法将图片输出到文本框。此时插入的图片实际上是一个<img>标签,其src属性为字符串表示的图片数据。因此,我们的目标是在监听器触发后,先执行文件上传,获取图片的src链接,再将链接传递给后续的execCommand方法。
由于笔者对Deferred对象尚不熟悉,故采用更为常规的callback回调模式进行实现。
观察ajaxFileUpload的调用方式:
$.ajaxFileUpload({
url : ...,
secureurl : false,
fileElementId : ...,
dataType : "json",
success : function(obj) {
...
},
error : function() {
...
}
});
该调用有两个必选属性:url和fileElementId。为了保持依赖关系的正确性,直接重写ajaxFileUpload插件并不可取。但由于WY控件是通过监听器实现的,通过函数直接传递参数并不现实,因此需要为输入框定义特定属性以达到目的。
在fileInput元素中添加以下属性:
<input type="file" id="pictureInput" name="picture"
data-role="magic-overlay" data-target="#pictureBtn"
data-edit="insertImage" action="..." />
其中id用于对应fileElementId,name属性也是必须的,主要用于后台取值时的标识,action属性指定图片需要提交到的服务器URL。
实现图片上传与实时预览
在bootstrap-wysiwyg.js中定义一个名为uploadFileToServer的函数,其格式如下:
var uploadFileToServer = function(id, action, callback) {
$.ajaxFileUpload({
url : action,
secureurl : false,
fileElementId : id,
dataType : 'json',
success : function(obj) {
if (obj.status) {
callback(obj.imgsrc);
} else
options.fileUploadError("server-internal-exception",
obj.message);
},
error : function() {
options.fileUploadErroe("upload-failure", "");
}
});
将insertFiles方法改写如下:
insertFiles = function(files, id, action) {
editor.focus();
$.each(files, function(idx, fileInfo) {
if (/^image\//.test(fileInfo.type)) {
/*
* $.when(readFileIntoDataUrl(fileInfo)).done(function(dataUrl) {
* execCommand('insertimage', dataUrl); }).fail(function(e) {
* options.fileUploadError("file-reader", e); });
*/
uploadFileToServer(id, action, function(src) {
execCommand('insertimage', src);
});
} else {
options.fileUploadError("unsupported-file-type",
fileInfo.type);
}
});
同时对监听器进行相应修改,以便获取必要的属性参数。
toolbar.find('input[type=file][data-' + options.commandRole + ']')
.change(
function() {
restoreSelection();
if (this.type === 'file' && this.files
&& this.files.length > 0) {
insertFiles(this.files, $(this).attr('id'),
$(this).attr('action'));
}
saveSelection();
this.value = '';
});
主要增加了两个参数位置以支持上传逻辑。
至此,改写工作完成。请注意,为确保功能正确执行,请在控件初始化之前引用ajaxFileUpload.js文件。
如果读者希望深入学习,可以点击相关链接进行学习,另附三个精彩专题供参考:
Bootstrap学习教程
Bootstrap实战教程
Bootstrap插件使用教程
以上为本文全部内容,希望对读者的学习有所帮助,也欢迎大家多多支持本站。