2011-05-02 122 views
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/

请帮助

回答

0

我不熟悉这种风格编写插件的jQuery所以也许我失去了一些东西明显,但我确实看到有一个叫“控制器”全局变量是在两地分配。这可能是问题吗?

+0

它完全是。昨天我所有人都在杀我。谢谢。 – noTxt 2011-05-02 16:10:21

+0

我是新来编写jquery插件和JavaScript的一般。但我一直在做一些关于它的阅读 - (主要是博客等) - 所以我有点从这些有意义的东西拼凑起来。如果你知道更好的方式,或者如何改进这种风格,我很乐意听到你的想法。 – noTxt 2011-05-02 16:13:33

+0

我从来没有写过一个使用MVC模式的jQuery插件,但[this](http://plugins.jquery.com/project/jQuery-MVC)看起来可能是一个很好的例子。 – Dan 2011-05-02 17:21:20