jquery插件控制器会互相覆盖

时间:2011-05-02 00:20:33

标签: javascript jquery inheritance jquery-plugins scope

我正在使用两个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);

我假设某些东西正在爬行范围链,但是在每个闭包中本地定义了“Controller”,我不明白如何。

更令人沮丧的是,我开始使用jsFiddle并让它在那里工作,但不能为我的生活找出它和我的生产代码之间的区别。 http://jsfiddle.net/noTxt/vWsJw/

请帮助

1 个答案:

答案 0 :(得分:0)

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