Skip to content

Instantly share code, notes, and snippets.

@scttnlsn
Last active December 17, 2015 16:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scttnlsn/5640917 to your computer and use it in GitHub Desktop.
Save scttnlsn/5640917 to your computer and use it in GitHub Desktop.
Flight-inspired mixin composition
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.js"></script>
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone.js"></script>
<script src="wings.js"></script>
<script>
function templatable() {
this.after('render', function () {
var context = _.result(this, 'context');
if (this.template) {
this.$el.html(this.template(context));
}
});
}
function submittable() {
this.events || (this.events = {});
this.events['submit form'] = function (e) {
e.preventDefault();
var data = {};
_.each(this.$('form').serializeArray(), function (item) {
data[item.name] = item.value;
});
if (this.submit) this.submit(data);
};
}
var ExampleView = wings(Backbone.View.extend(), function () {
this.context = function () {
return this.model.toJSON();
};
this.submit = function (data) {
this.model.set(data);
};
this.use(templatable, submittable);
this.after('initialize', function () {
this.template = _.template($('#example-template').html());
this.model = new Backbone.Model();
this.listenTo(this.model, 'change', this.render);
});
});
$(function () {
$('body').append(new ExampleView().render().el);
});
</script>
</head>
<body>
<script id="example-template" type="text/template">
<form>
<input type="text" name="name">
<input type="submit" value="Say Hello">
</form>
<% if (name) { %>
Hello <%= name %>
<% } %>
</script>
</body>
</html>
(function (name, root, factory) {
if (typeof exports == 'object') {
module.exports = factory();
} else if (typeof define == 'function' && define.amd) {
define(factory);
} else {
root[name] = factory();
}
})('wings', this, function () {
function use() {
var base = this;
this.use = function () {
var mixins = _.toArray(arguments);
_.each(mixins, function (mixin) {
mixin.call(base);
});
};
}
function hook() {
_.each(['before', 'after', 'around'], function (m) {
this[m] = function (method, wrapped) {
if (typeof this[method] == 'function') {
this[method] = hooks[m](this[method], wrapped);
} else {
this[method] = wrapped;
}
return this[method];
};
}, this);
var hooks = {
around: function (base, wrapped) {
return function () {
var args = _.toArray(arguments);
return wrapped.apply(this, [base.bind(this)].concat(args));
};
},
before: function (base, before) {
return hooks.around(base, function () {
var args = _.toArray(arguments);
var orig = args.shift();
before.apply(this, args);
return orig.apply(this, args);
});
},
after: function (base, after) {
return hooks.around(base, function () {
var args = _.toArray(arguments);
var orig = args.shift();
var res = orig.apply(this, args);
after.apply(this, args);
return res;
});
}
};
}
return function (klass, fn) {
var base = klass.prototype;
use.call(base);
hook.call(base);
fn.call(base);
return klass;
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment