You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vue-shop-admin-work/public2/ueditor/dialogs/attachment/attachment.js

1158 lines
123 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* User: Jinqn
* Date: 14-04-08
* Time: 下午16:34
* 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片
*/
// 立即执行函数,用于创建一个独立的作用域,避免变量污染全局环境
(function () {
// 定义两个变量,用于存储上传文件相关对象和在线文件相关对象,初始值为 undefined后续会根据情况进行赋值
var uploadFile,
onlineFile;
// 当页面加载完成时触发的事件处理函数,用于执行一些初始化操作
window.onload = function () {
// 调用 initTabs 函数,用于初始化 tab 标签相关的交互逻辑等功能
initTabs();
// 调用 initButtons 函数,用于初始化按钮相关的事件处理等功能
initButtons();
};
/* 初始化tab标签 */
function initTabs() {
// 通过自定义函数 $G 获取 id 为 'tabhead' 的元素,并获取其所有子元素(可能是各个 tab 标签元素)
var tabs = $G('tabhead').children;
// 循环遍历每个 tab 标签元素
for (var i = 0; i < tabs.length; i++) {
// 使用 domUtils 对象的 on 方法(可能是自定义的事件绑定函数)为每个 tab 标签元素绑定点击事件处理函数
domUtils.on(tabs[i], "click", function (e) {
// 获取触发点击事件的实际目标元素兼容不同浏览器获取方式e.target 适用于标准浏览器e.srcElement 适用于IE浏览器
var target = e.target || e.srcElement;
// 调用 setTabFocus 函数,传入目标元素的 data-content-id 属性值(可能用于标识对应的内容区域等),设置当前选中的 tab 标签焦点
setTabFocus(target.getAttribute('data-content-id'));
});
}
// 初始设置 'upload' 对应的 tab 标签为焦点状态(默认选中),调用 setTabFocus 函数并传入 'upload'
setTabFocus('upload');
}
/* 初始化tabbody */
function setTabFocus(id) {
// 如果传入的 id 参数为空值,则直接返回,不执行后续操作
if (!id) return;
// 定义循环变量 i 和用于存储 tab 标签对应内容区域 id 的变量 bodyId同时获取所有 tab 标签元素
var i, bodyId, tabs = $G('tabhead').children;
// 循环遍历每个 tab 标签元素
for (i = 0; i < tabs.length; i++) {
// 获取当前 tab 标签元素的 data-content-id 属性值,赋值给 bodyId该值可能对应着相关的内容区域元素的 id
bodyId = tabs[i].getAttribute('data-content-id')
// 如果当前 tab 标签元素的 data-content-id 属性值与传入的 id 参数相等,说明该 tab 标签被选中
if (bodyId == id) {
// 使用 domUtils 对象的 addClass 方法(可能是自定义的添加类名函数)给当前 tab 标签元素添加 'focus' 类名,用于设置样式等体现焦点状态
domUtils.addClass(tabs[i], 'focus');
// 使用 domUtils 对象的 addClass 方法给对应的内容区域元素(通过 $G 获取,传入 bodyId也添加 'focus' 类名,同样用于体现焦点相关样式等
domUtils.addClass($G(bodyId), 'focus');
} else {
// 如果当前 tab 标签元素的 data-content-id 属性值与传入的 id 参数不相等,使用 domUtils 对象的 removeClasses 方法(可能是自定义的移除类名函数)从当前 tab 标签元素移除 'focus' 类名
domUtils.removeClasses(tabs[i], 'focus');
// 使用 domUtils 对象的 removeClasses 方法从对应的内容区域元素移除 'focus' 类名
domUtils.removeClasses($G(bodyId), 'focus');
}
}
// 根据传入的 id 参数值进行不同的操作
switch (id) {
// 如果 id 为 'upload',表示当前选中的是上传文件相关的 tab 标签
case 'upload':
// 如果 uploadFile 变量还未赋值(即 undefined则创建一个 UploadFile 类的实例(传入 'queueList' 作为参数,可能用于标识相关队列等信息)并赋值给 uploadFile 变量
uploadFile = uploadFile || new UploadFile('queueList');
break;
// 如果 id 为 'online',表示当前选中的是在线文件相关的 tab 标签
case 'online':
// 如果 onlineFile 变量还未赋值(即 undefined则创建一个 OnlineFile 类的实例(传入 'fileList' 作为参数,可能用于标识相关文件列表等信息)并赋值给 onlineFile 变量
onlineFile = onlineFile || new OnlineFile('fileList');
break;
}
}
/* 初始化onok事件 */
function initButtons() {
// 给 dialog 对象的 onok 属性(可能是对话框确认按钮点击时触发的事件处理函数)赋值一个函数
dialog.onok = function () {
// 创建一个空数组 list用于存储要插入的文件相关信息后续会根据不同情况填充内容
var list = [], id, tabs = $G('tabhead').children;
// 循环遍历所有 tab 标签元素,查找当前处于焦点状态(被选中)的 tab 标签
for (var i = 0; i < tabs.length; i++) {
if (domUtils.hasClass(tabs[i], 'focus')) {
// 获取当前焦点 tab 标签的 data-content-id 属性值,赋值给 id用于判断当前处于哪个功能模块上传文件或在线文件等
id = tabs[i].getAttribute('data-content-id');
break;
}
}
// 根据获取到的 id 值进行不同的操作
switch (id) {
// 如果 id 为 'upload',表示当前处于上传文件相关的功能模块
case 'upload':
// 调用 uploadFile 对象的 getInsertList 方法(可能用于获取要插入的文件列表信息),将返回结果赋值给 list 数组
list = uploadFile.getInsertList();
// 调用 uploadFile 对象的 getQueueCount 方法(可能用于获取未上传文件的数量),获取未上传文件的数量并赋值给 count 变量
var count = uploadFile.getQueueCount();
// 如果还有未上传的文件count 不为0
if (count) {
// 使用 jQuery 选择器($('.info', '#queueList'),可能是获取 id 为 'queueList' 元素内部的类名为 'info' 的元素)找到对应的元素,并设置其 HTML 内容
// 内容中包含一个提示信息,使用字符串替换将 '还有2个未上传文件' 中的数字替换为实际的未上传文件数量count颜色设置为红色用于提示用户还有文件未上传
$('.info', '#queueList').html('<span style="color:red;">' + '还有2个未上传文件'.replace(/[\d]/, count) + '</span>');
// 返回 false可能用于阻止对话框继续执行后续的默认操作比如关闭等提示用户先处理未上传文件的情况
return false;
}
break;
// 如果 id 为 'online',表示当前处于在线文件相关的功能模块
case 'online':
// 调用 onlineFile 对象的 getInsertList 方法(可能用于获取要插入的在线文件列表信息),将返回结果赋值给 list 数组
list = onlineFile.getInsertList();
break;
}
// 调用 editor 对象的 execCommand 方法(可能是执行编辑器相关命令的函数),传入 'insertfile' 命令以及 list 数组(包含要插入的文件信息),执行插入文件相关的操作
editor.execCommand('insertfile', list);
};
}
/* 上传附件 */
// 定义一个名为UploadFile的构造函数用于创建与上传文件相关的对象实例接收一个参数target用于指定相关的DOM元素或元素的id标识等
function UploadFile(target) {
// 判断传入的target参数是否为字符串类型如果是则通过jQuery选择器根据该字符串当作id获取对应的DOM元素否则直接将传入的参数当作jQuery对象可能已经是选择好的DOM元素进行赋值最终将获取到的元素或对象赋值给this.$wrap属性用于后续操作中代表与上传文件相关的包裹元素
this.$wrap = target.constructor == String? $('#' + target) : $(target);
// 调用init方法用于进行一些初始化操作比如初始化文件列表、容器等相关设置
this.init();
}
// 为UploadFile构造函数的原型对象添加属性和方法这样通过该构造函数创建的所有实例对象都可以共享这些属性和方法
UploadFile.prototype = {
// 定义init方法用于进行一系列的初始化工作是整个上传文件功能初始化的入口函数
init: function () {
// 创建一个空数组用于存储上传文件的相关信息列表比如文件名、文件大小等信息后续会根据实际情况填充内容并将其赋值给this.fileList属性方便在实例对象中记录和操作文件相关数据
this.fileList = [];
// 调用initContainer方法用于初始化与上传文件相关的容器元素比如文件列表展示区域等
this.initContainer();
// 调用initUploader方法用于初始化文件上传相关的功能配置例如创建WebUploader实例、设置各种上传相关的参数等
this.initUploader();
},
// 定义initContainer方法用于初始化与上传文件相关的容器元素找到对应的DOM元素并赋值给相应的属性方便后续操作
initContainer: function () {
// 通过jQuery的find方法在之前初始化的this.$wrap代表与上传文件相关的包裹元素中查找类名为'filelist'的元素并将找到的元素赋值给this.$queue属性可能用于后续展示文件列表等操作
this.$queue = this.$wrap.find('.filelist');
},
/* 初始化容器 */
initUploader: function () {
// 将当前实例对象this赋值给变量_this用于在后续一些闭包环境中能正确访问到当前实例对象的属性和方法避免this指向问题导致的错误
var _this = this,
$ = jQuery, // just in case. Make sure it's not an other libaray.
// 获取当前实例对象的$wrap属性代表与上传文件相关的包裹元素赋值给变量$wrap方便后续使用
$wrap = _this.$wrap,
// 图片容器,通过在$wrap元素内查找类名为'filelist'的元素,获取到用于展示图片等文件的容器元素,可能用于展示上传文件的缩略图等信息,赋值给变量$queue
$queue = $wrap.find('.filelist'),
// 状态栏,包括进度和控制按钮,通过在$wrap元素内查找类名为'statusBar'的元素,获取到用于展示文件上传状态(如进度条、相关控制按钮所在的区域)的元素,赋值给变量$statusBar
$statusBar = $wrap.find('.statusBar'),
// 文件总体选择信息。通过在$statusBar元素内查找类名为'info'的元素,获取到用于展示文件总体选择情况(如已选文件数量、文件总大小等信息)的元素,赋值给变量$info
$info = $statusBar.find('.info'),
// 上传按钮,通过在$wrap元素内查找类名为'uploadBtn'的元素,获取到用于触发文件上传操作的按钮元素,赋值给变量$upload
$upload = $wrap.find('.uploadBtn'),
// 上传按钮,通过在$wrap元素内查找类名为'filePickerBtn'的元素,获取到可能用于选择文件的按钮元素(比如打开文件选择对话框的按钮),赋值给变量$filePickerBtn
$filePickerBtn = $wrap.find('.filePickerBtn'),
// 上传按钮,通过在$wrap元素内查找类名为'filePickerBlock'的元素,获取到与文件选择相关的某个块状元素(具体作用需根据上下文确定,可能是包含文件选择按钮等相关元素的一个区域),赋值给变量$filePickerBlock
$filePickerBlock = $wrap.find('.filePickerBlock'),
// 没选择文件之前的内容。通过在$wrap元素内查找类名为'placeholder'的元素,获取到在还未选择文件时显示的占位元素(比如提示用户选择文件的提示文字所在元素等),赋值给变量$placeHolder
$placeHolder = $wrap.find('.placeholder'),
// 总体进度条,通过在$statusBar元素内查找类名为'progress'的元素获取到进度条元素并调用hide方法将其初始设置为隐藏状态可能在文件上传开始后再显示赋值给变量$progress
$progress = $statusBar.find('.progress').hide(),
// 添加的文件数量初始化为0用于记录已经添加到上传队列中的文件数量后续会根据实际添加文件的情况进行累加
fileCount = 0,
// 添加的文件总大小初始化为0用于记录已经添加到上传队列中的所有文件的总大小单位可能是字节等后续会根据实际添加文件的大小情况进行累加
fileSize = 0,
// 优化retina, 在retina下这个值是2获取设备的像素比window.devicePixelRatio如果不存在则默认为1用于根据设备的像素情况对一些元素如缩略图等的尺寸进行适配比如在高清屏幕retina屏幕上让元素显示更清晰
ratio = window.devicePixelRatio || 1,
// 缩略图大小根据之前获取的像素比ratio计算缩略图的宽度和高度初始化为113乘以像素比使缩略图在不同像素密度的屏幕上能有合适的尺寸显示
thumbnailWidth = 113 * ratio,
thumbnailHeight = 113 * ratio,
// 可能有pedding, ready, uploading, confirm, done. 定义一个变量state用于记录文件上传的状态初始为空字符串后续会根据文件上传的不同阶段如等待、准备好、正在上传、确认、完成等设置相应的值来表示当前状态
state = '',
// 所有文件的进度信息key为file id创建一个空对象percentages用于存储每个文件以文件的id作为键对应的上传进度信息比如已上传百分比等方便在上传过程中更新和查询各个文件的进度情况
percentages = {},
// 检测浏览器是否支持CSS过渡效果transition通过创建一个临时的<p>元素,检查其样式对象中是否存在'transition'或各浏览器前缀版本的'transition'属性来判断将判断结果布尔值赋值给变量supportTransition用于后续可能涉及到的动画效果等相关操作判断浏览器是否支持
supportTransition = (function () {
var s = document.createElement('p').style,
r = 'transition' in s ||
'WebkitTransition' in s ||
'MozTransition' in s ||
'msTransition' in s ||
'OTransition' in s;
s = null;
return r;
})(),
// WebUploader实例用于后续创建和配置实际的文件上传功能初始化为未赋值状态后续会进行实例化操作并配置相关参数
uploader,
// 获取文件上传的目标URL地址通过调用editor对象的getActionUrl方法并传入editor对象的getOpt方法获取的'fileActionName'配置项作为参数用于指定文件要上传到的服务器端地址赋值给变量actionUrl
actionUrl = editor.getActionUrl(editor.getOpt('fileActionName')),
// 获取允许上传的文件最大大小限制通过调用editor对象的getOpt方法获取'fileMaxSize'配置项的值用于在文件选择等阶段判断文件大小是否超出限制赋值给变量fileMaxSize
fileMaxSize = editor.getOpt('fileMaxSize'),
// 获取允许上传的文件类型扩展名先通过调用editor对象的getOpt方法获取'fileAllowFiles'配置项可能是一个数组将其转换为字符串后进行一些格式处理替换点号为逗号去除开头可能出现的逗号得到允许上传的文件类型扩展名字符串赋值给变量acceptExtensions
acceptExtensions = (editor.getOpt('fileAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');;
// 判断WebUploader.Uploader是否支持当前浏览器环境如果不支持
if (!WebUploader.Uploader.support()) {
// 在id为'filePickerReady'的元素后面插入一个新创建的<div>元素其HTML内容为lang.errorNotSupport可能是定义好的提示不支持的错误信息然后调用hide方法将其隐藏起来同时直接返回不再执行后续的初始化操作因为不支持则无法进行文件上传功能的初始化了
$('#filePickerReady').after($('<div>').html(lang.errorNotSupport)).hide();
return;
} else if (!editor.getOpt('fileActionName')) {
// 如果editor对象中没有配置'fileActionName'可能是必须配置的文件上传相关的关键参数同样在id为'filePickerReady'的元素后面插入一个新创建的<div>元素其HTML内容为lang.errorLoadConfig可能是定义好的提示加载配置错误的信息然后调用hide方法将其隐藏起来并且直接返回不再继续后续的初始化流程因为缺少关键配置无法进行正常的文件上传初始化操作
$('#filePickerReady').after($('<div>').html(lang.errorLoadConfig)).hide();
return;
}
// 创建一个WebUploader实例用于实现文件上传功能并将其赋值给uploader变量以及当前实例对象_this的uploader属性方便后续通过不同方式访问该实例
// 同时传入一个配置对象用于配置WebUploader的各项参数
uploader = _this.uploader = WebUploader.create({
// 设置文件选择区域相关的配置
pick: {
// 指定文件选择区域对应的DOM元素的id为'filePickerReady',这意味着该区域将用于触发文件选择操作,例如点击这个区域可以弹出文件选择对话框等
id: '#filePickerReady',
// 设置文件选择区域显示的提示文本为lang.uploadSelectFile这应该是一个预先定义好的国际化文本变量用于提示用户选择文件
label: lang.uploadSelectFile
},
// 指定WebUploader使用的Flash文件路径这里相对路径指向'../../third-party/webuploader/Uploader.swf'在某些浏览器不支持HTML5上传时可能会依赖此Flash文件来实现文件上传功能
swf: '../../third-party/webuploader/Uploader.swf',
// 设置文件上传的目标服务器地址使用之前获取到的actionUrl变量通过editor相关配置获取的文件上传URL指定文件要上传到的服务器端接口位置
server: actionUrl,
// 设置文件上传时表单中文件对应的字段名通过调用editor对象的getOpt方法获取'fileFieldName'配置项的值来确定,服务器端会根据这个字段名来接收上传的文件
fileVal: editor.getOpt('fileFieldName'),
// 设置是否允许重复选择文件这里设置为true表示允许重复选择相同的文件添加到上传队列中
duplicate: true,
// 设置单个文件的大小限制使用之前获取到的fileMaxSize变量通过editor相关配置获取的允许上传的最大文件大小用于在选择文件时判断单个文件大小是否超出限制超出则可能不允许添加到上传队列
fileSingleSizeLimit: fileMaxSize,
// 设置是否对文件进行压缩这里设置为false表示不对要上传的文件进行压缩处理直接上传原始文件
compress: false
});
// 为WebUploader实例添加一个按钮通过传入一个配置对象来指定按钮相关的设置
// 这里指定按钮对应的DOM元素的id为'filePickerBlock'具体该按钮的功能和样式等可能在WebUploader内部有默认设置或者后续代码中进一步定义
uploader.addButton({
id: '#filePickerBlock'
});
// 再次为WebUploader实例添加一个按钮同样传入配置对象指定按钮相关设置
// 这里指定按钮对应的DOM元素的id为'filePickerBtn'并且设置按钮显示的提示文本为lang.uploadAddFile也是预先定义好的国际化文本变量用于提示用户添加文件
uploader.addButton({
id: '#filePickerBtn',
label: lang.uploadAddFile
});
// 调用setState函数应该是自定义的用于设置文件上传状态的函数传入'pedding'(可能表示文件处于等待添加或者初始的准备状态),用于更新和记录当前文件上传的状态
setState('pedding');
// 定义一个名为addFile的函数当有文件添加到WebUploader实例中时会执行该函数主要负责创建与该文件对应的视图展示相关元素比如在页面上展示文件的名称、进度条、操作按钮等信息
function addFile(file) {
// 创建一个 <li> 元素设置其id属性为传入的file对象的id每个添加的文件应该都有唯一的id标识并在元素内部添加一些包含文件相关信息的 <p> 元素,用于后续展示文件的名称、图片包装(可能用于展示文件缩略图等)、进度条等内容
var $li = $('<li id="' + file.id + '">' +
'<p class="title">' + file.name + '</p>' +
'<p class="imgWrap"></p>' +
'<p class="progress"><span></span></p>' +
'</li>'),
// 创建一个包含文件操作按钮的 <div> 元素,设置其类名为'file-panel',内部包含了取消、向右旋转、向左旋转等操作按钮,并将其添加到之前创建的 <li> 元素($li方便后续对文件进行相应的操作交互
$btns = $('<div class="file-panel">' +
'<span class="cancel">' + lang.uploadDelete + '</span>' +
'<span class="rotateRight">' + lang.uploadTurnRight + '</span>' +
'<span class="rotateLeft">' + lang.uploadTurnLeft + '</span></div>').appendTo($li),
// 通过jQuery选择器在创建的 <li> 元素($li中查找类名为'progress'的 <p> 元素内部的 <span> 元素,用于后续操作该进度条相关的 <span> 元素(比如更新进度条的显示等),并将找到的元素赋值给变量$prgress
$prgress = $li.find('p.progress span'),
// 通过jQuery选择器在创建的 <li> 元素($li中查找类名为'imgWrap'的 <p> 元素,用于后续可能在该元素内添加文件的缩略图等操作,将找到的元素赋值给变量$wrap
$wrap = $li.find('p.imgWrap'),
// 创建一个用于展示文件错误信息的 <p> 元素,设置其类名为'error'初始设置为隐藏状态调用hide方法然后将其添加到之前创建的 <li> 元素($li当文件出现错误时可以在该元素内显示相应的错误提示信息
$info = $('<p class="error"></p>').hide().appendTo($li),
// 定义一个名为showError的内部函数用于根据传入的错误代码来显示相应的错误提示文本通过判断不同的错误代码来设置要显示的具体文本内容从预先定义好的国际化文本变量中获取相应的提示信息并将文本显示在之前创建的错误信息元素$info调用show方法使其显示出来
showError = function (code) {
switch (code) {
case 'exceed_size':
text = lang.errorExceedSize;
break;
case 'interrupt':
text = lang.errorInterrupt;
break;
case 'http':
text = lang.errorHttp;
break;
case 'not_allow_type':
text = lang.errorFileType;
break;
default:
text = lang.errorUploadRetry;
break;
}
$info.text(text).show();
};
// 判断文件的状态是否为'invalid'(无效状态,可能表示文件不符合某些上传要求等情况)
if (file.getStatus() === 'invalid') {
// 如果文件状态为'invalid'调用showError函数之前定义的用于显示错误信息的函数传入文件的statusText应该是包含具体错误原因等的文本信息以在页面上展示相应的错误提示给用户
showError(file.statusText);
} else {
// 如果文件状态不是'invalid',则在用于展示文件缩略图等的元素($wrap内设置文本内容为lang.uploadPreview预先定义好的国际化文本变量用于提示用户正在预览文件之类的信息
$wrap.text(lang.uploadPreview);
// 检查文件的扩展名file.ext将其转换为小写形式后判断是否在指定的图片文件扩展名列表'|png|jpg|jpeg|bmp|gif|'如果不在indexOf方法返回 -1表示未找到说明不是常见的图片文件类型
if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) {
// 如果不是常见图片文件类型,先清空$wrap元素内部的内容empty方法然后添加类名'notimage'(可能用于后续设置样式区分非图片文件),接着在该元素内添加一个 <i> 元素(用于展示对应文件类型的图标,通过设置类名来匹配相应的图标样式)以及一个 <span> 元素用于展示文件名称并设置title属性同样为文件名称方便鼠标悬停提示完整文件名
$wrap.empty().addClass('notimage').append('<i class="file-preview file-type-' + file.ext.toLowerCase() + '"></i>' +
'<span class="file-title" title="' + file.name + '">' + file.name + '</span>');
} else {
// 如果是常见的图片文件类型判断当前浏览器是否为IE浏览器browser.ie为真表示是IE浏览器并且IE浏览器的版本是否小于等于7browser.version <= 7
if (browser.ie && browser.version <= 7) {
// 如果是低版本IE浏览器IE7及以下则在用于展示文件缩略图等的元素$wrap内设置文本内容为lang.uploadNoPreview预先定义好的国际化文本变量可能表示该浏览器无法预览此文件之类的信息
$wrap.text(lang.uploadNoPreview);
} else {
// 如果不是低版本IE浏览器调用uploader对象WebUploader实例的makeThumb方法用于生成文件的缩略图
// 传入文件对象file、一个回调函数用于处理生成缩略图的结果成功时获取到缩略图的源地址等信息失败时进行相应错误处理以及缩略图的宽度thumbnailWidth和高度thumbnailHeight参数
uploader.makeThumb(file, function (error, src) {
// 在回调函数内部判断是否有错误error为真或者生成的缩略图源地址src为空说明生成缩略图失败了
if (error ||!src) {
// 如果生成缩略图失败,就在用于展示文件缩略图等的元素($wrap内设置文本内容为lang.uploadNoPreview提示无法预览文件
$wrap.text(lang.uploadNoPreview);
} else {
// 如果生成缩略图成功,创建一个 <img> 元素设置其src属性为生成的缩略图源地址src
var $img = $('<img src="' + src + '">');
// 先清空$wrap元素内部的内容empty方法然后将创建好的 <img> 元素添加到$wrap元素内用于在页面上展示文件的缩略图
$wrap.empty().append($img);
// 为添加的 <img> 元素绑定error事件处理函数当图片加载出现错误比如图片地址无效、网络问题等导致无法显示图片时触发该函数
$img.on('error', function () {
// 在图片加载出错时,同样在用于展示文件缩略图等的元素($wrap内设置文本内容为lang.uploadNoPreview提示无法预览文件
$wrap.text(lang.uploadNoPreview);
});
}
}, thumbnailWidth, thumbnailHeight);
}
}
// 创建一个数组将文件的大小file.size和初始进度值0作为元素放入数组中然后以文件的id为键将这个数组存储到percentages对象中用于记录每个文件的大小以及后续更新其上传进度情况
percentages[ file.id ] = [ file.size, 0 ];
// 初始化文件的旋转角度为0可能用于后续支持文件旋转相关的操作比如图片旋转等功能
file.rotation = 0;
/* 检查文件格式 */
// 判断文件的扩展名file.ext是否为空或者文件的扩展名转换为小写形式后在允许上传的文件扩展名列表acceptExtensions中是否不存在indexOf方法返回 -1表示不存在也就是检查文件格式是否符合允许上传的要求
if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) {
// 如果文件格式不符合要求调用showError函数传入'not_allow_type'(表示文件类型不允许上传的错误代码),以显示相应的错误提示信息,告知用户文件类型不被允许上传
showError('not_allow_type');
// 调用uploader对象WebUploader实例的removeFile方法将不符合文件格式要求的文件从上传队列中移除避免上传不符合规定的文件
uploader.removeFile(file);
}
}
// 为文件对象绑定'statuschange'事件处理函数当文件的状态发生改变时会触发该函数传入当前状态cur和之前的状态prev作为参数用于根据不同的状态变化执行相应的操作
file.on('statuschange', function (cur, prev) {
// 如果文件之前的状态prev是'progress'(表示正在上传进度中)
if (prev === 'progress') {
// 隐藏用于展示文件上传进度的元素($prgress并将其宽度设置为0可能用于重置进度条的显示比如上传中断等情况需要重新展示进度时先进行这样的重置操作
$prgress.hide().width(0);
} else if (prev === 'queued') {
// 如果文件之前的状态是'queued'(表示已添加到上传队列中等待上传),则移除为 <li> 元素($li代表文件对应的整个展示元素绑定的鼠标进入mouseenter和鼠标离开mouseleave事件处理函数off方法用于移除事件绑定同时移除文件操作按钮所在的 <div> 元素($btns可能是在文件进入下一个阶段比如开始上传等时不需要这些交互元素或者需要重新绑定不同的交互逻辑了
$li.off('mouseenter mouseleave');
$btns.remove();
}
// 如果文件当前状态cur是'error'(表示出现错误)或者'invalid'(无效状态)
if (cur === 'error' || cur === 'invalid') {
// 调用showError函数传入文件的statusText包含具体错误原因等的文本信息以在页面上展示相应的错误提示给用户告知文件出现错误的情况
showError(file.statusText);
// 将文件在percentages对象中记录的进度值数组中的第二个元素设置为1表示出现错误后认为文件上传已完成但实际上是失败了可能用于更新界面上进度相关的显示等情况
percentages[ file.id ][ 1 ] = 1;
} else if (cur === 'interrupt') {
// 如果文件当前状态是'interrupt'表示上传被中断调用showError函数传入'interrupt'(表示上传中断的错误代码),以显示相应的错误提示信息,告知用户文件上传被中断了
showError('interrupt');
} else if (cur === 'queued') {
// 如果文件当前状态是'queued'表示重新回到已添加到上传队列等待上传的状态可能是之前出现问题后重新排队等情况将文件在percentages对象中记录的进度值数组中的第二个元素设置为0重置文件的上传进度为初始的等待上传状态用于更新界面上进度相关的显示等情况
percentages[ file.id ][ 1 ] = 0;
} else if (cur === 'progress') {
// 如果文件当前状态是'progress'(表示正在上传进度中),隐藏之前创建的用于展示文件错误信息的元素($info可能在上传过程中之前出现的错误提示等不需要显示了并将用于展示文件上传进度的元素$prgress的display样式属性设置为'block',使其显示出来,以展示当前文件正在上传的进度情况
$info.hide();
$prgress.css('display', 'block');
} else if (cur === 'complete') {
// 如果文件当前状态是'complete'(表示文件上传完成),这里暂时没有具体的操作,可能后续需要添加如更新界面显示完成状态、提示用户上传成功等相关操作逻辑,具体根据业务需求而定
}
// 根据文件状态变化,移除文件对应的 <li> 元素($li上之前表示状态的类名格式为'state-' + prevprev是文件之前的状态然后添加表示当前状态的类名格式为'state-' + curcur是文件当前的状态这样可以通过不同的类名来应用相应的样式以体现文件在不同状态下的外观变化例如不同状态下的颜色、图标显示等不同样式效果
$li.removeClass('state-' + prev).addClass('state-' + cur);
// 为文件对应的 <li> 元素($li绑定鼠标进入mouseenter事件处理函数当鼠标移入该元素时触发此函数
$li.on('mouseenter', function () {
// 当鼠标移入时,找到文件操作按钮所在的 <div> 元素($btns先调用stop方法停止正在进行的动画如果有的话避免动画队列堆积等问题然后调用animate方法触发一个动画效果将该元素的高度从当前值渐变到30像素实现鼠标移入时按钮区域展开显示的交互效果方便用户操作按钮
$btns.stop().animate({height: 30});
});
// 为文件对应的 <li> 元素($li绑定鼠标离开mouseleave事件处理函数当鼠标移出该元素时触发此函数
$li.on('mouseleave', function () {
// 当鼠标移出时,找到文件操作按钮所在的 <div> 元素($btns同样先调用stop方法停止正在进行的动画然后调用animate方法触发一个动画效果将该元素的高度从当前值渐变到0像素实现鼠标移出时按钮区域收缩隐藏的交互效果保持页面的简洁性和美观性
$btns.stop().animate({height: 0});
});
// 为文件操作按钮所在的 <div> 元素($btns绑定点击click事件处理函数并且通过第二个参数'span'指定只监听 <div> 元素内部的 <span> 元素(也就是各个具体的操作按钮)的点击事件
$btns.on('click', 'span', function () {
// 获取被点击的 <span> 元素也就是具体的操作按钮在其兄弟元素中的索引位置用于区分不同的按钮赋值给变量index例如索引为0可能是删除按钮索引为1可能是向右旋转按钮等
var index = $(this).index(),
deg;
// 根据按钮的索引index值进行不同的操作通过switch语句来区分不同的按钮点击情况
switch (index) {
// 如果索引为0说明点击的是第一个按钮通常是删除按钮之类的功能
case 0:
// 调用uploader对象WebUploader实例的removeFile方法传入当前文件对象file将该文件从上传队列中移除实现删除文件的功能
uploader.removeFile(file);
// 执行完删除操作后,直接返回,不再执行后续的代码,因为文件已经被删除,不需要再进行其他与该文件相关的操作了
return;
// 如果索引为1说明点击的是第二个按钮可能是向右旋转按钮之类的功能
case 1:
// 将文件的旋转角度file.rotation增加90度用于记录文件旋转的状态变化后续可能根据这个角度来实际旋转文件的展示效果比如图片旋转等
file.rotation += 90;
break;
// 如果索引为2说明点击的是第三个按钮可能是向左旋转按钮之类的功能
case 2:
// 将文件的旋转角度file.rotation减少90度同样是用于记录文件旋转的状态变化以便后续实现相应的展示效果调整
file.rotation -= 90;
break;
}
// 判断浏览器是否支持CSS过渡效果supportTransition为真表示支持如果支持
if (supportTransition) {
// 根据文件当前的旋转角度file.rotation构建一个CSS变换transform的旋转样式值格式为'rotate(' + file.rotation + 'deg)'用于后续设置元素的旋转效果赋值给变量deg
deg = 'rotate(' + file.rotation + 'deg)';
// 找到用于展示文件缩略图等的元素($wrap通过css方法设置其多个浏览器前缀版本的CSS变换属性-webkit-transform、-mos-transform、-o-transform以及标准的transform都设置为刚刚构建的旋转样式值deg从而实现在支持CSS过渡效果的浏览器中通过CSS变换来旋转文件展示元素比如图片达到视觉上的旋转效果
$wrap.css({
'-webkit-transform': deg,
'-mos-transform': deg,
'-o-transform': deg,
'transform': deg
});
} else {
// 如果浏览器不支持CSS过渡效果通过设置IE浏览器的滤镜filter属性来实现文件展示元素$wrap的旋转效果使用特定的IE滤镜语法'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')'其中通过一些数学运算来将文件的旋转角度转换为IE滤镜能识别的旋转参数值以实现在不支持CSS过渡效果的IE浏览器中也能进行文件展示元素的旋转操作虽然这种方式相对较旧且兼容性有限但用于应对旧版本IE浏览器的特殊情况
$wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')');
}
});
// 将文件对应的 <li> 元素($li插入到id为$filePickerBlock的元素之前这样可以调整文件展示元素在页面中的排列顺序例如将新添加的文件展示元素显示在文件选择相关区域之前等方便用户查看和操作文件相关信息
$li.insertBefore($filePickerBlock);
}
// 定义一个名为removeFile的函数用于销毁与文件相关的视图元素以及清理相关的数据等操作也就是负责文件相关视图的销毁工作
function removeFile(file) {
// 通过文件的id找到对应的 <li> 元素,赋值给变量$li后续将基于这个元素进行相关的销毁和清理操作
var $li = $('#' + file.id);
// 从percentages对象中删除以该文件的id为键的数据也就是移除记录该文件大小和进度等信息的数据项因为文件要被销毁了相关进度等信息不再需要保留
delete percentages[ file.id ];
// 调用updateTotalProgress函数用于更新总体上传进度相关的显示等情况在移除文件后及时更新整体的进度信息确保界面上显示的进度情况是准确的
updateTotalProgress();
// 对找到的 <li> 元素($li进行一系列操作先调用off方法移除该元素上绑定的所有事件处理函数避免内存泄漏以及不必要的事件触发等问题然后找到该元素内部的.file-panel类元素也就是文件操作按钮所在的 <div> 元素同样调用off方法移除其绑定的所有事件处理函数最后调用end方法回到最初的 <li> 元素并调用remove方法将该 <li> 元素从DOM树中移除彻底销毁与该文件相关的视图元素
$li.off().find('.file-panel').off().end().remove();
}
// 定义一个名为updateTotalProgress的函数用于更新文件上传的总体进度信息并根据进度情况更新界面上相关元素的显示内容如进度条的百分比显示等
function updateTotalProgress() {
// 初始化一个变量loaded用于记录已经上传的文件大小总和初始值设为0
var loaded = 0,
// 初始化一个变量total用于记录所有文件的总大小初始值设为0
total = 0,
// 通过jQuery选择器找到总体进度条$progress元素内部的所有子元素可能是用于展示进度文本和进度条宽度的元素等赋值给变量spans方便后续操作这些子元素来更新进度显示
spans = $progress.children(),
percent;
// 使用jQuery的each方法遍历percentages对象记录每个文件的大小和进度信息的对象对于每个键值对文件id作为键k文件大小和进度数组作为值v进行操作
$.each(percentages, function (k, v) {
// 将当前文件的大小v[0]累加到total变量中用于计算所有文件的总大小
total += v[ 0 ];
// 根据当前文件的大小v[0]和当前文件的上传进度v[1]计算已经上传的该文件的大小部分即文件大小乘以进度百分比并累加到loaded变量中用于计算所有文件已经上传的总大小
loaded += v[ 0 ] * v[ 1 ];
});
// 计算总体上传进度百分比通过判断总大小total是否为0来避免除数为0的情况如果总大小不为0则用已经上传的总大小loaded除以总大小total得到进度百分比否则进度百分比设为0
percent = total? loaded / total : 0;
// 找到总体进度条元素($progress的第一个子元素可能是用于展示进度百分比文本的元素调用text方法将计算得到的进度百分比转换为整数并拼接上 '%' 符号后设置为其文本内容,用于在界面上显示总体上传进度的百分比数值
spans.eq(0).text(Math.round(percent * 100) + '%');
// 找到总体进度条元素($progress的第二个子元素可能是用于展示进度条实际宽度的元素调用css方法设置其宽度样式属性将计算得到的进度百分比转换为整数并拼接上 '%' 符号后设置为宽度值,以通过改变宽度来直观展示总体上传进度的情况(例如进度条的填充长度等视觉效果)
spans.eq(1).css('width', Math.round(percent * 100) + '%');
// 调用updateStatus函数应该是用于更新文件上传相关的其他状态显示等情况的函数虽然此处未展示其具体代码但从函数名推测其功能在更新完进度信息后进一步更新其他相关的状态显示内容确保界面上展示的文件上传状态是完整且准确的
updateStatus();
}
// 定义一个名为setState的函数用于设置文件上传过程中的状态并根据不同状态进行相应的界面元素显示、隐藏以及样式调整等操作接收两个参数val表示要设置的目标状态值files参数此处从代码来看暂未明确具体使用方式但可能与文件相关比如特定的文件列表等
function setState(val, files) {
// 判断传入的要设置的目标状态值val与当前的状态state应该是在函数外部定义的用于记录当前文件上传状态的变量是否不相等如果不相等说明状态发生了变化需要执行相应的状态更新操作
if (val!= state) {
// 调用uploader对象WebUploader实例的getStats方法获取文件上传的统计信息比如已上传成功的文件数量、失败的文件数量等各种状态相关的数据并将结果赋值给变量stats用于后续根据不同状态判断并进行相应的界面操作
var stats = uploader.getStats();
// 移除上传按钮($upload上表示当前状态的类名格式为'state-' + statestate是之前的状态用于去除之前状态对应的样式以便后续添加新状态对应的样式
$upload.removeClass('state-' + state);
// 为上传按钮($upload添加表示目标状态val的类名格式为'state-' + val通过添加不同的类名可以应用不同的样式例如按钮的文本、颜色、可操作性等样式变化来体现当前文件上传所处的不同状态
$upload.addClass('state-' + val);
// 根据传入的目标状态值val进行不同的操作通过switch语句来区分不同的状态情况
switch (val) {
/* 未选择文件 */
case 'pedding':
// 为文件列表所在的元素($queue添加类名'element-invisible'这个类名可能在CSS中定义了相应的样式用于隐藏元素比如设置display:none或者visibility:hidden等使文件列表在未选择文件时隐藏起来符合此时的状态展示需求
$queue.addClass('element-invisible');
// 为状态栏元素($statusBar添加类名'element-invisible',同样使其隐藏起来,因为在未选择文件时,状态栏相关的进度、信息等展示可能不需要显示
$statusBar.addClass('element-invisible');
// 移除占位元素($placeHolder上的类名'element-invisible',也就是让占位元素显示出来,可能用于在未选择文件时展示一些提示用户选择文件之类的信息(例如“请选择要上传的文件”等提示语所在的元素)
$placeHolder.removeClass('element-invisible');
// 隐藏总体进度条元素($progress因为在未选择文件状态下不需要展示进度相关信息调用hide方法实现隐藏效果
$progress.hide();
// 隐藏文件总体选择信息元素($info同样此时不需要展示相关的文件选择等信息进行隐藏操作
$info.hide();
// 调用uploader对象WebUploader实例的refresh方法可能用于刷新WebUploader内部的一些状态或者界面相关的显示情况确保在状态切换时其内部状态与界面展示保持一致具体功能取决于WebUploader的实现逻辑
uploader.refresh();
break;
/* 可以开始上传 */
case 'ready':
// 为占位元素($placeHolder添加类名'element-invisible',使其隐藏起来,因为此时已经可以开始上传文件了,不需要再显示占位提示信息等内容
$placeHolder.addClass('element-invisible');
// 移除文件列表所在元素($queue的类名'element-invisible',让文件列表显示出来,方便用户查看已经添加到上传队列中的文件信息
$queue.removeClass('element-invisible');
// 移除状态栏元素($statusBar的类名'element-invisible',使状态栏显示出来,用于展示文件上传相关的进度、信息等内容
$statusBar.removeClass('element-invisible');
// 隐藏总体进度条元素($progress因为此时虽然可以上传但还未真正开始上传不需要展示进度情况先隐藏起来
$progress.hide();
// 显示文件总体选择信息元素($info用于展示如已选择文件的数量、大小等相关信息让用户了解当前的文件选择情况
$info.show();
// 设置上传按钮($upload的文本内容为lang.uploadStart预先定义好的国际化文本变量可能表示“开始上传”之类的提示语提示用户可以点击按钮进行文件上传操作了
$upload.text(lang.uploadStart);
// 调用uploader对象WebUploader实例的refresh方法刷新WebUploader内部状态及界面显示情况确保在进入可上传状态时相关展示是准确的
uploader.refresh();
break;
/* 上传中 */
case 'uploading':
// 显示总体进度条元素($progress因为文件正在上传需要展示上传的进度情况给用户调用show方法使其显示出来
$progress.show();
// 隐藏文件总体选择信息元素($info在上传过程中可能不需要展示文件选择相关信息了将其隐藏
$info.hide();
// 设置上传按钮($upload的文本内容为lang.uploadPause预先定义好的国际化文本变量可能表示“暂停上传”之类的提示语提示用户此时点击按钮可以暂停正在进行的文件上传操作
$upload.text(lang.uploadPause);
break;
/* 暂停上传 */
case 'paused':
// 显示总体进度条元素($progress虽然上传暂停了但仍可以展示之前已经上传的进度情况等信息所以使其显示出来
$progress.show();
// 隐藏文件总体选择信息元素($info同样在暂停状态下可能不需要展示该信息进行隐藏操作
$info.hide();
// 设置上传按钮($upload的文本内容为lang.uploadContinue预先定义好的国际化文本变量可能表示“继续上传”之类的提示语提示用户点击按钮可以继续之前暂停的文件上传操作
$upload.text(lang.uploadContinue);
break;
case 'confirm':
// 显示总体进度条元素($progress用于展示上传的进度情况调用show方法使其显示出来
$progress.show();
// 隐藏文件总体选择信息元素($info可能在这个确认状态下不需要展示该信息进行隐藏操作
$progress.show(); $info.hide();
// 设置上传按钮($upload的文本内容为lang.uploadStart预先定义好的国际化文本变量可能表示“开始上传”之类的提示语此处设置这个文本可能是根据业务逻辑在确认相关情况后可以再次开始上传之类的操作
$upload.text(lang.uploadStart);
// 再次获取文件上传的统计信息stats可能前面的操作过程中相关统计数据有变化重新获取最新数据用于后续判断
stats = uploader.getStats();
// 判断如果已经上传成功的文件数量stats.successNum大于0且上传失败的文件数量stats.uploadFailNum为0也就是所有文件都上传成功了的情况
if (stats.successNum &&!stats.uploadFailNum) {
// 调用setState函数传入'finish'作为状态值将文件上传状态设置为完成状态进入完成状态相关的界面展示和操作逻辑然后直接返回不再执行后续switch语句中的其他代码因为已经完成了状态的最终切换
setState('finish');
return;
}
break;
case 'finish':
// 隐藏总体进度条元素($progress因为文件上传已经完成不需要再展示进度信息了调用hide方法进行隐藏操作
$progress.hide();
// 显示文件总体选择信息元素($info可能用于展示一些如上传完成的提示信息或者最终的文件上传结果相关内容等调用show方法使其显示出来
$info.show();
// 判断如果上传失败的文件数量stats.uploadFailNum大于0也就是存在文件上传失败的情况
if (stats.uploadFailNum) {
// 设置上传按钮($upload的文本内容为lang.uploadRetry预先定义好的国际化文本变量可能表示“重试上传”之类的提示语提示用户可以点击按钮重新尝试上传失败的文件
$upload.text(lang.uploadRetry);
} else {
// 如果没有文件上传失败,设置上传按钮($upload的文本内容为lang.uploadStart预先定义好的国际化文本变量可能表示“开始上传”之类的提示语可能用于提示用户可以继续上传新的文件等操作具体根据业务逻辑而定
$upload.text(lang.uploadStart);
}
break;
}
// 将当前的状态state更新为传入的目标状态值val确保记录的状态与实际设置的状态保持一致方便后续其他函数根据这个状态变量进行相应的操作判断
state = val;
// 调用updateStatus函数应该是用于更新文件上传相关的其他一些状态显示、界面调整等操作的函数虽然此处未展示其具体代码但从函数名推测其功能在状态更新后进一步确保整个文件上传界面展示的状态是完整且准确的
updateStatus();
}
// 判断当前实例对象_this通过调用getQueueCount方法获取的上传队列中的文件数量是否为0如果是0表示上传队列中没有文件
if (!_this.getQueueCount()) {
// 如果上传队列中没有文件,为上传按钮($upload添加类名'disabled'这个类名可能在CSS中定义了相应的样式比如设置按钮为不可点击状态、改变按钮颜色等外观样式来表示不可用用于提示用户当前无法进行上传操作因为没有文件在队列中等待上传
$upload.addClass('disabled')
} else {
// 如果上传队列中文件数量不为0也就是有文件在队列中等待上传移除上传按钮$upload上的类名'disabled',使按钮恢复可操作的正常样式(例如可以点击进行上传等操作)
$upload.removeClass('disabled')
}
// 定义一个名为updateStatus的函数用于更新文件上传相关的状态信息展示内容比如在页面上的特定元素中显示不同状态下的提示文本告知用户当前文件上传的进展、结果等情况
function updateStatus() {
// 初始化一个变量text用于存储要展示的状态信息文本内容初始为空字符串后续会根据不同的文件上传状态进行相应的文本拼接和替换操作来生成最终要展示的文本
var text = '', stats;
// 判断当前文件上传状态state是否为'ready'(表示可以开始上传的状态)
if (state === 'ready') {
// 如果是'ready'状态使用lang.updateStatusReady预先定义好的国际化文本变量应该是包含占位符的文本模板用于展示准备上传状态相关信息通过replace方法将其中的'_'占位符替换为实际的已添加到队列中的文件数量fileCount再将'_KB'占位符替换为通过WebUploader.formatSize方法应该是WebUploader提供的用于格式化文件大小显示格式的函数格式化后的文件总大小fileSize最终得到符合当前状态且展示具体文件数量和总大小信息的文本内容赋值给text变量
text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize));
} else if (state === 'confirm') {
// 如果当前文件上传状态是'confirm'可能表示某种确认状态例如确认上传结果等情况先获取文件上传的统计信息通过调用uploader.getStats方法并将结果赋值给stats变量用于后续判断上传成功和失败的文件数量等情况
stats = uploader.getStats();
// 判断如果上传失败的文件数量stats.uploadFailNum大于0也就是存在文件上传失败的情况
if (stats.uploadFailNum) {
// 使用lang.updateStatusConfirm同样是预先定义好的国际化文本变量包含占位符的文本模板用于展示确认状态相关信息通过replace方法将其中的'_'占位符替换为实际的上传成功的文件数量stats.successNum这里替换了两次可能根据具体文本模板的格式需求来准确展示相关信息最终生成符合当前状态且体现上传成功文件数量的文本内容赋值给text变量
text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum);
}
} else {
// 如果当前文件上传状态不是'ready'也不是'confirm'也就是其他状态情况例如完成状态等先获取文件上传的统计信息调用uploader.getStats方法并将结果赋值给stats变量
stats = uploader.getStats();
// 使用lang.updateStatusFinish预先定义好的国际化文本变量包含占位符的文本模板用于展示完成状态相关信息通过replace方法依次进行占位符替换操作
// 将第一个'_'占位符替换为实际的已添加到队列中的文件数量fileCount
// 将'_KB'占位符替换为通过WebUploader.formatSize方法格式化后的文件总大小fileSize
// 将第二个'_'占位符替换为实际的上传成功的文件数量stats.successNum
// 经过这些替换操作后生成符合当前状态且展示文件数量、总大小以及上传成功文件数量等信息的文本内容赋值给text变量
text = lang.updateStatusFinish.replace('_', fileCount).
replace('_KB', WebUploader.formatSize(fileSize)).
replace('_', stats.successNum);
// 判断如果上传失败的文件数量stats.uploadFailNum大于0也就是存在文件上传失败的情况
if (stats.uploadFailNum) {
// 将预先定义好的用于展示错误信息的国际化文本变量lang.updateStatusError同样包含占位符的文本模板用于在有文件上传失败时补充相关错误信息通过replace方法将其中的'_'占位符替换为实际的上传失败的文件数量stats.uploadFailNum然后将生成的包含失败文件数量的错误提示文本追加到之前生成的text变量内容后面用于完整展示包含上传成功和失败文件数量等详细情况的最终状态信息文本
text += lang.updateStatusError.replace('_', stats.uploadFailNum);
}
}
// 找到用于展示文件总体选择信息的元素($info通过html方法将刚刚生成的text变量中的文本内容设置为该元素的HTML内容从而在页面上相应位置展示出更新后的文件上传状态信息让用户了解当前的上传情况
$info.html(text);
}
// 为uploader对象WebUploader实例绑定'fileQueued'事件处理函数当有单个文件添加到上传队列时会触发该函数传入添加的文件对象file作为参数用于处理文件添加到队列后的相关操作比如更新文件数量、文件总大小等信息以及创建文件对应的视图展示元素等
uploader.on('fileQueued', function (file) {
// 判断文件的扩展名file.ext是否存在并且文件的扩展名转换为小写形式后在允许上传的文件扩展名列表acceptExtensions中是否能找到indexOf方法返回值不为 -1表示存在同时判断文件大小file.size是否小于等于允许上传的单个文件最大大小限制fileMaxSize也就是检查文件是否符合上传要求
if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase())!= -1 && file.size <= fileMaxSize) {
// 如果文件符合上传要求将记录已添加到队列中的文件数量的变量fileCount加1用于统计上传队列中的文件数量变化情况
fileCount++;
// 将当前文件的大小file.size累加到记录文件总大小的变量fileSize用于实时更新所有已添加到队列中的文件的总大小情况
fileSize += file.size;
}
// 判断如果上传队列中的文件数量fileCount等于1也就是刚刚添加了第一个符合要求的文件到队列中时
if (fileCount === 1) {
// 为占位元素($placeHolder可能是在还未添加文件时显示提示用户选择文件等信息的元素添加类名'element-invisible',使其隐藏起来,因为已经有文件添加到队列了,不需要再显示占位提示信息了
$placeHolder.addClass('element-invisible');
// 显示状态栏元素($statusBar用于展示文件上传相关的进度、信息等内容使其显示出来方便用户查看文件上传相关的情况因为有文件在队列中了需要展示相应的状态信息了
$statusBar.show();
}
// 调用addFile函数之前定义的用于创建与文件对应的视图展示元素等操作的函数传入当前添加的文件对象file为该文件创建相应的展示元素如文件名称、进度条、操作按钮等元素并添加到页面中方便用户查看和操作该文件
addFile(file);
});
// 为uploader对象WebUploader实例绑定'fileDequeued'事件处理函数当有单个文件从上传队列中移除时会触发该函数传入被移除的文件对象file作为参数用于处理文件移除后的相关操作比如更新文件数量、文件总大小等信息以及销毁文件对应的视图展示元素等
uploader.on('fileDequeued', function (file) {
// 判断文件的扩展名file.ext是否存在并且文件的扩展名转换为小写形式后在允许上传的文件扩展名列表acceptExtensions中是否能找到indexOf方法返回值不为 -1表示存在同时判断文件大小file.size是否小于等于允许上传的单个文件最大大小限制fileMaxSize也就是检查被移除的这个文件是否原本是符合上传要求的文件进行相应的数量和大小统计调整时需要确认是符合要求的文件
if (file.ext && acceptExtensions.indexOf(file.ext.toLowerCase())!= -1 && file.size <= fileMaxSize) {
// 如果被移除的文件符合上传要求将记录已添加到队列中的文件数量的变量fileCount减1用于统计上传队列中的文件数量变化情况因为有文件被移除了
fileCount--;
// 将当前文件的大小file.size从记录文件总大小的变量fileSize中减去用于实时更新所有已添加到队列中的文件的总大小情况因为有文件的大小需要从总大小中扣除了
fileSize -= file.size;
}
// 调用removeFile函数之前定义的用于销毁文件相关视图元素以及清理相关数据等操作的函数传入当前被移除的文件对象file执行销毁文件对应展示元素、清理相关数据如移除记录该文件进度等信息的数据项等操作确保页面展示和相关数据与实际队列情况一致
removeFile(file);
// 调用updateTotalProgress函数之前定义的用于更新文件上传的总体进度信息以及相关界面显示的函数在文件移除后及时更新整体的进度信息以及相应的界面展示情况保证展示给用户的上传进度等信息是准确的
updateTotalProgress();
});
// 为uploader对象WebUploader实例绑定'filesQueued'事件处理函数当有多个文件添加到上传队列时会触发该函数传入添加的文件对象file作为参数虽然这里参数名和单个文件添加时一样但实际传入的可能是多个文件组成的集合之类的情况具体取决于WebUploader的实现方式用于处理多个文件添加到队列后的相关状态判断和操作比如根据当前状态判断是否可以切换到可上传状态等情况
uploader.on('filesQueued', function (file) {
// 判断uploader对象WebUploader实例当前是否正在进行上传操作通过调用isInProgress方法判断返回false表示不在进行中并且当前文件上传状态state是'pedding'(未选择文件状态)、'finish'(完成状态)、'confirm'(确认状态)或者'ready'(可开始上传状态)中的任意一种情况,也就是判断在合适的状态下且当前没有正在上传时,有新文件添加进来的情况
if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) {
// 如果满足上述条件调用setState函数传入'ready'作为状态值,将文件上传状态设置为可以开始上传的状态,方便用户能及时进行上传操作,更新相关的界面元素显示和状态信息展示等情况
setState('ready');
}
// 调用updateTotalProgress函数在多个文件添加到队列后及时更新文件上传的总体进度信息以及相应的界面展示情况确保展示给用户的进度等信息是准确的反映最新的文件队列情况
updateTotalProgress();
});
// 为uploader对象WebUploader实例绑定'all'事件处理函数,'all'事件会在多种不同的上传相关事件触发时都会被调用传入事件类型type和相关文件对象files可能是单个文件对象或者多个文件对象组成的集合取决于具体触发的事件情况作为参数用于根据不同的具体事件类型执行相应的操作
uploader.on('all', function (type, files) {
// 根据传入的事件类型type进行不同的操作通过switch语句来区分不同的事件情况
switch (type) {
// 如果事件类型是'uploadFinished',表示文件上传已经全部完成(所有文件都完成了上传操作)
case 'uploadFinished':
// 调用setState函数传入'confirm'作为状态值同时传入相关文件对象files将文件上传状态设置为确认状态可能用于后续确认上传结果、进行相关统计等操作并根据这个状态切换来更新界面元素显示、状态信息展示等情况
setState('confirm', files);
break;
// 如果事件类型是'startUpload',表示开始上传文件操作即将启动
case 'startUpload':
/* 添加额外的GET参数 */
// 通过调用utils对象的serializeParam函数应该是用于序列化参数的自定义函数传入editor对象的queryCommandValue方法获取'serverparam'命令对应的值可能是一些自定义的服务器端相关参数将返回结果赋值给params变量如果返回结果为空也就是没有获取到参数则params为空字符串用于后续构建包含额外参数的上传URL
var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '',
// 通过调用utils对象的formatUrl函数应该是用于格式化URL的自定义函数构建一个新的上传URL地址在原有的actionUrl文件上传的基础目标URL地址基础上根据其是否已经包含查询字符串通过判断是否存在'?'来确定),添加合适的连接符号(如果没有查询字符串则添加'?',已有则添加'&'),然后拼接上固定的'encode=utf-8&'以及前面获取到的参数params最终生成包含额外GET参数的完整上传URL地址赋值给url变量
url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1? '?':'&') + 'encode=utf-8&' + params);
// 调用uploader对象WebUploader实例的option方法传入'server'作为配置项名称将前面构建好的包含额外参数的上传URL地址url设置为新的文件上传服务器地址用于实际的文件上传请求将按照这个更新后的URL进行发送
uploader.option('server', url);
// 调用setState函数传入'uploading'作为状态值同时传入相关文件对象files将文件上传状态设置为正在上传状态并且根据这个状态切换来更新界面元素显示比如显示进度条等、状态信息展示等情况告知用户文件正在上传过程中
setState('uploading', files);
break;
// 如果事件类型是'stopUpload',表示文件上传操作被停止(例如用户点击了暂停按钮等情况导致上传停止)
case 'stopUpload':
// 调用setState函数传入'paused'作为状态值同时传入相关文件对象files将文件上传状态设置为暂停状态然后根据这个状态切换来更新界面元素显示比如保持进度条显示等、状态信息展示等情况提示用户上传已暂停可进行相应操作如继续上传等
setState('paused', files);
break;
}
});
// 为uploader对象WebUploader实例绑定'uploadBeforeSend'事件处理函数当在文件上传即将发送请求之前会触发该函数传入即将上传的文件对象file、用于存放POST请求参数的数据对象data可在这个对象中添加额外的POST参数以及请求头对象header可用于设置请求头相关的信息作为参数用于在上传前进行一些请求相关的配置操作
uploader.on('uploadBeforeSend', function (file, data, header) {
// 这里可以通过data对象添加POST参数也就是在文件上传前如果有需要向服务器端传递额外的POST数据可以在这个函数内部操作data对象来添加相应的参数信息具体添加哪些参数根据业务需求而定
// 判断文件上传的目标URL地址actionUrl转换为小写形式后是否包含'jsp'字符串如果包含indexOf方法返回值不为 -1说明可能是向JSP相关的服务器端接口上传文件
if (actionUrl.toLowerCase().indexOf('jsp')!= -1) {
// 如果是向JSP相关的服务器端接口上传文件在请求头对象header中添加一个名为'X_Requested_With'的属性,设置其值为'XMLHttpRequest'这是一种常见的设置用于标识该请求是通过XMLHttpRequest方式发起的可能用于服务器端识别请求来源或者进行相应的处理逻辑判断等情况
header['X_Requested_With'] = 'XMLHttpRequest';
}
});
// 为uploader对象WebUploader实例绑定'uploadProgress'事件处理函数在文件上传过程中当某个文件的上传进度有更新时会触发该函数传入正在上传的文件对象file以及该文件当前的上传进度百分比percentage作为参数用于更新界面上该文件的进度条显示以及整体的上传进度统计等相关信息
uploader.on('uploadProgress', function (file, percentage) {
// 通过文件的id找到对应的 <li> 元素(也就是该文件在页面上对应的整个展示元素),赋值给变量$li方便后续操作该元素内部的进度条相关元素来更新显示
var $li = $('#' + file.id),
// 通过jQuery选择器在找到的 <li> 元素($li中查找类名为'progress'的 <p> 元素内部的 <span> 元素(也就是用于展示该文件上传进度条的具体元素),赋值给变量$percent用于后续操作该进度条元素来更新其宽度等样式以体现文件上传进度的变化
$percent = $li.find('.progress span');
// 通过css方法设置找到的进度条元素$percent的宽度样式属性将传入的上传进度百分比percentage乘以100并拼接上 '%' 符号后设置为宽度值,这样进度条的宽度就会根据文件上传进度按比例进行变化,直观地展示给用户文件当前的上传进度情况
$percent.css('width', percentage * 100 + '%');
// 将当前文件在percentages对象用于记录每个文件的大小和进度信息的对象中对应的进度值数组中的第二个元素更新为传入的当前上传进度百分比percentage确保记录的文件进度信息是最新的方便后续计算总体上传进度等操作使用
percentages[ file.id ][ 1 ] = percentage;
// 调用updateTotalProgress函数之前定义的用于更新文件上传的总体进度信息以及相关界面显示的函数在单个文件上传进度更新后及时更新整体的上传进度情况以及相应的界面展示比如总体进度条的显示等保证展示给用户的上传进度信息是准确且实时更新的
updateTotalProgress();
});
// 为uploader对象WebUploader实例绑定'uploadSuccess'事件处理函数当某个文件上传成功后会触发该函数传入上传成功的文件对象file以及服务器端返回的响应数据ret包含了服务器端返回的关于该文件上传结果等相关信息作为参数用于根据服务器端返回的结果进行相应的界面提示、数据记录等操作
uploader.on('uploadSuccess', function (file, ret) {
// 通过文件的id找到对应的 <li> 元素(也就是该文件在页面上对应的整个展示元素),赋值给变量$file方便后续操作该元素进行相应的界面更新操作等
var $file = $('#' + file.id);
try {
// 尝试获取服务器端返回的响应数据中的原始数据ret._raw如果存在的话如果不存在则直接使用整个响应数据ret将获取到的数据赋值给responseText变量用于后续解析操作
var responseText = (ret._raw || ret),
// 通过调用utils对象的str2json函数应该是用于将字符串转换为JSON对象的自定义函数将前面获取到的响应数据文本responseText转换为JSON对象赋值给json变量方便后续根据JSON对象中的具体属性来判断上传结果等情况
json = utils.str2json(responseText);
// 判断转换后的JSON对象json中的'state'属性值是否为'SUCCESS',也就是判断服务器端返回的结果表示文件上传是否成功
if (json.state == 'SUCCESS') {
// 如果文件上传成功将服务器端返回的JSON对象json包含了文件相关的详细信息等添加到当前实例对象_this的fileList属性用于记录上传成功的文件相关信息的数组方便后续对上传成功的文件数据进行统一管理和使用
_this.fileList.push(json);
// 在找到的文件对应的 <li> 元素($file内部添加一个类名为'success'的 <span> 元素,可能用于在页面上展示一个表示文件上传成功的标识(比如一个成功图标之类的元素),给用户一个直观的提示,告知该文件已成功上传
$file.append('<span class="success"></span>');
} else {
// 如果服务器端返回的结果表示文件上传不成功json.state不是'SUCCESS'通过jQuery选择器在找到的文件对应的 <li> 元素($file中查找类名为'error'的元素可能是用于展示文件错误信息的元素调用text方法将JSON对象json中的'state'属性值也就是服务器端返回的错误提示等相关信息设置为该元素的文本内容然后调用show方法使其显示出来在页面上展示出文件上传失败的具体错误信息告知用户该文件上传出现问题了
$file.find('.error').text(json.state).show();
}
} catch (e) {
// 如果在尝试解析服务器端返回的响应数据或者进行其他相关操作时出现了异常比如数据格式不符合预期等情况导致转换JSON对象失败等通过jQuery选择器在找到的文件对应的 <li> 元素($file中查找类名为'error'的元素调用text方法将预先定义好的表示服务器端上传错误的国际化文本变量lang.errorServerUpload设置为该元素的文本内容然后调用show方法使其显示出来在页面上展示出一个通用的服务器端上传错误提示信息告知用户文件上传出现问题了但具体原因由于解析异常无法准确展示
$file.find('.error').text(lang.errorServerUpload).show();
}
});
// 为uploader对象WebUploader实例绑定'uploadError'事件处理函数当某个文件上传出现错误时会触发该函数传入出现错误的文件对象file以及错误代码code可能是WebUploader内部定义的用于标识不同类型错误的代码作为参数不过此处函数体为空可能后续需要根据具体的错误情况添加相应的处理逻辑比如提示用户具体错误原因、进行重试等操作
uploader.on('uploadError', function (file, code) {
});
// 为uploader对象WebUploader实例绑定'error'事件处理函数当出现全局的上传相关错误时会触发该函数传入错误代码code标识错误类型以及可能涉及的文件对象file作为参数用于处理一些全局性质的上传错误情况
uploader.on('error', function (code, file) {
// 判断错误代码code是否是'Q_TYPE_DENIED'(可能表示文件类型被拒绝,也就是上传的文件类型不符合要求)或者'F_EXCEED_SIZE'(可能表示文件大小超出限制)这两种情况之一
if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') {
// 如果是文件类型不符合要求或者文件大小超出限制这两种错误情况之一调用addFile函数之前定义的用于创建与文件对应的视图展示元素等操作的函数传入出现错误的文件对象file重新创建该文件对应的展示元素可能用于在页面上再次展示该文件以及对应的错误提示信息等情况让用户能清楚看到是哪个文件出现了什么类型的错误
addFile(file);
}
});
// 为uploader对象WebUploader实例绑定'uploadComplete'事件处理函数当某个文件完成了整个上传流程无论成功还是失败后会触发该函数传入完成上传流程的文件对象file以及服务器端返回的响应数据ret作为参数不过此处函数体为空可能后续需要根据具体业务需求添加相应的处理逻辑比如进行一些清理操作、记录最终结果等情况
uploader.on('uploadComplete', function (file, ret) {
});
// 为上传按钮($upload绑定点击click事件处理函数当用户点击上传按钮时会触发该函数用于根据当前文件上传的状态来执行相应的操作比如开始上传、暂停上传等操作
$upload.on('click', function () {
// 判断上传按钮($(this)在事件处理函数中this指向被点击的按钮元素通过jQuery包装后进行判断是否包含类名'disabled',如果包含该类名,表示按钮当前处于不可用状态(例如上传队列中没有文件时设置的不可点击状态等情况)
if ($(this).hasClass('disabled')) {
// 如果按钮处于不可用状态直接返回false阻止后续默认的点击事件行为比如阻止按钮的表单提交等默认行为在这里就是不让用户进行无效的点击操作
return false;
}
// 判断当前文件上传状态state是否为'ready',即是否处于可以开始上传的状态
if (state === 'ready') {
// 如果是'ready'状态调用uploader对象WebUploader实例的upload方法触发文件上传操作开始将上传队列中的文件发送到服务器端进行上传
uploader.upload();
} else if (state === 'paused') {
// 判断当前文件上传状态是否为'paused',即是否处于暂停上传的状态
// 如果是'paused'状态同样调用uploader对象的upload方法用于在暂停后继续进行文件上传操作恢复文件的上传流程
uploader.upload();
} else if (state === 'uploading') {
// 判断当前文件上传状态是否为'uploading',即是否处于正在上传文件的状态
// 如果是'uploading'状态调用uploader对象的uploader.stop方法用于暂停正在进行的文件上传操作停止向服务器发送文件数据等上传行为
uploader.stop();
}
});
// 为上传按钮($upload添加表示当前文件上传状态state的类名格式为'state-' + state通过添加这个类名可以应用相应的样式例如按钮的外观、可操作性等样式变化来体现当前文件上传所处的状态情况
$upload.addClass('state-' + state);
// 调用updateTotalProgress函数之前定义的用于更新文件上传的总体进度信息以及相关界面显示的函数在按钮相关操作完成后比如点击按钮开始、暂停上传等操作后及时更新整体的上传进度情况以及相应的界面展示保证展示给用户的上传进度信息是准确的
updateTotalProgress();
},
// 定义一个名为getQueueCount的函数用于获取当前处于可上传状态比如已添加到队列中等待上传、正在上传、上传进度中这些状态的文件都算可上传状态的文件的文件数量是当前实例对象的一个方法
getQueueCount: function () {
// 初始化几个变量file用于在循环中临时存储每个文件对象i作为循环计数器status用于存储文件的状态readyFile用于统计处于可上传状态的文件数量初始值设为0files通过调用this.uploader当前实例对应的WebUploader实例的getFiles方法获取所有已添加到WebUploader实例中的文件对象列表用于后续遍历判断文件状态
var file, i, status, readyFile = 0, files = this.uploader.getFiles();
// 使用一个特殊的for循环语法在循环条件中进行赋值操作从files列表中依次取出每个文件对象赋值给file变量并同时递增循环计数器i只要file变量能获取到有效的文件对象也就是files列表还没遍历完就会继续循环
for (i = 0; file = files[i++]; ) {
// 获取当前文件file的状态通过调用file对象的getStatus方法获取将获取到的状态赋值给status变量用于后续判断该文件是否处于可上传状态
status = file.getStatus();
// 判断文件的状态status是否是'queued'(已添加到队列中等待上传)、'uploading'(正在上传)或者'progress'上传进度中这几种可上传相关的状态之一如果是则将统计可上传状态文件数量的变量readyFile加1
if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++;
}
// 返回统计得到的处于可上传状态的文件数量readyFile以便其他地方可以获取并根据这个数量进行相应的操作比如判断是否有文件可上传来决定上传按钮是否可用等情况
return readyFile;
},
// 定义一个名为getInsertList的函数用于获取要插入的文件列表信息可能是用于后续在某个编辑器或者其他地方插入文件相关的链接、标题等信息是当前实例对象的一个方法
getInsertList: function () {
// 初始化几个变量i作为循环计数器link用于存储文件的链接地址data用于临时存储每个文件相关的数据对象list用于存储最终要返回的文件列表信息初始化为一个空数组prefix通过调用editor对象的getOpt方法获取'fileUrlPrefix'配置项的值(可能是文件链接的前缀地址,用于拼接完整的文件访问地址)
var i, link, data, list = [],
prefix = editor.getOpt('fileUrlPrefix');
// 使用for循环遍历当前实例对象this的fileList属性用于记录上传成功的文件相关信息的数组循环从0开始每次递增1直到遍历完所有元素
for (i = 0; i < this.fileList.length; i++) {
// 获取当前索引位置对应的文件相关数据对象赋值给data变量方便后续提取文件的相关信息如链接、标题等
data = this.fileList[i];
// 获取文件相关数据对象data中的文件链接地址url属性赋值给link变量用于后续构建要插入的文件信息中的链接部分
link = data.url;
// 将一个包含文件标题和链接的对象添加到list数组中文件标题优先取data.original属性可能是文件原始名称之类的更合适的标题信息如果不存在则取文件链接地址link中以'/'分割后的最后一部分也就是文件名部分作为标题文件链接则通过将获取到的前缀prefix和文件链接地址link进行拼接得到完整的可访问地址这样构建好的对象就包含了要插入的文件的标题和完整链接信息
list.push({
title: data.original || link.substr(link.lastIndexOf('/') + 1),
url: prefix + link
});
}
// 返回构建好的包含要插入的文件标题和链接信息的列表list以便其他地方比如编辑器相关的插入文件操作处可以获取并使用这些信息进行相应的文件插入操作
return list;
}
};
/* 在线附件 */
// 定义一个名为OnlineFile的构造函数用于创建与在线文件相关的对象实例接收一个参数target用于指定相关的DOM元素或者元素的标识等信息该函数是创建在线文件相关功能的入口
function OnlineFile(target) {
// 判断传入的target参数是否为字符串类型如果是字符串类型则通过document.getElementById方法根据该字符串当作元素的id获取对应的DOM元素否则直接将传入的参数当作已经获取到的DOM元素进行赋值最终将获取到的元素赋值给this.container属性用于后续操作中代表与在线文件相关的容器元素
this.container = utils.isString(target)? document.getElementById(target) : target;
// 调用init方法用于进行一些初始化操作比如初始化容器、事件绑定、数据初始化等相关设置启动在线文件相关功能的初始化流程
this.init();
}
// 为OnlineFile构造函数的原型对象添加属性和方法这样通过该构造函数创建的所有实例对象都可以共享这些属性和方法实现在线文件相关功能的具体逻辑定义
OnlineFile.prototype = {
// 定义init方法作为在线文件相关功能初始化的总入口会依次调用其他几个初始化子函数完成诸如容器初始化、事件绑定、初始数据准备等各项初始化操作
init: function () {
// 调用initContainer方法用于初始化与在线文件相关的容器元素比如创建文件列表展示的DOM结构等操作
this.initContainer();
// 调用initEvents方法用于初始化与在线文件相关的事件处理逻辑比如滚动事件等方便用户在操作在线文件时有相应的交互效果
this.initEvents();
// 调用initData方法用于初始化在线文件相关的数据可能是加载初始的文件列表数据等操作具体根据业务需求而定
this.initData();
},
/* 初始化容器 */
initContainer: function () {
// 将this.container代表与在线文件相关的容器元素的innerHTML属性设置为空字符串也就是清空该容器元素内部原有的所有内容用于重新构建与在线文件展示相关的DOM结构
this.container.innerHTML = '';
// 创建一个 <ul> 元素用于作为在线文件列表的外层容器元素将其赋值给this.list属性方便后续向其中添加具体的文件列表项等操作
this.list = document.createElement('ul');
// 创建一个 <li> 元素用于可能的清除浮动等样式相关操作比如在一些布局中通过添加这个元素来确保父元素能正确撑开高度等情况将其赋值给this.clearFloat属性后续会将其添加到文件列表中用于布局相关目的
this.clearFloat = document.createElement('li');
// 使用domUtils对象的addClass方法可能是自定义的添加类名函数为创建的文件列表元素this.list添加类名'list'用于通过CSS样式来设置文件列表的外观、布局等样式效果
domUtils.addClass(this.list, 'list');
// 使用domUtils对象的addClass方法为创建的用于清除浮动的元素this.clearFloat添加类名'clearFloat'同样是为了通过CSS样式来实现相应的布局效果比如清除浮动相关的样式规则应用到这个元素上
domUtils.addClass(this.clearFloat, 'clearFloat');
// 将用于清除浮动的元素this.clearFloat添加到文件列表元素this.list使其成为文件列表的子元素符合相应的布局结构要求
this.list.appendChild(this.clearFloat);
// 将包含了清除浮动元素的文件列表元素this.list添加到与在线文件相关的容器元素this.container完成在线文件列表展示的基本DOM结构搭建后续可以向文件列表中添加具体的文件项等内容
this.container.appendChild(this.list);
},
/* 初始化滚动事件,滚动到地步自动拉取数据 */
initEvents: function () {
// 将当前实例对象this赋值给变量_this用于在后续一些闭包环境中能正确访问到当前实例对象的属性和方法避免this指向问题导致的错误
var _this = this;
/* 滚动拉取图片 */
// 使用domUtils对象的on方法可能是自定义的事件绑定函数为id为'fileList'的元素可能就是前面初始化的文件列表所在元素或者相关的滚动容器元素绑定滚动scroll事件处理函数当该元素发生滚动时会触发此函数传入事件对象e作为参数
domUtils.on($G('fileList'), 'scroll', function(e){
// 将触发滚动事件的元素this在事件处理函数中this指向触发事件的DOM元素也就是绑定了滚动事件的那个元素赋值给变量panel方便后续操作该元素获取相关的滚动属性等信息
var panel = this;
// 判断文件列表容器元素panel的滚动高度scrollHeight表示整个可滚动内容的高度减去元素的可视高度offsetHeight加上已经滚动的距离scrollTop是否小于10像素也就是判断是否滚动到了容器元素的底部附近这里设定10像素的差值作为接近底部的判断条件
if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) {
// 如果滚动到了容器底部附近调用当前实例对象_this的getFileData方法应该是用于获取更多在线文件数据的函数虽然此处未展示其具体代码但从函数名推测其功能实现自动拉取更多在线文件数据的功能以满足用户滚动查看更多文件的需求
_this.getFileData();
}
});
/* 选中图片 */
// 使用domUtils对象的on方法可能是自定义的事件绑定函数为当前实例对象this的list属性所代表的元素应该是在线文件列表的DOM元素绑定点击click事件处理函数当用户点击文件列表中的元素时会触发该函数传入事件对象e作为参数用于处理图片选中相关的交互逻辑
domUtils.on(this.list, 'click', function (e) {
// 获取触发点击事件的实际目标元素兼容不同浏览器获取方式e.target适用于标准浏览器e.srcElement适用于IE浏览器将其赋值给变量target方便后续操作判断点击的具体元素是什么
var target = e.target || e.srcElement,
// 获取目标元素target的父节点元素也就是所在的 <li> 元素,假设文件列表中的每个文件项是用 <li> 元素包裹的赋值给变量li用于后续判断是否点击的是文件列表项元素以及进行相应的选中样式处理等操作
li = target.parentNode;
// 判断获取到的父节点元素li的标签名tagName转换为小写形式后是否等于'li',也就是确认点击的目标元素的父元素确实是文件列表中的 <li> 元素(用于排除点击到其他不符合要求的元素的情况)
if (li.tagName.toLowerCase() == 'li') {
// 判断该 <li> 元素li是否已经包含类名'selected'(可能表示该文件项已被选中的样式类名),如果包含
if (domUtils.hasClass(li, 'selected')) {
// 使用domUtils对象的removeClasses方法可能是自定义的移除类名函数从该 <li> 元素li中移除'selected'类名,也就是取消该文件项的选中状态,对应的样式效果(比如选中时的背景色等样式)会消失
domUtils.removeClasses(li, 'selected');
} else {
// 如果该 <li> 元素li不包含'selected'类名也就是当前未被选中使用domUtils对象的addClass方法可能是自定义的添加类名函数为该 <li> 元素li添加'selected'类名,使其变为选中状态,显示出相应的选中样式效果
domUtils.addClass(li, 'selected');
}
}
});
},
/* 初始化第一次的数据 */
initData: function () {
// 以下是拉取数据需要使用到的几个变量的初始化,用于记录在线文件数据拉取相关的状态、数量、索引等信息
/* 拉取数据需要使用的值 */
// 初始化一个变量state用于记录当前数据拉取的状态初始值设为0具体含义可能根据业务逻辑确定比如0表示初始状态后续可能根据不同阶段有不同的值来表示不同的数据拉取情况等
this.state = 0;
// 通过调用editor对象的getOpt方法获取'fileManagerListSize'配置项的值可能表示每次拉取在线文件列表数据的数量大小限制并赋值给this.listSize变量用于确定每次向后台请求获取的文件数量
this.listSize = editor.getOpt('fileManagerListSize');
// 初始化一个变量this.listIndex用于记录当前已经拉取的数据在整个数据集中的索引位置初始值设为0表示从最开始的位置开始拉取数据后续会根据实际拉取情况进行更新
this.listIndex = 0;
// 初始化一个变量this.listEnd用于标记是否已经拉取到了所有的在线文件数据初始值设为false表示还未拉取完所有数据当拉取完所有数据后会将其设置为true
this.listEnd = false;
/* 第一次拉取数据 */
// 调用this.getFileData方法用于向后台拉取图片列表数据的函数开始进行第一次在线文件数据的拉取操作获取初始的文件列表数据并展示在页面上后续根据滚动等操作可能会继续拉取更多数据
this.getFileData();
},
/* 向后台拉取图片列表数据 */
getFileData: function () {
// 将当前实例对象this赋值给变量_this用于在后续一些闭包环境中能正确访问到当前实例对象的属性和方法避免this指向问题导致的错误
var _this = this;
// 判断当前是否还未拉取完所有数据_this.listEnd为false并且当前是否不在加载数据的过程中!this.isLoadingDataisLoadingData变量可能用于标记是否正在进行数据请求加载操作只有这两个条件都满足时才执行后续的数据拉取操作避免重复请求或者在数据还未加载完时又发起新请求等情况
if (!_this.listEnd &&!this.isLoadingData) {
// 如果满足条件将表示正在加载数据的变量this.isLoadingData设置为true标记当前开始进入数据加载状态防止其他地方同时触发数据拉取操作
this.isLoadingData = true;
// 使用ajax对象可能是自定义的用于发送异步请求的对象或者基于某个库的请求对象的request方法发起一个GET请求向后台服务器获取在线文件图片列表数据传入请求的URL地址以及一些配置参数对象作为参数
ajax.request(editor.getActionUrl(editor.getOpt('fileManagerActionName')), {
// 设置请求的超时时间为100000毫秒也就是100秒如果请求在这个时间内没有响应则会触发超时处理逻辑防止请求长时间无响应导致页面卡顿等问题
timeout: 100000,
// 设置请求携带的数据通过调用utils对象的extend方法可能是用于合并对象的自定义函数将一个包含起始索引start使用this.listIndex变量的值表示从哪个位置开始拉取数据和拉取数量size使用this.listSize变量的值表示每次拉取的数据数量的对象与通过editor对象的queryCommandValue方法获取'serverparam'命令对应的值(可能是一些自定义的服务器端相关参数)进行合并,最终生成包含完整请求数据参数的对象,作为请求携带的数据发送给服务器端
data: utils.extend({
start: this.listIndex,
size: this.listSize
}, editor.queryCommandValue('serverparam')),
// 设置请求方法为'get'表示发起一个GET请求向服务器端获取数据而不是POST等其他请求方式
method: 'get',
// 设置请求成功的回调函数当服务器端成功返回数据时会触发该函数传入服务器端返回的响应对象r包含了响应的各种信息如响应文本、状态码等作为参数用于处理成功获取到的数据情况
onsuccess: function (r) {
try {
// 尝试将服务器端返回的响应文本r.responseText通过eval函数虽然使用eval函数存在一定安全风险但在这里可能是用于将服务器端返回的符合JSON格式的字符串转换为JavaScript对象不过更好的方式是使用JSON.parse等安全的解析方法转换为JavaScript对象并赋值给变量json方便后续根据对象中的属性判断数据情况并进行相应处理
var json = eval('(' + r.responseText + ')');
// 判断转换后的JavaScript对象json中的'state'属性值是否为'SUCCESS',也就是判断服务器端返回的结果表示此次数据获取是否成功(可能根据服务器端的业务逻辑,返回'SUCCESS'表示正常获取到了文件列表数据等情况)
if (json.state == 'SUCCESS') {
// 如果数据获取成功调用当前实例对象_this的pushData方法应该是用于将获取到的数据添加到页面或者相关数据存储中的函数虽然此处未展示其具体代码但从函数名推测其功能传入服务器端返回的数据列表json.list应该是包含了多个文件相关信息的数组将获取到的文件数据进行相应的展示等处理操作
_this.pushData(json.list);
// 更新当前已经拉取的数据在整个数据集中的索引位置_this.listIndex通过将服务器端返回的起始索引json.start可能是此次返回数据在整个数据集中的起始位置信息转换为整数后加上返回的数据列表长度json.list.length来计算得到新的索引位置以便下次拉取数据时能从正确的位置继续获取数据
_this.listIndex = parseInt(json.start) + parseInt(json.list.length);
// 判断如果更新后的索引位置_this.listIndex大于等于服务器端返回的总数据量json.total表示整个在线文件数据集的总数说明已经拉取完了所有数据将标记是否拉取完所有数据的变量_this.listEnd设置为true表示数据拉取结束了
if (_this.listIndex >= json.total) {
_this.listEnd = true;
}
// 将表示正在加载数据的变量_this.isLoadingData设置为false标记当前数据加载操作已完成允许后续再次发起数据拉取请求如果满足条件的话
_this.isLoadingData = false;
}
} catch (e) {
// 如果在尝试解析服务器端返回的数据或者进行其他相关操作时出现了异常(比如数据格式不符合预期等情况导致转换对象失败等),进行以下异常处理逻辑
// 判断服务器端返回的响应文本r.responseText中是否包含'ue_separate_ue'字符串,如果包含(可能表示一种特殊的数据格式或者错误情况等,具体根据业务逻辑确定)
if (r.responseText.indexOf('ue_separate_ue')!= -1) {
// 通过split方法将响应文本r.responseText按照自身进行分割这里的分割逻辑看起来有点奇怪可能是根据特定的数据格式要求进行处理也许是想获取其中的某个部分作为数据列表具体需要结合实际业务来看将分割后的结果赋值给变量list作为获取到的数据列表
var list = r.responseText.split(r.responseText);
// 调用当前实例对象_this的pushData方法传入获取到的数据列表list将数据进行相应的展示等处理操作虽然数据格式可能不符合常规的预期但按照这种特殊情况进行处理
_this.pushData(list);
// 将当前已经拉取的数据在整个数据集中的索引位置_this.listIndex更新为获取到的数据列表长度list.length转换为整数后的数值因为可能这种特殊格式下无法按照常规方式计算索引只能简单以数据列表长度来表示位置
_this.listIndex = parseInt(list.length);
// 将标记是否拉取完所有数据的变量_this.listEnd设置为true表示数据拉取结束了可能在这种特殊情况下认为已经获取完所有能处理的数据了
_this.listEnd = true;
// 将表示正在加载数据的变量_this.isLoadingData设置为false标记当前数据加载操作已完成结束这次特殊情况下的数据处理流程
_this.isLoadingData = false;
}
}
},
// 设置请求失败的回调函数当请求出现错误比如网络问题、服务器端返回错误状态码等情况时会触发该函数用于处理请求失败的情况在这里只是简单地将表示正在加载数据的变量_this.isLoadingData设置为false标记当前数据加载操作结束虽然失败了允许后续再次发起数据拉取请求如果满足条件的话
onerror: function () {
_this.isLoadingData = false;
}
});
}
},
/* 添加图片到列表界面上 */
// 定义一个名为pushData的函数用于将获取到的在线文件图片数据添加到列表界面上进行展示接收一个参数list代表从服务器端获取到的文件数据列表通常是包含多个文件相关信息的数组
pushData: function (list) {
// 初始化多个变量i作为循环计数器item用于创建每个文件对应的DOM元素<li>元素代表列表中的一个文件项img用于创建图片元素如果文件是图片类型的话filetype用于存储文件的类型通过文件链接的扩展名来判断preview用于创建文件的预览元素可能是图片元素或者包含文件相关信息的其他元素根据文件类型不同而不同icon用于创建一个图标元素可能用于展示文件的一些标识等_this用于保存当前实例对象this的引用方便在闭包等场景下正确访问实例的属性和方法urlPrefix通过调用editor对象的getOpt方法获取'fileManagerUrlPrefix'配置项的值(可能是文件链接的前缀地址,用于拼接完整的可访问文件链接)
var i, item, img, filetype, preview, icon, _this = this,
urlPrefix = editor.getOpt('fileManagerUrlPrefix');
// 使用for循环遍历传入的文件数据列表list从索引0开始每次递增1直到遍历完所有元素用于逐个处理每个文件的数据并添加到界面上
for (i = 0; i < list.length; i++) {
// 判断当前索引位置的文件数据list[i]是否存在并且其是否包含url属性也就是判断这个文件数据是否有效且有对应的文件链接地址用于后续操作
if (list[i] && list[i].url) {
// 创建一个 <li> 元素作为文件列表中的一个文件项元素用于包裹文件的相关展示元素如预览图、图标等并将其赋值给变量item后续会向这个元素中添加其他子元素来完善文件项的展示内容
item = document.createElement('li');
// 创建一个 <span> 元素可能作为文件相关的图标元素具体图标样式等可能后续通过类名等方式设置赋值给变量icon用于后续添加到文件项元素item
icon = document.createElement('span');
// 获取当前文件的类型通过截取文件链接list[i].url中最后一个 '.' 之后的字符串也就是文件扩展名来确定文件类型并赋值给变量filetype用于后续根据文件类型进行不同的展示处理比如图片文件和非图片文件展示方式不同
filetype = list[i].url.substr(list[i].url.lastIndexOf('.') + 1);
// 判断文件类型filetype是否在常见的图片文件类型列表"png|jpg|jpeg|gif|bmp")中,如果在这个列表中,说明是图片文件,进行以下处理逻辑来展示图片预览
if ("png|jpg|jpeg|gif|bmp".indexOf(filetype)!= -1) {
// 创建一个 <img> 元素用于展示图片文件的预览图赋值给变量preview后续会设置其相关属性如src、width等来正确显示图片
preview = document.createElement('img');
// 使用domUtils对象的on方法可能是自定义的事件绑定函数为创建的图片元素preview绑定加载load事件处理函数当图片加载完成时会触发该函数传入一个立即执行函数返回的另一个函数作为事件处理函数这样做是为了在闭包中正确传递当前的图片元素preview引用避免出现变量作用域问题
domUtils.on(preview, 'load', (function (image) {
return function () {
// 在图片加载完成的回调函数内部调用当前实例对象_this的scale方法应该是用于调整图片大小、缩放等操作的函数虽然此处未展示其具体代码但从函数名推测其功能传入当前图片元素image也就是传入的参数image它在闭包中指向最初创建的preview元素以及图片父元素image.parentNode也就是包含这个图片的元素这里应该是文件项中的用于展示图片的区域元素的宽度offsetWidth和高度offsetHeight作为参数根据父元素的尺寸来对图片进行缩放等适配操作确保图片在界面上能合适地展示
_this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight);
};
})(preview));
// 设置图片元素preview的宽度为113像素这里固定了一个初始宽度后续可能根据缩放等操作再进行调整具体根据界面布局和展示需求而定
preview.width = 113;
// 设置图片元素preview的src属性通过拼接文件链接前缀urlPrefix、文件的实际链接地址list[i].url以及一个用于避免缓存的参数根据文件链接中是否已经包含'?'来决定添加'?noCache='或者'&noCache='并加上当前时间的时间戳转换为36进制后的字符串这样每次请求图片时由于时间戳不同可以避免浏览器缓存旧的图片确保获取到最新的图片数据使得图片能正确加载并显示出来
preview.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1? '?noCache=' : '&noCache=') + (+new Date()).toString(36));
} else {
// 如果文件类型不是常见的图片文件类型,进行以下处理逻辑来展示非图片文件的相关信息
var ic = document.createElement('i'),
textSpan = document.createElement('span');
// 设置 <span> 元素textSpan的innerHTML属性为文件链接list[i].url中最后一个 '/' 之后的字符串(也就是文件名部分),用于展示文件的名称信息
textSpan.innerHTML = list[i].url.substr(list[i].url.lastIndexOf('/') + 1);
// 创建一个 <div> 元素作为非图片文件的整体预览元素将其赋值给变量preview后续会向这个元素中添加其他子元素如文件类型图标、文件名等来展示文件相关信息
preview = document.createElement('div');
// 将创建的 <i> 元素ic可能用于展示文件类型对应的图标样式等添加到 <div> 元素preview作为其子元素
preview.appendChild(ic);
// 将创建的 <span> 元素textSpan展示文件名添加到 <div> 元素preview同样作为其子元素完成非图片文件预览元素内部的结构搭建
preview.appendChild(textSpan);
// 使用domUtils对象的addClass方法可能是自定义的添加类名函数为 <div> 元素preview添加类名'file-wrapper'通过CSS样式类来设置这个元素的外观、布局等样式效果使其符合非图片文件展示的整体样式要求
domUtils.addClass(preview, 'file-wrapper');
// 使用domUtils对象的addClass方法为 <span> 元素textSpan添加类名'file-title',用于设置文件名展示的样式效果(比如字体、颜色等样式),使其更清晰地展示文件名
domUtils.addClass(textSpan, 'file-title');
// 使用domUtils对象的addClass方法为 <i> 元素ic添加类名'file-type-' + filetype通过动态添加包含文件类型的类名可以根据不同的文件类型应用不同的图标样式等效果方便用户直观识别文件类型
domUtils.addClass(ic, 'file-type-' + filetype);
// 使用domUtils对象的addClass方法再次为 <i> 元素ic添加类名'file-preview',可能用于统一设置文件预览相关元素的一些通用样式效果等情况
domUtils.addClass(ic, 'file-preview');
}
// 使用domUtils对象的addClass方法为之前创建的 <span> 元素icon添加类名'icon',用于设置这个图标元素的样式(比如图标大小、颜色、位置等样式效果),使其符合在文件项中的展示要求
domUtils.addClass(icon, 'icon');
// 为文件项元素item设置自定义的'data-url'属性其值通过拼接文件链接前缀urlPrefix和文件的实际链接地址list[i].url得到用于在后续操作中方便获取文件的完整链接信息例如点击文件项进行相关操作时可能会用到这个链接
item.setAttribute('data-url', urlPrefix + list[i].url);
// 判断当前文件数据list[i])中是否包含'original'属性(可能是文件的原始名称等更合适的标题信息),如果包含
if (list[i].original) {
// 为文件项元素item设置自定义的'data-title'属性,其值为文件的'original'属性值,用于设置文件项更准确的标题信息,方便在界面上展示(比如鼠标悬停提示等场景可以显示这个标题)
item.setAttribute('data-title', list[i].original);
}
// 将创建好的文件预览元素preview可能是图片元素或者包含文件相关信息的 <div> 元素取决于文件类型添加到文件项元素item作为其子元素完成文件项中主要内容的添加
item.appendChild(preview);
// 将设置好类名的图标元素icon添加到文件项元素item同样作为其子元素进一步完善文件项的展示结构
item.appendChild(icon);
// 将构建好的文件项元素item插入到当前实例对象this的list属性所代表的文件列表元素应该是之前初始化的 <ul> 元素并且插入位置在this.clearFloat元素可能是用于清除浮动等布局相关的元素之前这样新添加的文件项就会按照顺序展示在文件列表中合适的位置上
this.list.insertBefore(item, this.clearFloat);
}
}
},
/* 改变图片大小 */
// 定义一个名为'scale'的函数用于根据指定的参数来改变图片的大小以及对图片进行相应的位置调整例如使其在某个容器内居中显示等情况接收四个参数分别是要操作的图片元素img、期望的目标宽度w、期望的目标高度h以及用于指定调整类型的参数type
scale: function (img, w, h, type) {
// 获取传入的图片元素img当前的实际宽度值单位应该是像素并将其赋值给变量ow用于后续根据原始宽高比例来计算调整后的宽高尺寸等操作
var ow = img.width,
// 获取传入的图片元素img当前的实际高度值单位应该是像素赋值给变量oh同样方便后续按照原始宽高比例进行相应的尺寸计算和调整逻辑
oh = img.height;
// 判断传入的调整类型参数type是否等于'justify''justify'可能表示一种特定的图片缩放及对齐方式(比如让图片在某个区域内按比例缩放并居中显示等情况),如果等于该值,则进入以下相应的处理逻辑
if (type == 'justify') {
// 判断图片当前的原始宽度ow是否大于等于原始高度oh如果满足这个条件说明图片比较“宽”按照以下方式调整图片的宽高及位置
if (ow >= oh) {
// 将图片元素img的宽度属性width设置为传入的目标宽度值w也就是让图片宽度达到期望的宽度尺寸
img.width = w;
// 根据图片原始的宽高比例oh / ow来计算调整后的高度值通过目标高度h乘以原始宽高比例得到调整后的高度h * oh / ow这样能保证图片按比例缩放然后将计算得到的高度值赋给图片元素img的高度属性height
img.height = h * oh / ow;
// 计算图片在水平方向上需要设置的外边距marginLeft目的是让图片在水平方向上居中显示。先计算图片调整后的宽度img.width与目标宽度w的差值的一半(img.width - w) / 2然后取其绝对值并转换为整数通过parseInt函数最后在前面添加负号'-'将得到的值设置为图片元素img的marginLeft样式属性值这样图片就能在水平方向上相对于父容器居中了
img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
} else {
// 如果图片当前的原始宽度ow小于原始高度oh说明图片比较“高”则按照以下方式调整图片的宽高及位置
// 根据图片原始的宽高比例ow / oh来计算调整后的宽度值通过目标宽度w乘以原始宽高比例得到调整后的宽度w * ow / oh保证图片按比例缩放然后将该宽度值赋给图片元素img的宽度属性width
img.width = w * ow / oh;
// 将图片元素img的高度属性height设置为传入的目标高度值h使图片高度达到期望的高度尺寸
img.height = h;
// 计算图片在垂直方向上需要设置的外边距marginTop用于让图片在垂直方向上居中显示。先计算图片调整后的高度img.height与目标高度h的差值的一半(img.height - h) / 2然后取其绝对值并转换为整数通过parseInt函数最后在前面添加负号'-'将得到的值设置为图片元素img的marginTop样式属性值使图片在垂直方向上相对于父容器居中
img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
}
} else {
// 如果传入的调整类型参数type不等于'justify',则进入以下默认的处理逻辑(可能是另一种图片缩放及位置调整方式)
// 判断图片当前的原始宽度ow是否大于等于原始高度oh如果满足这个条件按照以下方式调整图片的宽高及位置
if (ow >= oh) {
// 根据图片原始的宽高比例ow / oh来计算调整后的宽度值通过目标宽度w乘以原始宽高比例得到调整后的宽度w * ow / oh保证图片按比例缩放然后将该宽度值赋给图片元素img的宽度属性width
img.width = w * ow / oh;
// 将图片元素img的高度属性height设置为传入的目标高度值h使图片高度达到期望的高度尺寸
img.height = h;
// 计算图片在水平方向上需要设置的外边距marginLeft用于让图片在水平方向上有一定的偏移以达到某种布局效果具体根据实际需求而定。先计算图片调整后的宽度img.width与目标宽度w的差值的一半(img.width - w) / 2然后取其绝对值并转换为整数通过parseInt函数最后在前面添加负号'-'将得到的值设置为图片元素img的marginLeft样式属性值
img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
} else {
// 如果图片当前的原始宽度ow小于原始高度oh则按照以下方式调整图片的宽高及位置
// 将图片元素img的宽度属性width设置为传入的目标宽度值w让图片宽度达到期望的宽度尺寸
img.width = w;
// 根据图片原始的宽高比例oh / ow来计算调整后的高度值通过目标高度h乘以原始宽高比例得到调整后的高度h * oh / ow保证图片按比例缩放然后将该高度值赋给图片元素img的高度属性height
img.height = h * oh / ow;
// 计算图片在垂直方向上需要设置的外边距marginTop用于让图片在垂直方向上有一定的偏移以达到某种布局效果具体根据实际需求而定。先计算图片调整后的高度img.height与目标高度h的差值的一半(img.height - h) / 2然后取其绝对值并转换为整数通过parseInt函数最后在前面添加负号'-'将得到的值设置为图片元素img的marginTop样式属性值
img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
}
}
},
// 定义一个名为'getInsertList'的函数,用于获取当前被选中的文件(图片)对应的列表信息,这些信息可能后续用于插入到其他地方(比如编辑器等场景),函数会遍历文件列表元素中的子元素,筛选出被选中的元素,并提取其相关属性信息组成列表返回
getInsertList: function () {
// 初始化循环计数器变量i用于后续遍历文件列表元素的子元素。同时通过this.list.children获取当前实例对象this的list属性所代表的文件列表元素应该是之前创建的 <ul> 元素)的所有子元素(也就是每个文件对应的 <li> 元素等并赋值给变量lis方便后续遍历这些子元素来判断哪些是被选中的元素。初始化一个空数组list用于存储最终提取出来的被选中文件的相关信息如标题、链接等
var i, lis = this.list.children, list = [];
// 使用for循环遍历获取到的文件列表子元素lis从索引0开始每次递增1直到遍历完所有子元素用于逐个检查每个子元素是否被选中并提取相应的信息
for (i = 0; i < lis.length; i++) {
// 使用domUtils对象的hasClass方法可能是自定义的判断元素是否包含某个类名的函数来判断当前遍历到的子元素lis[i],即每个 <li> 元素等)是否包含'selected'类名,'selected'类名可能表示该文件项在界面上处于被选中的状态,只有被选中的元素才进行以下信息提取操作
if (domUtils.hasClass(lis[i], 'selected')) {
// 通过getAttribute方法获取当前被选中的元素lis[i])的自定义'data-url'属性值该属性值应该是对应文件的链接地址将其赋值给变量url用于后续构建要返回的文件信息对象中的链接部分
var url = lis[i].getAttribute('data-url');
// 通过getAttribute方法获取当前被选中的元素lis[i])的自定义'data-title'属性值该属性值可能是对应文件更合适的标题信息比如原始文件名等如果该属性不存在也就是返回值为假值则通过截取文件链接url中最后一个'/'之后的字符串也就是文件名部分作为标题将最终确定的标题赋值给变量title用于后续构建要返回的文件信息对象中的标题部分
var title = lis[i].getAttribute('data-title') || url.substr(url.lastIndexOf('/') + 1);
// 将一个包含标题title和链接url信息的对象添加到list数组中这样就构建好了一个代表被选中文件相关信息的对象后续可以将整个list数组返回供其他地方使用这些文件信息进行相应的插入等操作
list.push({
title: title,
url: url
});
}
}
// 返回包含所有被选中文件相关信息标题和链接的列表list以便在其他代码中可以获取并根据这些信息进行相应的处理比如插入到编辑器中的相应位置等操作
return list;
}
};
})();