【发布时间】:2013-11-13 19:57:31
【问题描述】:
我有以下 jquery 自定义函数。 'uncheck all' 和 'check all' 功能按他们说的做。但是,当我单击单个复选框时,我得到最大调用堆栈大小超出错误。我已经在发生递归的地方进行了砖墙测试。请指教。谢谢
$.fn.multiselect = function(fn, options) {
if (typeof fn === 'object') {
options = fn;
fn = 'init';
}
if (typeof fn === 'undefined') {
fn = 'init';
}
//return direct methods
var directMethods = {
'widget': function() {
return $(this).data('multiselect-widget');
},
'modal': function() {
return $(this).data('multiselect-modal');
}
};
var args = arguments;
Array.prototype.shift.call(args);
if (args.length > 0) {
args.shift();
}
if (typeof directMethods[fn] === 'function') {
return directMethods[fn].apply(this, args);
}
var methods = {
init: function(options) {
var config = $.extend({}, {}, options || {
list: 1,
body: 'body'
}, $(this).data());
var $$ = $(this).hide();
$$.data('multiselect', config);
var $div = $('<div class="input-append dropdown-multiselect">').insertAfter($$);
$$.data('multiselect-widget', $div);
var $span = $('<span class="input-xlarge uneditable-input label" />').appendTo($div);
var $btn = $('<span class="add-on"><i class="icon-chevron-down"></i></span>').appendTo($div);
var $modal = $('<div class="modal hide fade modal-multiselect" />')
.appendTo($(config.body));
if ($$.attr('id')) {
$modal.attr('id', 'modal-multiselect-' + $$.attr('id'));
}
$div.click(function() {
$modal.modal('show');
});
$$.data('multiselect-modal', $modal);
var $menu = $('<div class="modal-body" role="multiselect" />').appendTo($modal);
var $controls = $('<div class="modal-footer" role="multiselectcontrols" />').appendTo($modal);
$("<span>").addClass('btn')
.appendTo($controls)
.text('Close')
.click(function() {
$modal.modal('hide');
});
if ($$.attr('multiple')) {
$controls.append($("<span class='btn btn-mini pull-left'>").html('<i class="icon-check-empty"></i>uncheck all').click(function() {
$$.val('');
$menu.find(":checkbox").prop('checked', false);
$$.multiselect('refreshLabel');
}));
$controls.append($("<span class='btn btn-mini pull-left'>").html('<i class="icon-check"></i>check all').click(function() {
$menu.find(":checkbox").prop("checked", !$(this).prop("checked")).each(function() {
$(this).trigger('click');
$(this).prop('checked', true);
});
}));
}
$$.multiselect('refresh');
},
refresh: function() {
var $menu = $(this).multiselect('modal').find('[role=multiselect]').empty();
var $controls = $(this).multiselect('modal').find('[role=multiselectcontrols]');
var $$ = $(this);
var val = $$.val();
var type = ($$.attr('multiple')) ? 'checkbox' : 'radio';
var clickIn = function() {
var check = $(this).is(":checked");
var self = this;
if ($$.attr('multiple')) {
var values = $$.val() || [];
if (check) {
values.push($(this).val());
} else {
values.splice($.inArray($(this).val(), values), 1);
}
$$.val(values).multiselect('refreshLabel').trigger('change');
} else {
$menu.find("input[type=radio]").each(function() {
if (this !== self) {
$(this).prop('checked', false);
}
});
$$.multiselect('modal').modal('hide');
$$.val($(this).val()).multiselect('refreshLabel').trigger('change');
}
return $(this);
};
var $lastParent = $$;
var $appendTo = $('<ul class="multiselect-menu">').appendTo($menu);
var $optGroup = null;
$$.find('option').each(function() {
if ($(this).parent().is($lastParent) === false) {
$lastParent = $(this).parent();
if ($lastParent.is('optgroup')) {
$optGroup = $('<li>').append($('<label class="optgroup">').text($lastParent.attr('label')));
}
}
if ($optGroup !== null) {
$($optGroup).append(
$("<ul>").append($("<li>").append($('<label>').append(
$('<input type="' + type + '">')
.attr({
checked: (typeof val === 'string') ? val === $(this).val() : $.inArray($(this).val(), val) > -1,
value: $(this).val()
})
.click(function() {
clickIn.apply(this);
})
)
.append($(this).text()))));
$($optGroup).appendTo($appendTo);
}
if ($optGroup === null) {
$("<li>").appendTo($appendTo)
.append($('<label>')
.append(
$('<input type="' + type + '">')
.attr({
checked: (typeof val === 'string') ? val === $(this).val() : $.inArray($(this).val(), val) > -1,
value: $(this).val()
})
.click(function() {
clickIn.apply(this);
})
)
.append($(this).text()));
}
});
$$.multiselect('refreshLabel');
},
refreshLabel: function() {
var self = this;
var $$ = $(this).multiselect('widget');
var txt = '';
var options = $(this).data('multiselect');
var val = $(this).val() || [];
if (typeof val === 'string') {
txt = $(this).find('[value="' + val + '"]').text();
} else {
var len = (val) ? val.length : 0;
if (len > options.list || len === 0) {
txt = len + ' of ' + $(this).find('option').length + ' selected';
} else {
var texts = [];
$.each(val, function(index, v) {
texts.push($(self).find('[value=' + v + ']').text());
});
txt = texts.join(', ');
}
}
$$.find('.label').text(txt);
}
};
return $(this).each(function() {
methods[fn].apply(this, args);
});
};
调用栈是:
jQuery.event.trigger
(anonymous function)
jQuery.extend.each
jQuery.fn.jQuery.each
jQuery.fn.extend.trigger
jQuery.fn.(anonymous function)
e.fn.extend.focus
(anonymous function)
jQuery.event.dispatch
elemData.handle.eventHandle
jQuery.event.trigger
(anonymous function)
jQuery.extend.each
jQuery.fn.jQuery.each
jQuery.fn.extend.trigger
jQuery.fn.(anonymous function)
e.fn.extend.focus
(anonymous function)
jQuery.event.dispatch
elemData.handle.eventHandle
jQuery.event.trigger
(anonymous function)
jQuery.extend.each
jQuery.fn.jQuery.each
jQuery.fn.extend.trigger
jQuery.fn.(anonymous function)
e.fn.extend.focus
(anonymous function)
jQuery.event.dispatch
elemData.handle.eventHandle
jQuery.event.trigger
(anonymous function)
jQuery.extend.each
etc..
【问题讨论】:
-
您的焦点事件似乎正在触发 $(someele).each() 触发焦点事件,然后重复该过程。虽然,我在你的代码中看不到它(那里只有这么多代码......),所以基本上由于某种原因,当你聚焦元素时,焦点事件再次被触发,导致无限循环。跨度>
-
您是否尝试过在代码中的某处设置断点,以便查看递归发生的位置?这是一个复杂的插件。
标签: javascript jquery