Chrome Uncaught RangeError:超出了最大调用堆栈大小的点击递归

时间:2013-11-13 19:57:32

标签: javascript jquery

我有以下jquery自定义函数。 “取消选中所有”和“检查所有”功能可以完成他们所说的内容。但是,当我单击一个单独的复选框时,我得到超出最大调用堆栈大小的错误。我已经在砖墙上测试了递归发生的地方。请指教。谢谢

$.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..

1 个答案:

答案 0 :(得分:0)

我认为问题在于您将复选框包装到<label>标记中。这导致我的情况相同的错误。所以你可以把你的复选框这样:

<label for="checkbox-1">Some label</label>
<input type="checkbox"  id="checkbox-1">