What makes Modularity stand out is that it scales very well with complexity, has a tiny footprint (1.3k compressed), is nicely testable, and overall does not get in the way of the expert developer.
If some of the existing MVC frameworks fit your use case, use them! If your app is not primarily data driven, or want to stay more in control of what happens on your page and when, Modularity might be a good lightweight and general-purpose infrastructure to make your life easier.
Each module is responsible for everything that happens inside its part of the web page.
Let's build a button that displays how often it was clicked. It should also have a switch to reset the counter. All we need for it is an empty container element.
Let's define a module for it.
# A button that displays how often it was clicked.# Each module must be given its container as the first argument of the constructor.# The container is the DOM element that contains all of the module content.## Everything that is happening inside the container is the# responsibility of this module. Nothing that happens outside of this# container element is a concern for the module. Anything that this# module does must happen inside the container.constructorsuper # Every module must call the superclass constructor.# Optionally create some DOM content, if it doesn't exist already.# This could also be done with a templating library.containerhtml """You have clicked me <span class="click_count">0</span> times.<div class="reset"></div>"""# This DOM attribute makes the click counter element easier accessible.# The @$ method runs jQuery only for elements inside this module's container.@click_count_display = @$'.click_count'# A data attribute, representing how often has the button has been clicked so far.@click_count = parseInt@click_count_displaytext# An embedded module. Modularity allows (and encourages) to compose modules# out of other modules or raw DOM elements.## In this case, the "ResetSwitch" module takes care of the "reset" switch# for this button. We don't care how it does that. It could listen to# mouse clicks, keyboard hotkeys, swiping gestures, or shaking of the# mobile device that this page runs on etc. All of this functionality is# encapsulated in the "ResetSwitch" module.# All we care about here is that the "ResetSwitch" module fires a# "triggered" event when the user activated the reset switch.@reset_switch = '.reset'# Automatically wire up event handlers.# See for how this works.eventualize this# Called when the user clicks on this button.: =>@click_count++@update_click_count_display# Called when the user triggers the 'reset' switch.: =>@click_count = 0@update_click_count_display# Updates the click counter display with the current click count.: ->@click_count_displayhtml @click_count# Let's make this a bit fancy, and indicate with colors whether the# button has been clicked enough.if @click_count_display > 3@containeraddClass 'green'else@containerremoveClass 'green'
To instantiate our CounterButton, all we have to do is give it the container element:
Similar to Ruby mixins, mixins in Modularity allow to include orthogonal functional aspects defined in separate objects into a class.
myMixin =# This will be called when an instance of a class that includes this mixin is created.: -># This method will be available in every class that includes this mixin.: ->@mixin myMixin:# The super constructor will call the mixin constructors here.super# ...
gulp build(you should not do this manually, tools/release does this for you)