@spalger/kibana
Version:
Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic
118 lines (101 loc) • 3.93 kB
JavaScript
define(function (require) {
var _ = require('lodash');
require('ui/modules').get('kibana')
.config(function ($provide) {
$provide.decorator('$rootScope', function ($delegate) {
/**
* Watch multiple expressions with a single callback. Along
* with making code simpler it also merges all of the watcher
* handlers within a single tick.
*
* # expression format
* expressions can be specified in one of the following ways:
* 1. string that evaluates to a value on scope. Creates a regular $watch
* expression.
* 'someScopeValue.prop' === $scope.$watch('someScopeValue.prop', fn);
*
* 2. #1 prefixed with '[]', which uses $watchCollection rather than $watch.
* '[]expr' === $scope.$watchCollection('expr', fn);
*
* 3. #1 prefixed with '=', which uses $watch with objectEquality turned on
* '=expr' === $scope.$watch('expr', fn, true);
*
* 4. a function that will be called, like a normal function water
*
* 5. an object with any of the properties:
* `get`: the getter called on each itteration
* `deep`: a flag to turn on objectEquality in $watch
* `fn`: the watch registration function ($scope.$watch or $scope.$watchCollection)
*
* @param {array[string|function|obj]} expressions - the list of expressions to $watch
* @param {Function} fn - the callback function
* @return {Function} - an unwatch function, just like the return value of $watch
*/
$delegate.constructor.prototype.$watchMulti = function (expressions, fn) {
if (!_.isArray(expressions)) throw new TypeError('expected an array of expressions to watch');
if (!_.isFunction(fn)) throw new TypeError('expected a function that is triggered on each watch');
var $scope = this;
var vals = new Array(expressions.length);
var prev = new Array(expressions.length);
var fire = false;
var init = 0;
var neededInits = expressions.length;
// first, register all of the multi-watchers
var unwatchers = expressions.map(function (expr, i) {
expr = normalizeExpression($scope, expr);
if (!expr) return;
return expr.fn.call($scope, expr.get, function (newVal, oldVal) {
if (newVal === oldVal) {
init += 1;
}
vals[i] = newVal;
prev[i] = oldVal;
fire = true;
}, expr.deep);
});
// then, the watcher that checks to see if any of
// the other watchers triggered this cycle
var flip = false;
unwatchers.push($scope.$watch(function () {
if (init < neededInits) return init;
if (fire) {
fire = false;
flip = !flip;
}
return flip;
}, function () {
if (init < neededInits) return false;
fn(vals.slice(0), prev.slice(0));
vals.forEach(function (v, i) {
prev[i] = v;
});
}));
return _.partial(_.callEach, unwatchers);
};
function normalizeExpression($scope, expr) {
if (!expr) return;
var norm = {
fn: $scope.$watch,
deep: false
};
if (_.isFunction(expr)) return _.assign(norm, { get: expr });
if (_.isObject(expr)) return _.assign(norm, expr);
if (!_.isString(expr)) return;
if (expr.substr(0, 2) === '[]') {
return _.assign(norm, {
fn: $scope.$watchCollection,
get: expr.substr(2)
});
}
if (expr.charAt(0) === '=') {
return _.assign(norm, {
deep: true,
get: expr.substr(1)
});
}
return _.assign(norm, { get: expr });
}
return $delegate;
});
});
});