我构建了一个插件,它应该将任何按钮转换为模式样式,给定一个可以获取表单的URL。
只有一个元素可以正常工作,但是当选择器返回多个元素时,所有按钮都使用最后一个元素的数据,当get&在插件中调用post方法。
我已经在SO中尝试了几个已回答的问题,但是我们无法找到并修复错误。看起来我错过了什么。
这里是完整的代码。您会看到一些{% django tags %}
和{{ django context variables }}
但只是忽略它们。
谢谢!
一个。
编辑:错字; EDIT2:添加了html; EDIT3:删除了django标签和上下文变量。<div class="modal fade" id="modal-1234" data-uuid="1234">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="title-1234">Title</h4>
</div>
<div class="modal-body" id="body-1234">Body</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" id="cancel-1234">Close</button>
<button type="button" class="btn btn-primary" id="confirm-1234">Save changes</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
(function($){
// define the modalform class
function ModalForm($button){
/*
You can use ModalForm to automate the ajax-form-modal process with TB3.
Usage:
var mf = new ModaForm($('#my-button')); // that's it
*/
self = this;
self.$button = $button;
self.$modal = $('#modal-1234');
// get vars
self.target = self.$button.attr('data-target');
self.uuid = self.$modal.attr('data-uuid');
self.$modal_title = $('#title-' + self.uuid);
self.$modal_body = $('#body-' + self.uuid);
self.$modal_confirm = $('#confirm-' + self.uuid);
self.modal_confirm_original_text = self.$modal_confirm.html()
self.$modal_cancel = $('#cancel-' + self.uuid);
self.$alerts = $('[data-exsutils=push-alerts]').first();
self.$spinner = $('<p class="center"><i class="ace-icon fa fa-spinner fa-spin orange bigger-300"></i></p>');
// bind button click to _get
self.$button.on('click', function(e){
e.preventDefault();
self._get();
});
}
ModalForm.prototype._get = function(){
/*
Issue a get request to fetch form and either render form or push alert when complete.
*/
var self = this;
// show modal, push spinner and change title
self.$modal.modal('show');
self.$modal_body.html(self.$spinner);
self.title = typeof(
self.$button.attr('data-title')) !== 'undefined' ?
self.$button.attr('data-title') : 'Modal form';
self.$modal_title.html(self.title);
// get content
$.ajax({
type: 'GET',
url: self.target,
statusCode: {
403: function(data){
// close modal
// forbidden => close modal & push alert
setTimeout(function(){
self.$modal.modal('hide');
self.$alerts.html(data.responseText);
}, 500);
},
200: function(data){
// success => push form
// note that we will assign self.$form
var $response = $(data);
self.$form = $response.filter('form').first();
self.$modal_body.html($response);
self.$modal_confirm.click(function(e){
e.preventDefault();
self._submit(self.$form);
});
}
},
error: function(data){
console.log(data);
}
});
}
ModalForm.prototype._submit = function(){
/*
Post this.$form data and rerender form or push alert when complete.
*/
var self = this;
// change submit button to loading state
self.$modal_confirm.addClass('disabled').html('Loading...');
// issue pot request
// cleanup
// rebind if rerender or push alerts
$.ajax({
type: 'POST',
url: self.$form.attr('action'),
data: self.$form.serialize(),
statusCode: {
200: function(data){
// this is a form error
// so we must rerender and rebind form
// else we need to rerender and rebind
self.$form.remove();
var $response = $(data);
self.$form = $response.filter('form').first();
self.$modal_body.html($response);
self.$modal_confirm.on('click', function(e){
e.preventDefault();
self._submit(self.$form);
});
},
201: function(data){
// this means object was created
// so we must push an alert and clean up
self.$form.remove();
delete self.$form;
self.$modal.modal('hide');
self.$modal_body.html('');
// we will push alerts only if there is no 201 callback
var callback_201 = self.$button.attr('data-callback-201');
if (typeof(window[callback_201]) !== 'undefined') {
window[callback_201](data);
} else {
self.$alerts.prepend(data);
};
},
403: function(data){
// this means request was forbidden => clean up and push alert
self.$form.remove();
delete self.$form;
self.$modal.modal('hide');
self.$modal_body.html('');
self.$alerts.prepend(data.responseText);
}
},
complete: function(){
// reset button
self.$modal_confirm.removeClass('disabled').html(
self.modal_confirm_original_text);
}
});
}
window.ModalForm = ModalForm;
// define plugin
$.fn.modalForm = function(){
var self = this;
return self.each(function(){
var el = this;
var _ = new window.ModalForm($(el));
$.data(el, 'modalform', _);
});
}
// run plugin
$('[data-exsutils=modal-form]').modalForm();
})(jQuery);
</script>
@Daniel Arant编辑:
可以找到带有简化工作版插件代码的jsFiddle here
我请注意:请阅读所选答案。这个jsfiddle +添加var self = this
将为您提供问题的完整画面和周围的好方法。
答案 0 :(得分:1)
问题的根源是self = this
构造函数中的行ModalForm
。由于您未在var
之前使用关键字self
,因此JavaScripts解释器认为self
是全局window
对象的属性,并将其声明为此类。因此,每次调用ModalForm
构造函数时,self都会接受一个新值,并且构造函数为先前按钮创建的事件处理程序中对self
的所有引用都指向新的,大多数最近的ModalForm
实例已分配给全局self
属性。
要解决此特定问题,只需在var
之前添加关键字self = this
即可。这使得self成为局部变量而不是全局变量,click事件回调函数将指向它们自己的ModalForm实例,而不是指向self
的最后一个实例。
我根据您的代码创建了一个有效的jsFiddle,可以找到here
为了简单起见,我删除了插件代码以消除ajax调用。我也删除了所有的uuid引用。一旦获得对作为jQuery对象的模态的引用,就可以使用jQuery的.find()
方法来获取对模态的各个组件的引用。
如果您对我的插件的快速和脏修改有任何疑问