jQuery UI Tabs Plugin Broke

荒凉一梦 提交于 2019-12-12 21:03:57

问题


We are using the jquery ui tabs arrow plugin from this fiddle: http://jsfiddle.net/dECtZ/282/, but like many plugins, it breaks with the latest version of jQuery. We were able to get the csscur to work, but still get the following error in the jquery core (line 353):

Uncaught TypeError: Cannot assign to read only property 'length' of function (e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)}

Code is as follows:

(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:


I've found a work around in both jquery-ui 1.10.3 and jquery-ui-1.9.2. The version of JQuery itself didn't seem to make a difference.

So, in jquery-ui-1.10.3.custom.js at line 427

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

fails because _childConstructors is undefined with this extension.

I've worked around it by

adding a check to see if existingConstructor._childConstructors is undefined or not before the .each

original

    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 );
    }

so that the code in that reads

    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 );
    }

Not the best workaround, but it does work with jquery-ui-1.9.2 and jquery-ui-1.10.3 and for all the recent jquery.js I've tried.

In jquery-ui-1.9.2.custom.js the the line number about 460



来源:https://stackoverflow.com/questions/13427834/jquery-ui-tabs-plugin-broke

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!