jQuery UI Tabs Plugin Broke

时间:2012-11-17 04:57:39

标签: jquery jquery-ui jquery-plugins jquery-ui-tabs

我们正在使用来自这个小提琴的jquery ui tabs箭头插件:http://jsfiddle.net/dECtZ/282/,但是像许多插件一样,它打破了最新版本的jQuery。我们能够使csscur工作,但仍然在jquery核心中得到以下错误(第353行):

Uncaught TypeError:无法分配给只读属性'length'的函数(e,t){if(!this._createWidget)返回new o(e,t); arguments.length&& this._createWidget(e ,t)}

代码如下:

(function($, undefined) {
    if (!$.xui) {
        $.xui = {};
    }
    var tabs = $.extend({}, $.ui.tabs.prototype),
        _super = {
            _create: tabs._create,
            _destroy: tabs._destroy,
            _update: tabs._update
        };
    $.xui.tabs = $.extend(tabs, {
        options: $.extend({}, tabs.options, {
            scrollable: false,
            changeOnScroll: false,
            closable: false,
            resizable: false,
            resizeHandles: "e,s,se"
        }),
        _create: function() {
            var self = this,
                o = self.options;
            _super._create.apply(self);
            if (o.scrollable) {
                self.element.addClass("ui-tabs-scrollable");
                var scrollContainer = $('<div class="ui-tabs-scroll-container"></div>').prependTo(this.element);
                self.header = $('<div class="ui-tabs-nav-scrollable ui-widget-header ui-corner-all"></div>').prependTo(scrollContainer);
                var nav = self.element.find(".ui-tabs-nav:first").removeClass("ui-widget-header ui-corner-all").appendTo(this.header);
                var arrowsNav = $('<ol class="ui-helper-reset ui-helper-clearfix ui-tabs-nav-arrows"></ol>').prependTo(self.element);
                var navPrev = $('<li class="ui-tabs-arrow-previous ui-state-default ui-corner-bl ui-corner-tl" title="Previous"><a href="#"><span class="ui-icon ui-icon-carat-1-w">Previous tab</span></a></li>').prependTo(arrowsNav).hide(),
                    navNext = $('<li class="ui-tabs-arrow-next ui-state-default ui-corner-tr ui-corner-br" title="Next"><a href="#"><span class="ui-icon ui-icon-carat-1-e">Next tab</span></a></li>').appendTo(arrowsNav).hide();


                var scrollTo = function(to, delay) {
                    var navWidth = 0,
                        arrowWidth = navPrev.outerWidth(),
                        marginLeft = -(parseInt(nav.css("marginLeft"), 10)),
                        hwidth = self.header.width(),
                        newMargin = 0;

                    nav.find("li").each(function() {
                        navWidth += $(this).outerWidth(true);
                    });

                    if (to instanceof $.Event) {

                    } else {
                        newMargin = marginLeft+to;
                        if (newMargin > (navWidth-hwidth)) {
                            newMargin = (navWidth-hwidth);
                        } else if (newMargin < 0) {
                            newMargin = 0;
                        }
                        nav.stop(true).animate({
                            marginLeft: -(newMargin)
                        }, delay, function(){
                            $(window).trigger("resize.tabs");
                        });
                    }
                }


                var holdTimer = false;
                navPrev.add(navNext).bind({
                    "click": function(e) {
                        var isNext = this === navNext[0];
                        e.preventDefault();
                        if (o.changeOnScroll) {
                            self.select(self.options.selected + (isNext ? 1 : -1));
                        } else {
                            if (!holdTimer)
                                scrollTo(isNext ? 150 : -150, 250);
                        }
                    },
                    "mousedown": function(e){
                        if (!o.changeOnScroll) {
                            var isNext = this === navNext[0],
                                duration = 10, pos = 15, timer;
                            if (holdTimer)
                                clearTimeout(holdTimer);
                            holdTimer = setTimeout(timer = function(){
                                scrollTo(isNext ? pos : -(pos), duration);
                                holdTimer = setTimeout(arguments.callee, duration);
                            }, 150);
                        }
                    },
                    "mouseup mouseout": function(e){
                        if (!o.changeOnScroll) {
                            clearTimeout(holdTimer);
                            holdTimer = false;
                            nav.stop();
                        }
                    }
                });

                self.header.bind('mousewheel', function(e, d, dX, dY) {
                    e.preventDefault();
                    if (d === -1) {
                        navNext.click();
                    } else if (d === 1) {
                        navPrev.click();
                    }
                });

                $(window).bind("resize.tabs", function(e) {
                    var navWidth = 0;
                    var arrowWidth = navPrev.outerWidth();
                    nav.find("li").each(function() {
                        navWidth += $(this).outerWidth(true);
                    });

                    var marginLeft = -(parseInt(nav.css("marginLeft"), 10)),
                        hwidth = self.header.width();

                    if (navWidth > (hwidth+marginLeft)) {
                        self.header.addClass("ui-tabs-arrow-r");
                        navNext.show("fade");
                        if (marginLeft > 0) {
                            self.header.addClass("ui-tabs-arrow-l");
                            navPrev.show("fade");
                        } else {
                            self.header.removeClass("ui-tabs-arrow-l");
                            navPrev.hide("fade");
                        }
                    } else {
                        self.header.removeClass("ui-tabs-arrows ui-tabs-arrow-l");
                        navNext.hide("fade");
                        if (marginLeft > 0) {
                            self.header.addClass("ui-tabs-arrow-l");
                            navPrev.show("fade");
                        } else {
                            self.header.removeClass("ui-tabs-arrow-l");
                            navPrev.hide("fade");
                        }
                    }
                }).trigger("resize.tabs");

                arrowsNav.find("li").bind({
                    "mouseenter focus": function(e) {
                        $(this).addClass("ui-state-hover");
                    },
                    "mouseleave blur": function(e) {
                        $(this).removeClass("ui-state-hover");
                    }
                });

                this.anchors.bind("click.tabs", function(){
                    var li = $(this).parent(),
                        arrowWidth = navPrev.outerWidth(),
                        width = li.outerWidth(true),
                        hwidth = self.header.width(),
                        pos = li.position().left,
                        marginLeft = -(parseInt(nav.stop(true,true).css("marginLeft"),10)),
                        newMargin = -1;

                    if (li.index() === 0) {
                        newMargin = 0;
                    } else if ((pos+width) >= (hwidth+marginLeft)) {
                        newMargin = pos-hwidth+width;
                        if ((li.index()+1) < nav.find("li").length) {
                            newMargin += arrowWidth;
                        }
                    } else if (pos < marginLeft) {
                        newMargin = pos-arrowWidth;
                    }

                    if (newMargin > -1) {
                        nav.animate({
                            marginLeft: -(newMargin)
                        }, 250, function(){
                            $(window).trigger("resize.tabs");
                        });
                    }
                });
            }
            return self;
        },
        _update: function(){
            console.log(arguments);
            _super._update.apply(this);
        }
    });
    $.widget("xui.tabs", $.xui.tabs);
})(jQuery);
$(function() {
    $("#tabs").tabs({
        scrollable: true,
        changeOnScroll: false,
        closable: true
    });
    $("#switcher").themeswitcher();
});

1 个答案:

答案 0 :(得分:2)

我在jquery-ui 1.10.3和jquery-ui-1.9.2中找到了解决方法。 JQuery本身的版本似乎没有什么区别。

所以,在第427行的jquery-ui-1.10.3.custom.js

$.each( existingConstructor._childConstructors, function( i, child ) {

失败,因为使用此扩展名未定义_childConstructors。

我已经通过

解决了这个问题

在.each

之前添加一个检查以查看是否未定义existingConstructor._childConstructors

原始

    if ( existingConstructor ) {
            $.each( existingConstructor._childConstructors, function( i, child ) {
                    var childPrototype = child.prototype;

                    // redefine the child widget using the same prototype that was
                    // originally used, but inherit from the new version of the base
                    $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
            });
            // remove the list of existing child constructors from the old constructor
            // so the old child constructors can be garbage collected
            delete existingConstructor._childConstructors;
    } else {
            base._childConstructors.push( constructor );
    }

以便其中的代码读取

    if ( existingConstructor ) {
        if (!(typeof existingConstructor._childConstructors === 'undefined')) {
            $.each( existingConstructor._childConstructors, function( i, child ) {
                    var childPrototype = child.prototype;

                    // redefine the child widget using the same prototype that was
                    // originally used, but inherit from the new version of the base
                    $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
            });
            // remove the list of existing child constructors from the old constructor
            // so the old child constructors can be garbage collected
            delete existingConstructor._childConstructors;
        }
    } else {
            base._childConstructors.push( constructor );
    }

不是最好的解决方法,但它确实适用于jquery-ui-1.9.2和jquery-ui-1.10.3以及我尝试过的所有最近的jquery.js。

在jquery-ui-1.9.2.custom.js中,行号约为460