Dispatcher
Example for functional programming in JavaScript: a dispatcher that executes arbitrary callbacks when corresponding predicate functions return true
by Patrick Hund
HTML
<div class="container">
<div class="row">
<div class="col-md-12">
<h1>Dispatcher</h1>
<p>Executes callback functions as soon as a predicate function returns true by executing the predicate every 100 ms.</p>
<p>You can provide as many predicate/callback pairs as you like, they all run in the same loop, since the dispatcher is implemented as a singleton and keeps an array of predicates and callbacks in its function scope.</p>
<p>The callbacks in this example simply write log statements to the black console window below, but you can, of course, have them do anything.</p>
<p>So instead of using a keyup event listener on the input field that triggers each time the user types, we simply specify a predicate function that returns true if the input field has a value.</p>
<p>The advantage over event listeners: you can listen to things that there are no events for, like an element becoming visible (the blue buttons trigger these).</p>
</div>
</div>
<div class="row">
<div class="col-md-2">
<div class="form-group">
<input id="input1" type="text" class="form-control" placeholder="Input 1">
</div>
</div>
<div class="col-md-1">
<div id="toggle-input1" class="form-group">
<button type="button" class="btn btn-primary form-control visible-md">Toggle</button>
<button type="button" class="btn btn-primary form-control hidden-md"> <span class="glyphicon glyphicon-eye-open left"></span>
Toggle</button>
</div>
</div>
<div class="col-md-2"></div>
<div class="col-md-2">
<div class="checkbox">
<label>
<input id="checkbox1" type="checkbox">Checkbox 1</label>
</div>
</div>
<div class="col-md-1">
<div id="toggle-checkbox1" class="form-group">
<button...
CSS
#console {
background-color: #000000;
width: 100%;
height: 200px;
overflow: scroll;
padding: 10px;
border-radius: 15px;
}
#console p {
margin: 0;
color: green;
}
#console p.new {
color: lime;
}
JavaScript
(function () {
"use strict";
var dispatcher;
function log(msg) {
var $console = $("#console");
$console.find("p").first().removeClass("new");
$console.prepend("<p class=\"new\">" + msg + "</p>");
}
function elementOrSelector(elors) {
return function (func) {
return func.apply(typeof elors === "string" ? $(elors) : elors);
};
}
function cull(arr) {
return function (predf) {
var i;
for (i = arr.length - 1; i >= 0; i--) {
if (predf.apply(arr[i])) {
arr.splice(i, 1);
}
}
};
}
dispatcher = (function () {
var instance, dispatches = [];
function createInstance() {
(function dispatch() {
cull(dispatches)(function () {
if (this.predf.apply(null, this.additionalArgs)) {
this.deferred.resolve.apply(null, this.additionalArgs);
return true;
}
return false;
});
window.setTimeout(dispatch, 100);
}());
return {
register: function () {
var predf, additionalArgs, deferred;
if (!arguments.length) {
throw "'when' function expects at least one argument (the predicate function";
}
predf = arguments[0];
if (typeof predf !== "function") {
throw "first argument passed to 'when' function is not a function";
}
additionalArgs = Array.prototype.slice.apply(arguments, [1]);
deferred = $.Deferred();
dispatches.push({
predf: predf,
additionalArgs: additionalArgs,
deferred: deferred
...