Skip to content

Instantly share code, notes, and snippets.

@rodaine
Last active Dec 16, 2015
Embed
What would you like to do?
Code Snippets for my blog post "Unchain HTML and JavaScript using Dependency Injection" (http://clarknikdelpowell.com/blog/untangle-html-and-javascript-using-dependency-injection/)
$('#browsers, #web-team').on 'click', 'li', (e) ->
# get the clicked li as a jQuery object
$el = $ this
# get the whole list as a jQuery object
$delegate = $ e.delegateTarget
# the class to be toggled on the element
cls = 'active'
if 'web-team' == $delegate.attr('id')
# change class to 'on' and remove class from all other li's in the list
cls = 'on'
$delegate.children('li').removeClass cls
$this.addClass cls
else
# just toggle the class regardless of the rest of the li's
$this.toggleClass cls
<ul id="browsers">
<li>
<h2>Google Chrome</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Mozilla Firefox</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Apple Safari</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Microsoft Internet Explorer</h2>
<p><!-- the collapsable content --></p>
</li>
</ul>
<ul id="web-team">
<li>
<h2>Alex Nikdel</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Seth Wilson</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Glenn Welser</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Josh Nederveld</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Taylor Gorman</h2>
<p><!-- the collapsable content --></p>
</li>
<li>
<h2>Chris Roche</h2>
<p><!-- the collapsable content --></p>
</li>
</ul>
// Generated by CoffeeScript 1.6.3
$('#browsers, #web-team').on('click', 'li', function(e) {
var $delegate, $el, cls;
$el = $(this);
$delegate = $(e.delegateTarget);
cls = 'active';
if ('web-team' === $delegate.attr('id')) {
cls = 'on';
$delegate.children('li').removeClass(cls);
return $this.addClass(cls);
} else {
return $this.toggleClass(cls);
}
});
class Accordion
constructor: (@el) ->
@applyOptions()
@eventBindings()
applyOptions: ->
defaults = {
toggle: 'active'
behavior: 'radio'
}
@options = $.extend defaults, @el.data()
eventBindings: ->
that = this
@el.on 'click', 'li', -> that.toggle $ this
toggle: (item) ->
if @options.behavior == 'radio'
@el.children('li').removeClass @options.toggle
item.toggleClass @options.toggle
Bindable.register 'accordion', Accordion
<ul class="browsers accordion" data-bindable="accordion" data-behavior="checkbox">
<!-- same contents as before -->
</ul>
<ul class="web-team accordian" data-bindable="accordion" data-toggle="on">
<!-- same contents as before -->
</ul>
// Generated by CoffeeScript 1.6.3
var Accordion;
Accordion = (function() {
function Accordion(el) {
this.el = el;
this.applyOptions();
this.eventBindings();
}
Accordion.prototype.applyOptions = function() {
var defaults;
defaults = {
toggle: 'active',
behavior: 'radio'
};
return this.options = $.extend(defaults, this.el.data());
};
Accordion.prototype.eventBindings = function() {
var that;
that = this;
return this.el.on('click', 'li', function() {
return that.toggle($(this));
});
};
Accordion.prototype.toggle = function(item) {
if (this.options.behavior === 'radio') {
this.el.children('li').removeClass(this.options.toggle);
}
return item.toggleClass(this.options.toggle);
};
return Accordion;
})();
Bindable.register('accordion', Accordion);
# prepend jquery, bindable.coffee, accordion.v2.coffee
# and any other bindable classes used in this project
# with a utility like CodeKit, Grunt, Yeoman, etc...
new Bindable().bindAll()
# yes, that's it!
// Generated by CoffeeScript 1.6.3
var bindable;
bindable = new Bindable().bindAll();
###*
* bindable.coffee
*
* Bindable - Lightweight Dependency Injection
* A part of the Utensils Library
* https://github.com/modeset/utensils
*
* Documentation & Arrangement by Chris Roche
*
* @license MIT
* @copyright 2013 Mode Set
###
class Bindable
#----------------------------------------------------------------------------
# CLASS REGISTRATION
#----------------------------------------------------------------------------
###*
* Registers a class with the utility to be bound on elements with the
* specified key.
* @param {string} key The key used to link DOM elements to the class
* @param {class} klass The class bound to elements with the given key
* @return null
###
@register: (key, klass) ->
@registry ?= {}
@registry[key] = {class: klass}
return null
###*
* Gets the registered class associated with a key, if one exists
* @param {string} key The key of the class
* @return {class} The class associated with key, else null
###
@getClass: (key) ->
@registry[key]?.class
#----------------------------------------------------------------------------
# ELEMENT BINDING
#----------------------------------------------------------------------------
###*
* Binds an element with the class associated with its key
* @param {HtmlElement} el The DOM element that will be bound to
* @param {string} dataKey=@dataKey The attribute on the element containing the key
* @return this
###
bind: (el, dataKey=@dataKey) ->
el = $(el)
key = el.data(dataKey)
if _class = @constructor.getClass(key)
el.data(@instanceKey, new _class(el)) unless el.data(@instanceKey)
else
console?.error "Bindable for key: #{key} not found in Bindable.registry for instance", el
@
###*
* Binds all DOM elements of this instance with their associated classes
* @return this
###
bindAll: ->
@bind(el) for el in @bindables
@
#----------------------------------------------------------------------------
# LIFECYCLE
#----------------------------------------------------------------------------
###*
* Creates a new Bindable instance with associated context and dataKey
* @param {jQuery Object} context=$('body') Where to search for bindable elements
* @param {string} dataKey='bindable' The data attribute to bind against
###
constructor: (context=$('body'), @dataKey='bindable')->
@bindables = $("[data-#{@dataKey}]", context)
@instanceKey = "#{@dataKey}-instance"
###*
* Gets all the bindable objects on the page for this instance
* @return {array} Instances of the bindable classes applied to the page
###
getRefs: ->
$(bindable).data(@instanceKey) for bindable in @bindables
###*
* Cleans up all bound objects (memory management)
* @return this
###
dispose: ->
for bindable in @bindables
bindable = $(bindable)
if instance = bindable.data(@instanceKey)
instance.release() if typeof instance?.release is 'function'
instance.dispose() if typeof instance?.dispose is 'function'
bindable.data(@instanceKey, null)
delete @bindables
@bindables = []
@
###*
* @deprecated
###
release: ->
@dispose()
// Generated by CoffeeScript 1.3.3
/**
* bindable.js
*
* Bindable - Lightweight Dependency Injection
* A part of the Utensils Library
* https://github.com/modeset/utensils
*
* Documentation & Arrangement by Chris Roche
*
* @license MIT
* @copyright 2013 Mode Set
*/
var Bindable;
Bindable = (function() {
/**
* Registers a class with the utility to be bound on elements with the
* specified key.
* @param {string} key The key used to link DOM elements to the class
* @param {class} klass The class bound to elements with the given key
* @return null
*/
Bindable.register = function(key, klass) {
var _ref;
if ((_ref = this.registry) == null) {
this.registry = {};
}
this.registry[key] = {
"class": klass
};
return null;
};
/**
* Gets the registered class associated with a key, if one exists
* @param {string} key The key of the class
* @return {class} The class associated with key, else null
*/
Bindable.getClass = function(key) {
var _ref;
return (_ref = this.registry[key]) != null ? _ref["class"] : void 0;
};
/**
* Binds an element with the class associated with its key
* @param {HtmlElement} el The DOM element that will be bound to
* @param {string} dataKey=@dataKey The attribute on the element containing the key
* @return this
*/
Bindable.prototype.bind = function(el, dataKey) {
var key, _class;
if (dataKey == null) {
dataKey = this.dataKey;
}
el = $(el);
key = el.data(dataKey);
if (_class = this.constructor.getClass(key)) {
if (!el.data(this.instanceKey)) {
el.data(this.instanceKey, new _class(el));
}
} else {
if (typeof console !== "undefined" && console !== null) {
console.error("Bindable for key: " + key + " not found in Bindable.registry for instance", el);
}
}
return this;
};
/**
* Binds all DOM elements of this instance with their associated classes
* @return this
*/
Bindable.prototype.bindAll = function() {
var el, _i, _len, _ref;
_ref = this.bindables;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
el = _ref[_i];
this.bind(el);
}
return this;
};
/**
* Creates a new Bindable instance with associated context and dataKey
* @param {jQuery Object} context=$('body') Where to search for bindable elements
* @param {string} dataKey='bindable' The data attribute to bind against
*/
function Bindable(context, dataKey) {
if (context == null) {
context = $('body');
}
this.dataKey = dataKey != null ? dataKey : 'bindable';
this.bindables = $("[data-" + this.dataKey + "]", context);
this.instanceKey = "" + this.dataKey + "-instance";
}
/**
* Gets all the bindable objects on the page for this instance
* @return {array} Instances of the bindable classes applied to the page
*/
Bindable.prototype.getRefs = function() {
var bindable, _i, _len, _ref, _results;
_ref = this.bindables;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
bindable = _ref[_i];
_results.push($(bindable).data(this.instanceKey));
}
return _results;
};
/**
* Cleans up all bound objects (memory management)
* @return this
*/
Bindable.prototype.dispose = function() {
var bindable, instance, _i, _len, _ref;
_ref = this.bindables;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
bindable = _ref[_i];
bindable = $(bindable);
if (instance = bindable.data(this.instanceKey)) {
if (typeof (instance != null ? instance.release : void 0) === 'function') {
instance.release();
}
if (typeof (instance != null ? instance.dispose : void 0) === 'function') {
instance.dispose();
}
bindable.data(this.instanceKey, null);
}
}
delete this.bindables;
this.bindables = [];
return this;
};
/**
* @deprecated
*/
Bindable.prototype.release = function() {
return this.dispose();
};
return Bindable;
})();
/**
* app.js : What you'll see on a typical marketings site.
*/
jQuery(function($) {
$('.slides').slideshow({'style':'push','speed':'600'});
// Maybe a couple more event bindings...
});
/**
* app.js : The file that runs after all your dependencies
* are loaded on the page ... Look familiar?
*/
jQuery(function($) {
$('#toggle-active-list').on('click', function() {
/* DO SOMETHING */
});
$('#toggle-inactive-list').on('click', function() {
/* DO SOMETHING SLIGHTLY DIFFERENT THAN ABOVE */
});
$('.list a').on('click', function() {
/* SOMETHING ELSE */
});
$('#edit-dialog').dialog({
/* CONFIG INCLUDING ... */
close: function() { /* CALLBACK */ },
buttons: {
'Cancel': function() { /* MORE CALLBACKS */ },
'Save': function() {
$.ajax({
success: function() { /* WELCOME TO CALLBACK HELL */ }
})
}
}
});
// 500 Lines Later?
// 1000 Lines Later?
// 10K Lines Later?!
/*EOF*/ });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment