【问题标题】:Chrome Uncaught RangeError: Maximum call stack size exceeded click recursionChrome Uncaught RangeError:最大调用堆栈大小超出点击递归
【发布时间】: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


【解决方案1】:

我认为问题在于您将复选框包装到 &lt;label&gt; 标记中。在我的情况下,这会导致相同的错误。所以你可以像这样放置你的复选框:

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

【讨论】:

    猜你喜欢
    • 2011-12-01
    • 2014-06-11
    • 2017-05-23
    • 1970-01-01
    • 2021-07-24
    • 2018-03-18
    • 1970-01-01
    • 2022-09-29
    相关资源
    最近更新 更多