测试

修改https://github.com/tkvw/jQuery-File-Upload/blob/master/basic-plus.html

var node = $('<p id="chuck" class="preview"/>')
.append($('<span/>').text(file.name));

给p增加id和class,在页面加载后,

打开浏览器的console,然后手动执行,然后单击图片。会发现这个事件是会触发的

$(".preview").on("click", function(){
alert("test");
})

但是jquery.fileupload-image-editor.js中的没有触发,事件应该是绑定了

手动移除事件

$(".preview").off("click");  https://stackoverflow.com/questions/209029/best-way-to-remove-an-event-handler-in-jquery

分析

1.jquery.fileupload-image-editor.js定义了uploadImageEditorPreviewSelector

uploadImageEditorPreviewSelector: 'click .preview',

2,.jquery.fileupload-ui.js中定义了filesContainer
// The container for the list of files. If undefined, it is set to
// an element with class "files" inside of the widget element:
filesContainer: undefined,

_initEventHandlers: function () {
this._super();

var handlers = {};
handlers[this.options.uploadImageEditorPreviewSelector] = this._previewHandler.bind(this);

this._on(this.options.filesContainer, handlers);
},

文件上传之后

jquery.fileupload.js中_onAdd: function (e, data) {

that._initResponseObject(newData);
that._initProgressObject(newData);
that._addConvenienceMethods(e, newData);
result = that._trigger(
'add',
$.Event('add', {delegatedEvent: e}),
newData
);
return result;

_initResponseObject: function (obj) {
var prop;
if (obj._response) {
for (prop in obj._response) {
if (obj._response.hasOwnProperty(prop)) {
delete obj._response[prop];
}
}
} else {
obj._response = {};
}
},

_initProgressObject: function (obj) {
var progress = {
loaded: 0,
total: 0,
bitrate: 0
};
if (obj._progress) {
$.extend(obj._progress, progress);
} else {
obj._progress = progress;
}
},

 // Adds convenience methods to the data callback argument:
_addConvenienceMethods: function (e, data) {
var that = this,
getPromise = function (args) {
return $.Deferred().resolveWith(that, args).promise();
};
data.process = function (resolveFunc, rejectFunc) {
if (resolveFunc || rejectFunc) {
data._processQueue = this._processQueue =
(this._processQueue || getPromise([this])).then(
function () {
if (data.errorThrown) {
return $.Deferred()
.rejectWith(that, [data]).promise();
}
return getPromise(arguments);
}
).then(resolveFunc, rejectFunc);
}
return this._processQueue || getPromise([this]);
};
data.submit = function () {
if (this.state() !== 'pending') {
data.jqXHR = this.jqXHR =
(that._trigger(
'submit',
$.Event('submit', {delegatedEvent: e}),
this
) !== false) && that._onSend(e, this);
}
return this.jqXHR || that._getXHRPromise();
};
data.abort = function () {
if (this.jqXHR) {
return this.jqXHR.abort();
}
this.errorThrown = 'abort';
that._trigger('fail', null, this);
return that._getXHRPromise(false);
};
data.state = function () {
if (this.jqXHR) {
return that._getDeferredState(this.jqXHR);
}
if (this._processQueue) {
return that._getDeferredState(this._processQueue);
}
};
data.processing = function () {
return !this.jqXHR && this._processQueue && that
._getDeferredState(this._processQueue) === 'pending';
};
data.progress = function () {
return this._progress;
};
data.response = function () {
return this._response;
};
},

jquery.ui.widget.js里面的_trigger函数

this.element.trigger( event, data );

打印event

jQuery.Event {originalEvent: j…y.Event, type: "fileuploadadd", isDefaultPrevented: ƒ, timeStamp: 1561917127348, jQuery111304105261403454039: true, …}currentTarget: input#fileuploaddata: undefineddelegateTarget: input#fileuploaddelegatedEvent: jQuery.Event {originalEvent: Event, type: "change", isDefaultPrevented: ƒ, timeStamp: 33359.854999987874, jQuery111304105261403454039: true, …}handleObj: {type: "fileuploadadd", origType: "fileuploadadd", data: undefined, handler: ƒ, guid: 20, …}isDefaultPrevented: ƒ returnFalse()isTrigger: 3jQuery111304105261403454039: truenamespace: ""namespace_re: nulloriginalEvent: jQuery.Event {type: "add", delegatedEvent: j…y.Event, timeStamp: 1561917127348, jQuery111304105261403454039: true}result: undefinedtarget: input#fileuploadtimeStamp: 1561917127348type: "fileuploadadd"__proto__: Object

trigger后面的代码是

return !( $.isFunction( callback ) &&
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
event.isDefaultPrevented() );

callback对应下面的add

// The add callback is invoked as soon as files are added to the fileupload
// widget (via file input selection, drag & drop or add API call).
// See the basic file upload widget for more information:
add: function (e, data) {
if (e.isDefaultPrevented()) {
return false;
}
var $this = $(this),
that = $this.data('blueimp-fileupload') ||
$this.data('fileupload'),
options = that.options;
data.context = that._renderUpload(data.files)
.data('data', data)
.addClass('processing');
options.filesContainer[
options.prependFiles ? 'prepend' : 'append'
](data.context);
that._forceReflow(data.context);
that._transition(data.context);
data.process(function () { //这里的process是在_addConvenienceMethods里面定义的
return $this.fileupload('process', data);
}).always(function () {
data.context.each(function (index) {
$(this).find('.size').text(
that._formatFileSize(data.files[index].size)
);
}).removeClass('processing');
that._renderPreviews(data);
}).done(function () {
data.context.find('.start').prop('disabled', false);
if ((that._trigger('added', e, data) !== false) &&
(options.autoUpload || data.autoUpload) &&
data.autoUpload !== false) {
data.submit();
}
}).fail(function () {
if (data.files.error) {
data.context.each(function (index) {
var error = data.files[index].error;
if (error) {
$(this).find('.error').text(error);
}
});
}
});
},

jquery.fileupload-ui.js里面的

 _renderUpload: function (files) {
return this._renderTemplate(
this.options.uploadTemplate, //自己做测试的,这边是null
files
);
},
_renderTemplate: function (func, files) {
if (!func) {
return $(); //自己做测试,这边就返回了
}
var result = func({
files: files,
formatFileSize: this._formatFileSize,
options: this.options
});
if (result instanceof $) {
return result;
}
return $(this.options.templatesContainer).html(result).children();
},
_forceReflow: function (node) {
return $.support.transition && node.length &&
node[0].offsetWidth;
},
_transition: function (node) {
var dfd = $.Deferred();
if ($.support.transition && node.hasClass('fade') && node.is(':visible')) {
node.bind(
$.support.transition.end,
function (e) {
// Make sure we don't respond to other transitions events
// in the container element, e.g. from button elements:
if (e.target === node[0]) {
node.unbind($.support.transition.end);
dfd.resolveWith(node);
}
}
).toggleClass('in');
} else {
node.toggleClass('in');
dfd.resolveWith(node);

}
return dfd;
},
 data.process = function (resolveFunc, rejectFunc) {
if (resolveFunc || rejectFunc) {
data._processQueue = this._processQueue =
(this._processQueue || getPromise([this])).then(
function () {
if (data.errorThrown) {
return $.Deferred()
.rejectWith(that, [data]).promise();
}
return getPromise(arguments);
}
).then(resolveFunc, rejectFunc);
}
return this._processQueue || getPromise([this]);
};

然后跳转jquery.fileupload-ui.js里面

 // Processes the files given as files property of the data parameter,
// returns a Promise object that allows to bind callbacks:
process: function (data) {
var that = this,
options = $.extend({}, this.options, data);
if (options.processQueue && options.processQueue.length) {
this._transformProcessQueue(options);
if (this._processing === 0) {
this._trigger('processstart');
}
$.each(data.files, function (index) {
var opts = index ? $.extend({}, options) : options,
func = function () {
if (data.errorThrown) {
return $.Deferred()
.rejectWith(that, [data]).promise();
}
return that._processFile(opts, data);
};
opts.index = index;
that._processing += 1;
that._processingQueue = that._processingQueue.then(func, func)
.always(function () {
that._processing -= 1;
if (that._processing === 0) {
that._trigger('processstop');
}
});
});
}
return this._processingQueue;
},
// Replaces the settings of each processQueue item that
// are strings starting with an "@", using the remaining
// substring as key for the option map,
// e.g. "@autoUpload" is replaced with options.autoUpload:
_transformProcessQueue: function (options) {
var processQueue = [];
$.each(options.processQueue, function () {
var settings = {},
action = this.action,
prefix = this.prefix === true ? action : this.prefix;
$.each(this, function (key, value) {
if ($.type(value) === 'string' &&
value.charAt(0) === '@') {
settings[key] = options[
value.slice(1) || (prefix ? prefix +
key.charAt(0).toUpperCase() + key.slice(1) : key)
];
} else {
settings[key] = value;
} });
processQueue.push(settings);
});
options.processQueue = processQueue;
},
 processstart: function (e) {
if (e.isDefaultPrevented()) {
return false;
}
$(this).addClass('fileupload-processing');
},

然后是jquery.fileupload-process.js里面的

_processFile: function (data, originalData) {
var that = this,
dfd = $.Deferred().resolveWith(that, [data]),
chain = dfd.promise();
this._trigger('process', null, data);
$.each(data.processQueue, function (i, settings) {
var func = function (data) {
if (originalData.errorThrown) {
return $.Deferred()
.rejectWith(that, [originalData]).promise();
}
return that.processActions[settings.action].call(
that,
data,
settings
);
};
chain = chain.then(func, settings.always && func);
});
chain
.done(function () {
that._trigger('processdone', null, data);
that._trigger('processalways', null, data);
})
.fail(function () {
that._trigger('processfail', null, data);
that._trigger('processalways', null, data);
});
return chain;
},
 // Processes the files given as files property of the data parameter,
// returns a Promise object that allows to bind callbacks:
process: function (data) {
var that = this,
options = $.extend({}, this.options, data);
if (options.processQueue && options.processQueue.length) {
this._transformProcessQueue(options);
if (this._processing === 0) {
this._trigger('processstart');
}
$.each(data.files, function (index) {
var opts = index ? $.extend({}, options) : options,
func = function () {
if (data.errorThrown) {
return $.Deferred()
.rejectWith(that, [data]).promise();
}
return that._processFile(opts, data);
};
opts.index = index;
that._processing += 1;
that._processingQueue = that._processingQueue.then(func, func)
.always(function () {
that._processing -= 1;
if (that._processing === 0) {
that._trigger('processstop');
}
});
});
}
return this._processingQueue;
},

结论

绑定事件的时候依赖于this.options.filesContainer,这玩意不存在于jquery.fileupload.js里面

 _initEventHandlers: function () {
this._super(); var handlers = {};
handlers[this.options.uploadImageEditorPreviewSelector] = this._previewHandler.bind(this);
console.log(`filesContainer = ${this.options.filesContainer}`);
this._on(this.options.filesContainer, handlers);
},

而filesContainer在jquery.fileupload-ui.js中

 // The container for the list of files. If undefined, it is set to
// an element with class "files" inside of the widget element:
filesContainer: undefined, _initFilesContainer: function () {
var options = this.options;
if (options.filesContainer === undefined) {
options.filesContainer = this.element.find('.files');
} else if (!(options.filesContainer instanceof $)) {
options.filesContainer = $(options.filesContainer);
}
},

因为basic.html没有引用jquery.fileupload-ui.js,所以导致事件绑定失败。

顺便打印一下this.element

console.log(`filesContainer = ${this.options.filesContainer}`);
console.log(this.element);

自己手动复制函数,然后在_initEventHandlers里面调用

  _initFilesContainer: function () {
var options = this.options;
if (options.filesContainer === undefined) {
options.filesContainer = this.element.find('.files');
} else if (!(options.filesContainer instanceof $)) {
options.filesContainer = $(options.filesContainer);
}
},
_initEventHandlers: function () {
this._super();
this._initFilesContainer();
var handlers = {};
handlers[this.options.uploadImageEditorPreviewSelector] = this._previewHandler.bind(this);
this._on(this.options.filesContainer, handlers);
},

页面加载后,进行查询

$('#fileupload').fileupload('option', 'filesContainer')

在还有jquery.fileupload-ui.js里面还有关于uploadTemplateID的设置

options: {
// By default, files added to the widget are uploaded as soon
// as the user clicks on the start buttons. To enable automatic
// uploads, set the following option to true:
autoUpload: false,
// The ID of the upload template:
uploadTemplateId: 'template-upload',
// The ID of the download template:
downloadTemplateId: 'template-download',

jQuery file upload cropper的 click .preview事件没有绑定成功的更多相关文章

  1. jQuery file upload cropper的流程

    https://tkvw.github.io/jQuery-File-Upload/basic-plus-editor.html 最开始初始化jquery.ui.widget.js中的factory( ...

  2. jQuery File Upload

    jQuery File Upload介绍.............................................. 2 实现基本原理......................... ...

  3. jQuery File Upload 单页面多实例的实现

    jQuery File Upload 的 GitHub 地址:https://github.com/blueimp/jQuery-File-Upload 插件描述:jQuery File Upload ...

  4. jQuery File Upload blueimp with struts2 简单试用

    Official Site的话随便搜索就可以去了 另外新版PHP似乎都有问题  虽然图片都可以上传  但是response报错  我下载的是8.8.7木有问题   但是8.8.7版本结合修改main. ...

  5. 定制jQuery File Upload为微博式单文件上传

    日志未经声明,均为AlloVince原创.版权采用『 知识共享署名-非商业性使用 2.5 许可协议』进行许可. jQuery File Upload是一个非常优秀的上传组件,主要使用了XHR作为上传方 ...

  6. jquery file upload示例

    原文链接:http://blog.csdn.net/qq_37936542/article/details/79258158 jquery file upload是一款实用的上传文件插件,项目中刚好用 ...

  7. jQuery File Upload的使用

    jQuery File Upload 是一个Jquery文件上传组件,支持多文件上传.取消.删除,上传前缩略图预览.列表显示图片大小,支持上传进度条显示等,以下就介绍一下该插件的简单使用 1.需要加载 ...

  8. jQuery file upload callback options

    autoUpload By default, files added to the widget are uploaded as soon as the user clicks on the star ...

  9. jQuery File Upload done函数没有返回

    最近在使用jQuery File Upload 上传图片时发现一个问题,发现done函数没有callback,经过一番折腾,找到问题原因,是由于dataType: ‘json’造成的,改为autoUp ...

随机推荐

  1. phpstudy配置多站点

    1.打开vhosts.conf文件     目录 Apache/conf/vhosts.conf #开启apache的vhost模块 (此模块默认是关闭的,去掉前面的#号) LoadModule vh ...

  2. [.net core]6.launchSettings.json,调试配置

    展开properties, 双击查看内容, { "iisSettings": { "windowsAuthentication": false, "a ...

  3. redis为什么使用单线程 ,还那么快,单线程是怎么实现的

    单线程使用队列 为什么使用单线程 https://baijiahao.baidu.com/s?id=1628498089535886382&wfr=spider&for=pc http ...

  4. Jade学习(四)之结合node如何编译执行

    1.首先安装node 2.新建一个文件夹并进入该文件夹 3.安装jade 4.在新建的文件夹下新建js文件,写nodejs代码 5.在vscode中利用插件code runner直接执行js文件,输出 ...

  5. 关于IDEA中@Autowired 注解报错~图文

    例如鼠标放上去会报错如下: Could not autowire. No beans of 'StudentMapper' type found. less... (Ctrl+F1) Inspecti ...

  6. python之kafka消费

    使用python3第三方工具,实现kafka消费 # -*- coding: utf-8 -*- import uuid import json from kafka import KafkaCons ...

  7. Windows下搭建Nacos及Seata

    一.简介 本文主要描述Nacos及Seata在Windows环境下环境搭建 下载相关软件: Nacos-1.1.4 Seata-0.9.0 二.安装 2.1安装Nacos 解压nacos-server ...

  8. Spring配置搭建——Spring学习 day1

    对象准备 1.导包 Spring core ,context ,beans ,expression ,aop Apache commons logging 2.写入一个对象 这边写入User对象 3. ...

  9. Java并发编程实战 第3章 对象的共享

    可见性 可见性是由于java对于多线程处理的内存模型导致的.这似乎是一种失败的设计,但是JVM却能充分的利用多核处理器的强大性能,例如在缺乏同步的情况下,Java内存模型允许编译器对操作顺序进行重排序 ...

  10. WPF 样式Style

    一:样式基础 如果我们的程序有三个这样的按键,一般我们会这样写 <StackPanel> <!--按键的背景色为Azure蔚蓝色背景色为Coral珊瑚色字体为Arial加粗字体大小为 ...