Javascript jquery插件控制器相互覆盖
我正在使用两个jquery插件——一个用于选项卡,另一个用于缩略图库——来创建选项卡库。在我尝试引入一个简单的mvc模式之前,一切都进展顺利。现在,不知何故,第二个插件初始化后的控制器会覆盖第一个插件-当第一个插件尝试使用第二个插件的控制器时,会导致很多“new_view.tab未定义” 以下是选项卡的代码Javascript jquery插件控制器相互覆盖,javascript,jquery,inheritance,jquery-plugins,scope,Javascript,Jquery,Inheritance,Jquery Plugins,Scope,我正在使用两个jquery插件——一个用于选项卡,另一个用于缩略图库——来创建选项卡库。在我尝试引入一个简单的mvc模式之前,一切都进展顺利。现在,不知何故,第二个插件初始化后的控制器会覆盖第一个插件-当第一个插件尝试使用第二个插件的控制器时,会导致很多“new_view.tab未定义” 以下是选项卡的代码 ( function( $ ) { // private vars var settings; var Model = ( function( ) { var pub = { }
( 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);
我假设某个东西正在范围链上爬行,但由于在每个闭包中本地定义了“控制器”,我不明白如何进行
更令人沮丧的是,我启动了一个JSFIDLE并在那里工作,但我一辈子都无法找出它与我的生产代码之间的区别。
请帮助我不熟悉为jQuery编写插件的这种风格,因此可能我遗漏了一些明显的东西,但我确实看到有一个名为“controller”的全局变量在这两个位置都赋值。这可能就是问题所在吗?完全是。昨天一整天都在折磨我的人。谢谢。一般来说,我对编写jquery插件和javascript还不熟悉。但是我已经读了很多关于它的书(大部分是博客之类的),所以我把这些第一次尝试的东西拼凑在一起,从我觉得有意义的地方。如果你知道更好的方法,或者如何改进这种风格,我很想听听你的想法。我从来没有专门使用MVC模式编写过jQuery插件,但看起来它可能是一个很好的例子。