0
我使用两个jQuery插件 - 一个用于制表符,一个用于缩略图库 - 创建一个选项卡式的画廊。一切都很顺利,直到我试图引入一个简单的MVC模式。现在,无论如何,来自任何插件初始化的控制器都会覆盖第一个插件 - 导致很多“new_view.tab未定义”,因为第一个插件尝试使用第二个控制器。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);
我认为有些事情是爬上范围链标签
(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);
和画廊中的代码,但与“控制器”每个封闭内本地定义,我不明白如何。
更令人沮丧的是,我创建了一个jsFiddle并在那里工作,但是不能在我的生活中找出它和我的生产代码之间的区别。 http://jsfiddle.net/noTxt/vWsJw/
请帮助
它完全是。昨天我所有人都在杀我。谢谢。 – noTxt 2011-05-02 16:10:21
我是新来编写jquery插件和JavaScript的一般。但我一直在做一些关于它的阅读 - (主要是博客等) - 所以我有点从这些有意义的东西拼凑起来。如果你知道更好的方式,或者如何改进这种风格,我很乐意听到你的想法。 – noTxt 2011-05-02 16:13:33
我从来没有写过一个使用MVC模式的jQuery插件,但[this](http://plugins.jquery.com/project/jQuery-MVC)看起来可能是一个很好的例子。 – Dan 2011-05-02 17:21:20