aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatias Niemelä2014-02-24 18:14:29 -0500
committerMatias Niemelä2014-02-24 21:23:05 -0500
commit04d7317cdd95ba00783389f89f6e9a7e1fc418f8 (patch)
treec0eff0f1d143a3340c40b532a3ffd4149787d0a0
parent2cd87dbb93497e38ffad016c1f5766c2bb56e604 (diff)
downloadangular.js-04d7317cdd95ba00783389f89f6e9a7e1fc418f8.tar.bz2
chore(core): introduce a wrapper for requestAnimationFrame
-rwxr-xr-xangularFiles.js1
-rw-r--r--src/AngularPublic.js5
-rw-r--r--src/ng/raf.js22
-rw-r--r--src/ngMock/angular-mocks.js29
-rw-r--r--test/ng/rafSpec.js47
5 files changed, 103 insertions, 1 deletions
diff --git a/angularFiles.js b/angularFiles.js
index 225c2dec..3cbc7ece 100755
--- a/angularFiles.js
+++ b/angularFiles.js
@@ -26,6 +26,7 @@ angularFiles = {
'src/ng/log.js',
'src/ng/parse.js',
'src/ng/q.js',
+ 'src/ng/raf.js',
'src/ng/rootScope.js',
'src/ng/sanitizeUri.js',
'src/ng/sce.js',
diff --git a/src/AngularPublic.js b/src/AngularPublic.js
index 006de9ab..3870c519 100644
--- a/src/AngularPublic.js
+++ b/src/AngularPublic.js
@@ -72,6 +72,8 @@
$SnifferProvider,
$TemplateCacheProvider,
$TimeoutProvider,
+ $$RAFProvider,
+ $AsyncCallbackProvider,
$WindowProvider
*/
@@ -211,7 +213,8 @@ function publishExternalAPI(angular){
$sniffer: $SnifferProvider,
$templateCache: $TemplateCacheProvider,
$timeout: $TimeoutProvider,
- $window: $WindowProvider
+ $window: $WindowProvider,
+ $$rAF: $$RAFProvider
});
}
]);
diff --git a/src/ng/raf.js b/src/ng/raf.js
new file mode 100644
index 00000000..f85ee12a
--- /dev/null
+++ b/src/ng/raf.js
@@ -0,0 +1,22 @@
+'use strict';
+
+function $$RAFProvider(){ //rAF
+ this.$get = ['$window', function($window) {
+ var requestAnimationFrame = $window.requestAnimationFrame ||
+ $window.webkitRequestAnimationFrame;
+
+ var cancelAnimationFrame = $window.cancelAnimationFrame ||
+ $window.webkitCancelAnimationFrame;
+
+ var raf = function(fn) {
+ var id = requestAnimationFrame(fn);
+ return function() {
+ cancelAnimationFrame(id);
+ };
+ };
+
+ raf.supported = !!requestAnimationFrame;
+
+ return raf;
+ }];
+}
diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js
index 9a45939c..efde0f3a 100644
--- a/src/ngMock/angular-mocks.js
+++ b/src/ngMock/angular-mocks.js
@@ -1656,6 +1656,34 @@ angular.mock.$TimeoutDecorator = function($delegate, $browser) {
return $delegate;
};
+angular.mock.$RAFDecorator = function($delegate) {
+ var queue = [];
+ var rafFn = function(fn) {
+ var index = queue.length;
+ queue.push(fn);
+ return function() {
+ queue.splice(index, 1);
+ };
+ };
+
+ rafFn.supported = $delegate.supported;
+
+ rafFn.flush = function() {
+ if(queue.length === 0) {
+ throw new Error('No rAF callbacks present');
+ }
+
+ var length = queue.length;
+ for(var i=0;i<length;i++) {
+ queue[i]();
+ }
+
+ queue = [];
+ };
+
+ return rafFn;
+};
+
/**
*
*/
@@ -1689,6 +1717,7 @@ angular.module('ngMock', ['ng']).provider({
$rootElement: angular.mock.$RootElementProvider
}).config(['$provide', function($provide) {
$provide.decorator('$timeout', angular.mock.$TimeoutDecorator);
+ $provide.decorator('$$rAF', angular.mock.$RAFDecorator);
}]);
/**
diff --git a/test/ng/rafSpec.js b/test/ng/rafSpec.js
new file mode 100644
index 00000000..6c15e2d2
--- /dev/null
+++ b/test/ng/rafSpec.js
@@ -0,0 +1,47 @@
+'use strict';
+
+describe('$$rAF', function() {
+ it('should queue and block animation frames', inject(function($$rAF) {
+ if(!$$rAF.supported) return;
+
+ var message;
+ $$rAF(function() {
+ message = 'yes';
+ });
+
+ expect(message).toBeUndefined();
+ $$rAF.flush();
+ expect(message).toBe('yes');
+ }));
+
+ it('should provide a cancellation method', inject(function($$rAF) {
+ if(!$$rAF.supported) return;
+
+ var present = true;
+ var cancel = $$rAF(function() {
+ present = false;
+ });
+
+ expect(present).toBe(true);
+ cancel();
+
+ try {
+ $$rAF.flush();
+ } catch(e) {};
+ expect(present).toBe(true);
+ }));
+
+ describe('mocks', function() {
+ it('should throw an error if no frames are present', inject(function($$rAF) {
+ if($$rAF.supported) {
+ var failed = false;
+ try {
+ $$rAF.flush();
+ } catch(e) {
+ failed = true;
+ }
+ expect(failed).toBe(true);
+ }
+ }));
+ });
+});