jquery 插件控制器互相覆盖

发布于 2024-11-04 15:02:05 字数 9675 浏览 0 评论 0原文

我使用两个 jquery 插件(一个用于选项卡,一个用于缩略图库)来创建选项卡式库。一切都很顺利,直到我尝试引入一个简单的 mvc 模式。现在,不知何故,第二个初始化的插件的控制器会覆盖第一个插件 - 当第一个插件尝试使用第二个插件的控制器时,导致大量“new_view.tab 未定义”。

的代码

( function( $ ) {

// private vars
var settings;

var Model = ( function( ) {
    var pub = { };
        current_view = null;

    pub.get_current = function( ) {
        if( current_view ) {
            return current_view;
        } else {
            return false;
        }
    }
    pub.set_current = function( new_view ) {
        if( current_view ) console.log( 'current view is ' + current_view.number );
        current_view = new_view;
        if( current_view ) console.log( 'current view is now ' +current_view.number );
    }
    return pub;
})( );

var Controller = ( function( Model ) {
    var pub = { };
        model = Model;

    pub.update = function( new_view ) {
        console.log( 'tab controller update' );

        settings.update( model.get_current_view, new_view, function( callback ) {
            if( model.get_current( ) ) {
                model.get_current( ).tab.removeClass( settings.active_class );
            }
            model.set_current( new_view );
            new_view.tab.addClass( settings.active_class );
        });
    }
    pub.close = function( new_view ) {
        settings.close_callback(  );
        pub.model.set_current( null );
    }
    console.log( 'in tabs controller');
    console.log( pub );
    return pub;
})( Model );

console.log( 'in tabs')
console.log( Controller );

var View = ( function( Controller ) {
    var pub = { };
        controller = Controller;

    pub.update = function( new_view ) {
        controller.update( new_view );
    }

    pub.close = function( new_view ) {
        controller.update( new_view );
    }

    return pub;
})( Controller );

/* private closures */
function Tab( tab, tab_content, close, number ) {
    this.tab = tab;
    this.tab_content = tab_content;
    this.close = close;
    this.number = number;
    var Tab = this;

    // listeners
    tab.bind( 'click.tab', function( evnt ) {
        console.log( 'tab' + number + ' clicked' );
        evnt.preventDefault( );
        if( Tab.tab.hasClass( settings.active_class ) ) return;
        Tab.update( Tab );
    });

    close.bind( 'click.close', function( evnt ) {
        console.log( 'tab' + number + ' close clicked' );
        evnt.preventDefault( );
        Tab.close( Tab );
    });
}
Tab.prototype = View;

//public methods
var methods = {
    init : function( options ) {

        //defaults
        var defaults = {
            'tab_class': 'tab',
            'content_class' : 'content',
            'close_class': 'close',
            'active_class': 'active',
            'animate_open': function( arg ) {
                $( arg ).show( );
            },
            'animate_close': function( arg ) {
                $( arg ).hide( );
            },
            'tab_click_callback': function( ) { },
            'close_callback': function( ){ }
        };

        return this.each( function( ) {
            //update defaults with user options
            if( options ) {
                settings = $.extend( true, { }, defaults, options );
            } else {
                settings = defaults;
            }

            var container = $( this );
            var tabs = $( '.' + settings.tab_class, container ).children( );
            var content = $( '.' + settings.content_class, container );
            var close = $( '.' + settings.close_class, container );
            var len = tabs.length;
            var i = 0;
            tabs.each( function( index ) {
                var current_tab = $( this );
                new Tab( current_tab, $( content[ index ] ), $( close[ index ] ), index + 1 );
            });
        });//end return
    },//end init
    destroy: function( ) {
        return this.each( function( ) {
            methods = null;
        });
    }
};//end methods

//add function to jquery
$.fn.id_tabs = function( method ) {
    if ( methods[method] ) {
        return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Method ' +  method + ' does not exist on jQuery.id_tabs' );
    }    
};

})(jQuery);

这是选项卡和画廊

(function($) {

var settings;

/* private */   
var Model = ( function( ) {
    var pub = { };
        current_view = null;

    pub.get_current = function( ) {
        if( current_view ) {
            return current_view;
        } else {
            return false;
        }
    }
    pub.set_current = function( new_view ) {
        if( current_view ) console.log( 'current view is ' + current_view.number );
        current_view = new_view;
        if( current_view ) console.log( 'current view is now ' +current_view.number );
    }
    return pub;
})( );

var Controller = ( function( Model ) {
    var pub = { };
        model = Model;

    pub.update = function( view ) {
        console.log( 'gallery controller update' );
        settings.update( model.current_view, view );
        if( model.get_current( ) ) {
            model.get_current( ).thumb.removeClass( settings.active_class );
        }
        model.set_current( view );
        view.thumb.addClass( settings.active_class );
    }
    console.log( 'in gallery controller');
    console.log( pub );
    return pub;
})( Model );

console.log( 'in gallery');
console.log( Controller );

var View = ( function( Controller ) {
    var pub = { };
        controller = Controller;

    console.log( 'in gallery view' );
    console.log( controller );

    pub.update = function( new_view ) {
        console.log( 'in gallery update');
        console.log( controller );
        controller.update( new_view );
    }
    return pub;
})( Controller );

function Thumb( thumb, pic, number ) {
    this.thumb = thumb;
    this.pic = pic;
    this.number = number;
    var Thumb = this;

    this.hide = function( callback ) {

        console.log( Thumb );
        settings.animate_out( Thumb, function( ) {
            if( callback ) callback( );
        });
    }
    this.show = function( callback ) {
        console.log( Thumb );
        settings.animate_in( Thumb, function( ) { 
            if( callback ) callback( );
        });
    }
    thumb.bind( 'click.thumb', function( evnt ) {
        console.log( 'pic' + number + ' clicked' );
        evnt.preventDefault( );
        if( Thumb.thumb.hasClass( settings.active_class ) ) return;
        Thumb.update( Thumb );
    });
};
Thumb.prototype = View;

/* public */
var methods = {
    init : function( options ) {

        //defaults
        var defaults = {
            'container_id': 'content',
            'active_class' : 'active',
            'movie_class': 'movie',
            'animate_in': function( arg ) {
                $( arg ).fadeIn( );
            },
            'animate_out': function( arg, callback ) {
                $( arg ).fadeOut( );
                callback( );                    
            },
            'update' : function( current, new_view, callback) {
                if( current ) current.pic.fadeOut( );
                new_view.pic.fadeIn( );
                if( callback ) callback( );
            }
        };

        return this.each( function( ) {
            //update defaults with user options
            if( options ) {
                settings = $.extend( true, { }, defaults, options );
            } else {
                settings = defaults;
            }

            var obj = $( this );
            var li = $( 'li', obj );
            var obj_class = obj.attr( 'id' );
            var container = $( '#' + settings.container_id );
            var content = $( '.' + obj_class, container );

            li.each( function( index ) {
                var current_li = $( this );
                var current_content = $( content[ index ] );
                var src = current_li.children( ).children( ).hide( ).attr( 'src');
                var href = current_li.children( ).attr( 'href');
                current_li.css( 'background-image', 'url(' + src + ')' );
                current_content.css( 'background-image', 'url(' + href + ')' );         
                new Thumb( current_li, current_content, index );
            });
        });//end return
    },//end init
    destroy: function( ) {
        return this.each( function( ) {
            methods = null;
        });
    },
    hide_current: function( callback ) {
        console.log( 'hide_current' );
        if( Model.current_view ) {
            settings.animate_out( Model.current_view, function( ) {
                Model.current_view.thumb.removeClass( settings.active_class );
                Model.current_view = null;
                if( callback ) callback( );
            });
        } else {
            callback( );
        }
    }
};//end public methods

//add function to jquery
$.fn.id_gallery = function( method ) {
    if ( methods[method] ) {
        return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Method ' +  method + ' does not exist on jquery.id_gallery' );
    }    
};

})(jQuery);

,我假设有些东西正在作用域链上爬行,但是由于“控制器”在每个闭包中本地定义,我不明白如何进行。

更令人沮丧的是,我启动了一个 jsFiddle 并让它在那里工作,但我一生都无法弄清楚它与我的生产代码之间的区别。 http://jsfiddle.net/noTxt/vWsJw/

请帮忙

I'm using two jquery plugins - one for tabs and one for a thumbnail gallery - to create a tabbed gallery. Everything was going smoothly until I tried to introduce a simple mvc pattern. Now, somehow, the controller from whichever plugin is initialized second overrides the first one - leading to a lot of "new_view.tab is undefined" as the first plugin tries to use the second's controller.

Here's the code for tabs

( function( $ ) {

// private vars
var settings;

var Model = ( function( ) {
    var pub = { };
        current_view = null;

    pub.get_current = function( ) {
        if( current_view ) {
            return current_view;
        } else {
            return false;
        }
    }
    pub.set_current = function( new_view ) {
        if( current_view ) console.log( 'current view is ' + current_view.number );
        current_view = new_view;
        if( current_view ) console.log( 'current view is now ' +current_view.number );
    }
    return pub;
})( );

var Controller = ( function( Model ) {
    var pub = { };
        model = Model;

    pub.update = function( new_view ) {
        console.log( 'tab controller update' );

        settings.update( model.get_current_view, new_view, function( callback ) {
            if( model.get_current( ) ) {
                model.get_current( ).tab.removeClass( settings.active_class );
            }
            model.set_current( new_view );
            new_view.tab.addClass( settings.active_class );
        });
    }
    pub.close = function( new_view ) {
        settings.close_callback(  );
        pub.model.set_current( null );
    }
    console.log( 'in tabs controller');
    console.log( pub );
    return pub;
})( Model );

console.log( 'in tabs')
console.log( Controller );

var View = ( function( Controller ) {
    var pub = { };
        controller = Controller;

    pub.update = function( new_view ) {
        controller.update( new_view );
    }

    pub.close = function( new_view ) {
        controller.update( new_view );
    }

    return pub;
})( Controller );

/* private closures */
function Tab( tab, tab_content, close, number ) {
    this.tab = tab;
    this.tab_content = tab_content;
    this.close = close;
    this.number = number;
    var Tab = this;

    // listeners
    tab.bind( 'click.tab', function( evnt ) {
        console.log( 'tab' + number + ' clicked' );
        evnt.preventDefault( );
        if( Tab.tab.hasClass( settings.active_class ) ) return;
        Tab.update( Tab );
    });

    close.bind( 'click.close', function( evnt ) {
        console.log( 'tab' + number + ' close clicked' );
        evnt.preventDefault( );
        Tab.close( Tab );
    });
}
Tab.prototype = View;

//public methods
var methods = {
    init : function( options ) {

        //defaults
        var defaults = {
            'tab_class': 'tab',
            'content_class' : 'content',
            'close_class': 'close',
            'active_class': 'active',
            'animate_open': function( arg ) {
                $( arg ).show( );
            },
            'animate_close': function( arg ) {
                $( arg ).hide( );
            },
            'tab_click_callback': function( ) { },
            'close_callback': function( ){ }
        };

        return this.each( function( ) {
            //update defaults with user options
            if( options ) {
                settings = $.extend( true, { }, defaults, options );
            } else {
                settings = defaults;
            }

            var container = $( this );
            var tabs = $( '.' + settings.tab_class, container ).children( );
            var content = $( '.' + settings.content_class, container );
            var close = $( '.' + settings.close_class, container );
            var len = tabs.length;
            var i = 0;
            tabs.each( function( index ) {
                var current_tab = $( this );
                new Tab( current_tab, $( content[ index ] ), $( close[ index ] ), index + 1 );
            });
        });//end return
    },//end init
    destroy: function( ) {
        return this.each( function( ) {
            methods = null;
        });
    }
};//end methods

//add function to jquery
$.fn.id_tabs = function( method ) {
    if ( methods[method] ) {
        return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Method ' +  method + ' does not exist on jQuery.id_tabs' );
    }    
};

})(jQuery);

and for the gallery

(function($) {

var settings;

/* private */   
var Model = ( function( ) {
    var pub = { };
        current_view = null;

    pub.get_current = function( ) {
        if( current_view ) {
            return current_view;
        } else {
            return false;
        }
    }
    pub.set_current = function( new_view ) {
        if( current_view ) console.log( 'current view is ' + current_view.number );
        current_view = new_view;
        if( current_view ) console.log( 'current view is now ' +current_view.number );
    }
    return pub;
})( );

var Controller = ( function( Model ) {
    var pub = { };
        model = Model;

    pub.update = function( view ) {
        console.log( 'gallery controller update' );
        settings.update( model.current_view, view );
        if( model.get_current( ) ) {
            model.get_current( ).thumb.removeClass( settings.active_class );
        }
        model.set_current( view );
        view.thumb.addClass( settings.active_class );
    }
    console.log( 'in gallery controller');
    console.log( pub );
    return pub;
})( Model );

console.log( 'in gallery');
console.log( Controller );

var View = ( function( Controller ) {
    var pub = { };
        controller = Controller;

    console.log( 'in gallery view' );
    console.log( controller );

    pub.update = function( new_view ) {
        console.log( 'in gallery update');
        console.log( controller );
        controller.update( new_view );
    }
    return pub;
})( Controller );

function Thumb( thumb, pic, number ) {
    this.thumb = thumb;
    this.pic = pic;
    this.number = number;
    var Thumb = this;

    this.hide = function( callback ) {

        console.log( Thumb );
        settings.animate_out( Thumb, function( ) {
            if( callback ) callback( );
        });
    }
    this.show = function( callback ) {
        console.log( Thumb );
        settings.animate_in( Thumb, function( ) { 
            if( callback ) callback( );
        });
    }
    thumb.bind( 'click.thumb', function( evnt ) {
        console.log( 'pic' + number + ' clicked' );
        evnt.preventDefault( );
        if( Thumb.thumb.hasClass( settings.active_class ) ) return;
        Thumb.update( Thumb );
    });
};
Thumb.prototype = View;

/* public */
var methods = {
    init : function( options ) {

        //defaults
        var defaults = {
            'container_id': 'content',
            'active_class' : 'active',
            'movie_class': 'movie',
            'animate_in': function( arg ) {
                $( arg ).fadeIn( );
            },
            'animate_out': function( arg, callback ) {
                $( arg ).fadeOut( );
                callback( );                    
            },
            'update' : function( current, new_view, callback) {
                if( current ) current.pic.fadeOut( );
                new_view.pic.fadeIn( );
                if( callback ) callback( );
            }
        };

        return this.each( function( ) {
            //update defaults with user options
            if( options ) {
                settings = $.extend( true, { }, defaults, options );
            } else {
                settings = defaults;
            }

            var obj = $( this );
            var li = $( 'li', obj );
            var obj_class = obj.attr( 'id' );
            var container = $( '#' + settings.container_id );
            var content = $( '.' + obj_class, container );

            li.each( function( index ) {
                var current_li = $( this );
                var current_content = $( content[ index ] );
                var src = current_li.children( ).children( ).hide( ).attr( 'src');
                var href = current_li.children( ).attr( 'href');
                current_li.css( 'background-image', 'url(' + src + ')' );
                current_content.css( 'background-image', 'url(' + href + ')' );         
                new Thumb( current_li, current_content, index );
            });
        });//end return
    },//end init
    destroy: function( ) {
        return this.each( function( ) {
            methods = null;
        });
    },
    hide_current: function( callback ) {
        console.log( 'hide_current' );
        if( Model.current_view ) {
            settings.animate_out( Model.current_view, function( ) {
                Model.current_view.thumb.removeClass( settings.active_class );
                Model.current_view = null;
                if( callback ) callback( );
            });
        } else {
            callback( );
        }
    }
};//end public methods

//add function to jquery
$.fn.id_gallery = function( method ) {
    if ( methods[method] ) {
        return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
    } else if ( typeof method === 'object' || ! method ) {
        return methods.init.apply( this, arguments );
    } else {
        $.error( 'Method ' +  method + ' does not exist on jquery.id_gallery' );
    }    
};

})(jQuery);

I assume that something is crawling up the scope chain, but with "Controller" defined locally within each closure, I don't understand how.

Even more frustrating, I started a jsFiddle and got it working there, but cannot for the life of me figure out the difference between that and my production code.
http://jsfiddle.net/noTxt/vWsJw/

please help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

羁客 2024-11-11 15:02:05

我不熟悉这种编写 jQuery 插件的风格,所以也许我遗漏了一些明显的东西,但我确实看到有一个名为“controller”的全局变量在两个地方都分配了。这也许是问题所在?

I'm not familiar with this style of writing plugins for jQuery so perhaps I'm missing something obvious, but I do see that there is a global variable called "controller" that is assigned in both places. Is this perhaps the issue?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文