Merge branch 'master' into pinned-filters

Conflicts:
	src/kibana/components/watch_multi.js
This commit is contained in:
Joe Fleming 2015-05-01 10:49:18 -07:00
commit cd4b4ac385
7 changed files with 115 additions and 84 deletions

View file

@ -22,6 +22,13 @@ Please make sure you have signed the [Contributor License Agreement](http://www.
```sh
npm install -g grunt-cli bower
```
- Clone the kibana repo and move into it
```sh
git clone https://github.com/elastic/kibana.git kibana
cd kibana
```
- Install node and bower dependencies

View file

@ -254,7 +254,7 @@ define(function (require) {
div = d3.select(this);
width = parentWidth / n;
height = $(this).height();
height = $(this.parentElement).height();
self.validateWidthandHeight(width, height);

View file

@ -148,7 +148,7 @@
.x-axis-div-wrapper {
.display(flex);
.flex-direction(row);
min-height: 15px;
min-height: 20px;
min-width: 0;
}

View file

@ -31,91 +31,76 @@ define(function (require) {
*
* @param {array[string|function|obj]} expressions - the list of expressions to $watch
* @param {Function} fn - the callback function
* @param {boolean} deep - should the watchers be created as deep watchers?
* @return {undefined}
* @return {Function} - an unwatch function, just like the return value of $watch
*/
$delegate.constructor.prototype.$watchMulti = function (expressions, fn, deep) {
$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 registry = [];
var fired = false;
var queue = [];
var vals = new Array(expressions.length);
var prev = new Array(expressions.length);
var fire = false;
function normalizeExpression(expr) {
// first, register all of the multi-watchers
var unwatchers = expressions.map(function (expr, i) {
expr = 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 });
}
expressions.forEach(function (expr, i) {
expr = normalizeExpression(expr);
if (!expr) return;
queue.push(expr);
var watcher = expr.fn.call($scope, expr.get, function (newVal, oldVal) {
return expr.fn.call($scope, expr.get, function (newVal, oldVal) {
vals[i] = newVal;
prev[i] = oldVal;
if (queue) {
_.pull(queue, expr);
if (queue.length > 0) return;
queue = false;
}
if (fired) return;
fired = true;
$scope.$evalAsync(function () {
fired = false;
if (fn.length) {
fn(vals.slice(0), prev.slice(0));
} else {
fn();
}
for (var i = 0; i < vals.length; i++) {
prev[i] = vals[i];
}
});
fire = true;
}, expr.deep);
registry.push(watcher);
});
return function deregister() {
registry.forEach(function (deregisterWatcher) {
deregisterWatcher();
// 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 (fire) {
fire = false;
flip = !flip;
}
return flip;
}, function () {
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;
});
});

View file

@ -19,6 +19,10 @@
}
}
.btn-xs {
line-height: 1.3;
}
navbar {
.bitty-modal-container {
position: relative;
@ -94,6 +98,10 @@
> .vis-edit-sidebar-buttons {
.flex(0, 0, auto)
}
label {
margin-bottom: 0px;
}
}
}
@ -103,6 +111,7 @@
border: inherit !important;
background-color: @gray-lighter;
margin-bottom: 5px;
padding: 2px 5px !important;
}
.sidebar-item-title:hover {

View file

@ -36,6 +36,11 @@
ScreencastReporter: '../../node_modules/mocha-screencast-reporter/screencast-reporter'
},
shim: {
angular_src: {
deps: [
'jquery'
]
},
angular: {
deps: [
'jquery',

View file

@ -82,23 +82,48 @@ define(function (require) {
]);
});
it('does not pass args unless the function will use them', function () {
var calls = 0;
it('the current value is always up to date', function () {
var count = 0;
$scope.one = 'a';
$scope.two = 'b';
$scope.three = 'c';
$scope.$watchMulti([
'one',
'two',
'three'
], function () {
calls++;
expect(arguments).to.have.length(0);
$scope.vals = [1, 0];
$scope.$watchMulti([ 'vals[0]', 'vals[1]' ], function (cur, prev) {
expect(cur).to.eql($scope.vals);
count++;
});
$rootScope.$apply();
expect(calls).to.be(1);
var $child = $scope.$new();
$child.$watch('vals[0]', function (cur) {
$child.vals[1] = cur;
});
$rootScope.$apply();
expect(count).to.be(2);
});
it('returns a working unwatch function', function () {
$scope.a = 0;
$scope.b = 0;
var triggers = 0;
var unwatch = $scope.$watchMulti(['a', 'b'], function () { triggers++; });
// initial watch
$scope.$apply();
expect(triggers).to.be(1);
// prove that it triggers on chagne
$scope.a++;
$scope.$apply();
expect(triggers).to.be(2);
// remove watchers
expect($scope.$$watchers).to.not.eql([]);
unwatch();
expect($scope.$$watchers).to.eql([]);
// prove that it doesn't trigger anymore
$scope.a++;
$scope.$apply();
expect(triggers).to.be(2);
});
});
});
});