Skip to content

Instantly share code, notes, and snippets.

@stephenplusplus
Last active December 14, 2015 12:08
Show Gist options
  • Save stephenplusplus/5083898 to your computer and use it in GitHub Desktop.
Save stephenplusplus/5083898 to your computer and use it in GitHub Desktop.
DI thing.
// Create a module for the application.
var app = things('taptap');
// A "Service" is a once-instantiated, injectable dependency your app may need.
// "User" is a service that will handle the functionality of logging in and out
// a user. Note that it lists "Store" in the signature of the function. This
// will be caught by "thing.js" and injected into the function when it is
// called.
app.service('User', function(Store) {
var loggedIn = !!Store.getItem('User');
var isLoggedIn = function() {
return loggedIn;
};
var logIn = function(username) {
Store.setItem('User', username);
loggedIn = true;
};
var logOut = function() {
Store.removeItem('User');
loggedIn = false;
};
return {
isLoggedIn: isLoggedIn,
logIn: logIn,
logOut: logOut
};
});
// "Store" is a localStorage-y bucket that you can drop things in for the life
// of the session.
app.service('Store', function(Feature) {
if (Feature.localStorage) {
return Feature.localStorage;
}
var Store = {};
this.setItem = function(name, value) {
Store[name] = value;
};
this.getItem = function(name) {
return Store[name];
};
this.removeItem = function(name) {
delete Store[name];
};
});
// We'll see what features we support.
app.service('Feature', function(root) {
this.touch = false; // Modernizr.touch?
this.localStorage = root.localStorage;
});
// You can also declare a "thing". A function, an array, anything.
app.thing('root', window);
app.thing('$', function() {
var forEach = Array.prototype.forEach;
var matches = [];
var api = {
html: function(newString) {
forEach.call(matches, function(match) {
match.innerHTML = newString;
});
}
};
return function(str) {
matches = document.querySelectorAll(str);
return api;
}
});
app.service('goTo', function() {
return app.goTo;
});
app.thing('States', [
'Alabama',
'Alaska',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Connecticut',
'Delaware',
'Florida',
'Georgia',
'Hawaii',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Kansas',
'Kentucky',
'Louisiana',
'Maine',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana',
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota',
'Ohio',
'Oklahoma',
'Oregon',
'Pennsylvania',
'Rhode Island',
'South Carolina',
'South Dakota',
'Tennessee',
'Texas',
'Utah',
'Vermont',
'Virginia',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming'
]);
// A "route" is like a "page" of your app.
app.route('/', function(User, goTo, $) {
if (User.isLoggedIn())
goTo('/usa');
else
$('body').html('Ha! You\'re not logged in.');
});
app.route('/login', function(root, User, goTo, $) {
User.logIn('stephen');
if (User.isLoggedIn()) {
$('body').html('Hey! Thanks for logging in, Stephen! You\'ll be re-directed momentarily.');
}
});
app.route('/logout', function(User, goTo) {
User.logOut();
if (!User.isLoggedIn()) {
goTo('/');
}
});
app.route('/usa', function($, States) {
$('body').html(States.join(', '));
});
app.boots(function(root, goTo) {
goTo('/');
root.setTimeout(function() {
goTo('/login');
}, 2000);
root.setTimeout(function() {
goTo('/');
}, 4000);
root.setTimeout(function() {
goTo('/logout');
}, 6000);
});
(function(root) {
var is = function (thing, type) { return typeof thing === type; }
, isDefined = function(thing) { return !isUndefined(thing); }
, isUndefined = function(thing) { return is(thing, 'undefined'); }
, isFunction = function(thing) { return is(thing, 'function'); }
, isString = function(thing) { return is(thing, 'string'); };
root.things = (function() {
var allOfTheThings = {}
, dependencyTypes = ['route', 'service', 'thing'];
var registerDependency = function(module, type, name, value) {
var dependency = module[type][name] = value;
if (isFunction(value)) {
var dependencies = value.toString().match(/^\s*function\s*\((.*?)\)/);
dependency.__dependencies = dependencies && dependencies[1] !== ''? dependencies[1].replace(/\s/g, '').split(',') : [];
}
if (type === 'service')
dependency.__invoked = false;
};
var requestDependency = function(module, name, type) {
var returnDependency = {
dependencyType: undefined,
dependency: undefined
};
if (!isDefined(name) && !isDefined(type))
// Nothing provided to us! Abort!
return returnDependency;
if (isDefined(name) && isDefined(type))
// We know exactly what we want.
returnDependency.dependencyType = type,
returnDependency.dependency = module[type][name];
else
// Let's go digging for it.
returnDependency.dependency = dependencyTypes.filter(function(depType) {
if (isDefined(module[depType][name])) {
returnDependency.dependencyType = depType;
return module[depType][name];
}
})[0];
if (!returnDependency.dependency || !returnDependency.dependencyType)
throw new Error(name + ' doesn\'t appear to be a thing.');
return returnDependency;
};
var invokeDependency = function(module, name, type) {
var value = requestDependency(module, name, type).dependency
, dependencies = value? value.__dependencies : []
, service = type === 'service'
, invoked = service && value.__invoked;
theInvoking: {
if (isFunction(value)) {
if (invoked)
break theInvoking;
value = new value(
invokeDependency(module, dependencies[0], requestDependency(module, dependencies[0]).dependencyType),
invokeDependency(module, dependencies[1], requestDependency(module, dependencies[1]).dependencyType),
invokeDependency(module, dependencies[2], requestDependency(module, dependencies[2]).dependencyType),
invokeDependency(module, dependencies[3], requestDependency(module, dependencies[3]).dependencyType),
invokeDependency(module, dependencies[4], requestDependency(module, dependencies[4]).dependencyType)
);
if (service) {
registerDependency(module, 'service', name, value);
module.service[name].__invoked = true;
}
}
}
return value;
};
var things = function(module) {
module = allOfTheThings[module] = {
route: {},
service: {},
thing: {},
boot: {}
};
var route = function(route, value) {
registerDependency(module, 'route', route, value);
return module;
};
var service = function(service, value) {
registerDependency(module, 'service', service, value);
return module;
};
var thing = function(thing, value) {
registerDependency(module, 'thing', thing, value);
return module;
};
var goTo = function(route) {
invokeDependency(module, route, 'route');
return module;
};
var boots = function(value) {
registerDependency(module, 'boot', value.toString().substr(10, 30).replace(/^\w|\s/g, ''), value);
return module;
};
root.onload = function() {
for (var bootFn in module.boot)
if (module.boot.hasOwnProperty(bootFn))
invokeDependency(module, bootFn, 'boot');
};
return {
route: route,
service: service,
thing: thing,
goTo: goTo,
boots: boots
};
};
return things;
})();
})(window);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment