Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(core): ensure core animate runner is the same with and without animations #13347

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions angularFiles.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var angularFiles = {

'src/ng/anchorScroll.js',
'src/ng/animate.js',
'src/ng/animateRunner.js',
'src/ng/animateCss.js',
'src/ng/browser.js',
'src/ng/cacheFactory.js',
Expand Down
6 changes: 4 additions & 2 deletions src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
$AnimateProvider,
$CoreAnimateCssProvider,
$$CoreAnimateQueueProvider,
$$CoreAnimateRunnerProvider,
$$AnimateRunnerProvider,
$$AnimateAsyncRunFactoryProvider,
$BrowserProvider,
$CacheFactoryProvider,
$ControllerProvider,
Expand Down Expand Up @@ -218,7 +219,8 @@ function publishExternalAPI(angular) {
$animate: $AnimateProvider,
$animateCss: $CoreAnimateCssProvider,
$$animateQueue: $$CoreAnimateQueueProvider,
$$AnimateRunner: $$CoreAnimateRunnerProvider,
$$AnimateRunner: $$AnimateRunnerFactoryProvider,
$$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
$browser: $BrowserProvider,
$cacheFactory: $CacheFactoryProvider,
$controller: $ControllerProvider,
Expand Down
30 changes: 6 additions & 24 deletions src/ng/animate.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,29 +53,6 @@ function prepareAnimateOptions(options) {
: {};
}

var $$CoreAnimateRunnerProvider = function() {
this.$get = ['$q', '$$rAF', function($q, $$rAF) {
function AnimateRunner() {}
AnimateRunner.all = noop;
AnimateRunner.chain = noop;
AnimateRunner.prototype = {
end: noop,
cancel: noop,
resume: noop,
pause: noop,
complete: noop,
then: function(pass, fail) {
return $q(function(resolve) {
$$rAF(function() {
resolve();
});
}).then(pass, fail);
}
};
return AnimateRunner;
}];
};

// this is prefixed with Core since it conflicts with
// the animateQueueProvider defined in ngAnimate/animateQueue.js
var $$CoreAnimateQueueProvider = function() {
Expand All @@ -101,7 +78,12 @@ var $$CoreAnimateQueueProvider = function() {
addRemoveClassesPostDigest(element, options.addClass, options.removeClass);
}

return new $$AnimateRunner(); // jshint ignore:line
var runner = new $$AnimateRunner(); // jshint ignore:line

// since there are no animations to run the runner needs to be
// notified that the animation call is complete.
runner.complete();
return runner;
}
};

Expand Down
39 changes: 5 additions & 34 deletions src/ng/animateCss.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,7 @@
* Click here {@link ngAnimate.$animateCss to read the documentation for $animateCss}.
*/
var $CoreAnimateCssProvider = function() {
this.$get = ['$$rAF', '$q', function($$rAF, $q) {

var RAFPromise = function() {};
RAFPromise.prototype = {
done: function(cancel) {
this.defer && this.defer[cancel === true ? 'reject' : 'resolve']();
},
end: function() {
this.done();
},
cancel: function() {
this.done(true);
},
getPromise: function() {
if (!this.defer) {
this.defer = $q.defer();
}
return this.defer.promise;
},
then: function(f1,f2) {
return this.getPromise().then(f1,f2);
},
'catch': function(f1) {
return this.getPromise()['catch'](f1);
},
'finally': function(f1) {
return this.getPromise()['finally'](f1);
}
};

this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {
return function(element, options) {
// there is no point in applying the styles since
// there is no animation that goes on at all in
Expand All @@ -55,24 +26,24 @@ var $CoreAnimateCssProvider = function() {
options.from = null;
}

var closed, runner = new RAFPromise();
var closed, runner = new $$AnimateRunner();
return {
start: run,
end: run
};

function run() {
$$rAF(function() {
close();
applyAnimationContents();
if (!closed) {
runner.done();
runner.complete();
}
closed = true;
});
return runner;
}

function close() {
function applyAnimationContents() {
if (options.addClass) {
element.addClass(options.addClass);
options.addClass = null;
Expand Down
170 changes: 170 additions & 0 deletions src/ng/animateRunner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
'use strict';

var $$AnimateAsyncRunFactoryProvider = function() {
this.$get = ['$$rAF', function($$rAF) {
var waitQueue = [];

function waitForTick(fn) {
waitQueue.push(fn);
if (waitQueue.length > 1) return;
$$rAF(function() {
for (var i = 0; i < waitQueue.length; i++) {
waitQueue[i]();
}
waitQueue = [];
});
}

return function() {
var passed = false;
waitForTick(function() {
passed = true;
});
return function(callback) {
passed ? callback() : waitForTick(callback);
};
};
}];
};

var $$AnimateRunnerFactoryProvider = function() {
this.$get = ['$q', '$sniffer', '$$animateAsyncRun',
function($q, $sniffer, $$animateAsyncRun) {

var INITIAL_STATE = 0;
var DONE_PENDING_STATE = 1;
var DONE_COMPLETE_STATE = 2;

AnimateRunner.chain = function(chain, callback) {
var index = 0;

next();
function next() {
if (index === chain.length) {
callback(true);
return;
}

chain[index](function(response) {
if (response === false) {
callback(false);
return;
}
index++;
next();
});
}
};

AnimateRunner.all = function(runners, callback) {
var count = 0;
var status = true;
forEach(runners, function(runner) {
runner.done(onProgress);
});

function onProgress(response) {
status = status && response;
if (++count === runners.length) {
callback(status);
}
}
};

function AnimateRunner(host) {
this.setHost(host);

this._doneCallbacks = [];
this._runInAnimationFrame = $$animateAsyncRun();
this._state = 0;
}

AnimateRunner.prototype = {
setHost: function(host) {
this.host = host || {};
},

done: function(fn) {
if (this._state === DONE_COMPLETE_STATE) {
fn();
} else {
this._doneCallbacks.push(fn);
}
},

progress: noop,

getPromise: function() {
if (!this.promise) {
var self = this;
this.promise = $q(function(resolve, reject) {
self.done(function(status) {
status === false ? reject() : resolve();
});
});
}
return this.promise;
},

then: function(resolveHandler, rejectHandler) {
return this.getPromise().then(resolveHandler, rejectHandler);
},

'catch': function(handler) {
return this.getPromise()['catch'](handler);
},

'finally': function(handler) {
return this.getPromise()['finally'](handler);
},

pause: function() {
if (this.host.pause) {
this.host.pause();
}
},

resume: function() {
if (this.host.resume) {
this.host.resume();
}
},

end: function() {
if (this.host.end) {
this.host.end();
}
this._resolve(true);
},

cancel: function() {
if (this.host.cancel) {
this.host.cancel();
}
this._resolve(false);
},

complete: function(response) {
var self = this;
if (self._state === INITIAL_STATE) {
self._state = DONE_PENDING_STATE;
self._runInAnimationFrame(function() {
self._resolve(response);
});
}
},

_resolve: function(response) {
if (this._state !== DONE_COMPLETE_STATE) {
forEach(this._doneCallbacks, function(fn) {
fn(response);
});
this._doneCallbacks.length = 0;
this._state = DONE_COMPLETE_STATE;
}
}
};

return AnimateRunner;
}];
};
Loading