├── .babelrc
├── dist
├── .gitignore
├── request-frame.es.js
└── request-frame.js
├── .gitignore
├── .npmignore
├── test
├── compatibility
│ ├── amd
│ │ ├── native.js
│ │ └── assign.js
│ ├── compatibility-assignation-amd.html
│ ├── compatibility-native.html
│ ├── compatibility-native-amd.html
│ └── compatibility-assignation.html
├── system.js
├── index.html
└── test.js
├── rollup
├── rollup.config.es.js
└── rollup.config.umd.js
├── bower.json
├── LICENSE
├── gulpfile.babel.js
├── package.json
├── demo
└── fps.html
├── README.md
└── src
└── request-frame.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
--------------------------------------------------------------------------------
/dist/.gitignore:
--------------------------------------------------------------------------------
1 | #request-frame.js
2 | #request-frame.min.js
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | project
3 | npm-debug.log
4 | dummy.js
5 | yarn.lock
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | project
3 | npm-debug.log
4 | dummy.js
5 | yarn.lock
6 | rollup
7 | src
8 | test
9 | .babelrc
10 | bower.json
11 | gulpfile.babel.js
12 |
--------------------------------------------------------------------------------
/test/compatibility/amd/native.js:
--------------------------------------------------------------------------------
1 | requirejs.config({
2 | baseUrl: '../../dist',
3 | });
4 | requirejs(['request-frame'],
5 | function(requestFrame) {
6 | // Re-assign native functions
7 | requestFrame('native');
8 | });
9 |
--------------------------------------------------------------------------------
/rollup/rollup.config.es.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 |
3 | export default {
4 | moduleName: 'requestFrame',
5 | entry: 'src/request-frame.js',
6 | plugins: [babel({
7 | babelrc: false,
8 | exclude: 'node_modules/**'
9 | })],
10 | format: 'es',
11 | dest: 'dist/request-frame.es.js'
12 | };
13 |
--------------------------------------------------------------------------------
/rollup/rollup.config.umd.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 |
3 | export default {
4 | moduleName: 'requestFrame',
5 | entry: './src/request-frame.js',
6 | plugins: [babel({
7 | babelrc: false,
8 | presets: ["es2015-rollup"]
9 | })],
10 | format: 'umd',
11 | dest: './dist/request-frame.js'
12 | };
13 |
--------------------------------------------------------------------------------
/test/system.js:
--------------------------------------------------------------------------------
1 | describe('System check', function () {
2 | it('DeStijl function exists', function () {
3 | expect(_deStijl).to.be.a('function');
4 | });
5 | it('Style namespace to exist as an object', function(){
6 | var obj = _deStijl.isObject(style);
7 | expect(obj).to.be.true;
8 | });
9 | it('Version should be a string', function(){
10 | expect(DeStijl.version).to.be.a('string');
11 | })
12 | });
13 |
--------------------------------------------------------------------------------
/test/compatibility/amd/assign.js:
--------------------------------------------------------------------------------
1 | requirejs.config({
2 | baseUrl: '../../dist',
3 | });
4 | requirejs(['request-frame'],
5 | function(requestFrame) {
6 | var div = document.getElementsByTagName('div');
7 |
8 | // Assign functions
9 | var request = requestFrame('request');
10 | var cancel = requestFrame('cancel');
11 |
12 | // Expose the functions on screen
13 | (function exposeFunctions(timestamp) {
14 |
15 | // Show the request function
16 | div[0].innerHTML = request;
17 |
18 | // Show the cancel function
19 | div[1].innerHTML = cancel;
20 |
21 | // Show the high resolution timestamp
22 | div[2].innerHTML = timestamp;
23 |
24 | // request the frame
25 | request(exposeFunctions);
26 | }());
27 | });
28 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "request-frame",
3 | "version": "1.5.3",
4 | "description": "requestAnimationFrame & cancelAnimationFrame polyfill for optimal cross-browser development.",
5 | "main": "dist/request-frame.js",
6 | "moduleType": [
7 | "amd",
8 | "globals"
9 | ],
10 | "keywords": [
11 | "requestAnimationFrame",
12 | "webkitRequestAnimationFrame",
13 | "mozRequestAnimationFrame",
14 | "cancelAnimationFrame",
15 | "mozCancelAnimationFrame",
16 | "webkitCancelAnimationFrame",
17 | "webkitCancelRequestAnimationFrame",
18 | "setTimeout",
19 | "cancelTimeout",
20 | "timing functions",
21 | "requestAnimationFrame polyfill",
22 | "polyfill",
23 | "animation timing",
24 | "animation timestamp"
25 | ],
26 | "author": "Julien Etienne",
27 | "license": "MIT",
28 | "ignore": [
29 | "node_modules",
30 | "bower_components",
31 | "test"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright © 2016 Julien Etienne
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 |
6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7 |
8 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | request-frame test
8 |
9 |
15 |
16 |
17 |
18 |
20 |
21 |
22 |
23 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/test/compatibility/compatibility-assignation-amd.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | AMD request-frame Assignation Check
9 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/gulpfile.babel.js:
--------------------------------------------------------------------------------
1 | const version = '1.5.3';
2 |
3 |
4 | import {src, dest, task, watch} from 'gulp-es-next';
5 | import concat from 'gulp-concat';
6 | import rename from 'gulp-rename';
7 | import header from 'gulp-header';
8 | import bump from 'gulp-bump';
9 | import pkg from './package.json';
10 |
11 |
12 | const banner = ['/**',
13 | ' * <%= pkg.name %> - requestAnimationFrame & cancelAnimationFrame polyfill for',
14 | ' * optimal cross-browser development.',
15 | ' * Version: v<%= pkg.version %>',
16 | ' * License: <%= pkg.license %>',
17 | ' * Copyright <%= pkg.author %> 2015 All Rights Reserved.',
18 | ' * github: <%= pkg.repository.url %>',
19 | ' *‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾',
20 | ' */',
21 | ''
22 | ].join('\n');
23 |
24 |
25 | const minBanner = ['/**',
26 | ' * <%= pkg.name %> - <%= pkg.description %>',
27 | ' * @version v<%= pkg.version %>',
28 | ' * @license <%= pkg.license %>',
29 | ' * Copyright <%= pkg.author %> 2015 All Rights Reserved.',
30 | ' */',
31 | ''
32 | ].join('\n');
33 |
34 |
35 | task('Add header to ES version', function() {
36 | return src('./dist/request-frame.es.js')
37 | .pipe(header(minBanner, {
38 | pkg: pkg
39 | }))
40 | .pipe(dest('./dist'));
41 | });
42 |
43 |
44 | task('Add header to UMD version', function() {
45 | return src('./dist/request-frame.js')
46 | .pipe(header(minBanner, {
47 | pkg: pkg
48 | }))
49 | .pipe(dest('./dist'));
50 | });
51 |
52 |
53 | task('bump', function(){
54 | src(['./bower.json','./package.json'])
55 | .pipe(bump({version: version}))
56 | .pipe(dest('./'));
57 | });
58 |
59 |
60 | task('default', [
61 | 'Add header to ES version',
62 | 'Add header to UMD version'
63 | ]);
64 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "request-frame",
3 | "version": "1.5.3",
4 | "description": "requestAnimationFrame & cancelAnimationFrame polyfill for optimal cross-browser development.",
5 | "main": "dist/request-frame.js",
6 | "jsnext:main": "dist/request-frame.es.js",
7 | "scripts": {
8 | "bump": "gulp bump",
9 | "header": "gulp",
10 | "build": "rollup -c rollup/rollup.config.umd.js && rollup -c rollup/rollup.config.es.js",
11 | "watch": "rollup -c rollup/rollup.config.umd.js -c --watch",
12 | "test": "./node_modules/.bin/http-server ./ -p 9999",
13 | "dummy": "wzrd dummy.js | wtch | garnish"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/julienetie/request-frame"
18 | },
19 | "keywords": [
20 | "requestAnimationFrame",
21 | "webkitRequestAnimationFrame",
22 | "mozRequestAnimationFrame",
23 | "cancelAnimationFrame",
24 | "mozCancelAnimationFrame",
25 | "webkitCancelAnimationFrame",
26 | "webkitCancelRequestAnimationFrame",
27 | "setTimeout",
28 | "cancelTimeout",
29 | "timing functions",
30 | "requestAnimationFrame polyfill",
31 | "polyfill",
32 | "animation timing",
33 | "animation timestamp"
34 | ],
35 | "author": "Julien Etienne",
36 | "license": "MIT",
37 | "bugs": {
38 | "url": "https://github.com/julienetie/request-frame/issues"
39 | },
40 | "homepage": "https://github.com/julienetie/request-frame",
41 | "devDependencies": {
42 | "babel-cli": "*",
43 | "babel-preset-es2015": "*",
44 | "babel-preset-es2015-rollup": "^1.2.0",
45 | "chai": "*",
46 | "gulp": "^3.9.1",
47 | "gulp-bump": "*",
48 | "gulp-concat": "*",
49 | "gulp-es-next": "*",
50 | "gulp-header": "*",
51 | "gulp-rename": "*",
52 | "http-server": "*",
53 | "mocha": "*",
54 | "requirejs": "*",
55 | "rollup": "*",
56 | "rollup-plugin-babel": "*",
57 | "rollup-watch": "*"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/test/compatibility/compatibility-native.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | SRC request-frame Native Check
9 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/test/compatibility/compatibility-native-amd.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | AMD request-frame Native Check
9 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/test/compatibility/compatibility-assignation.html:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 | SRC request-frame Assignation Check
9 |
10 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/demo/fps.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | FPS demo
7 |
8 |
9 |
10 |
11 |
12 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | `* *` _If you are not supporting browsers from IE9 and below, you probably don't need this or any equivalent polyfill_ `* *`
2 |
3 | # request-frame
4 |
5 | ### A comprehensive requestAnimationFrame & cancelAnimationFrame polyfill.
6 |
7 | - Supports ES6 - AMD - CJS & IIFE
8 | - Provides a clean polyfill for requestAnimationFrame & cancelAnimationFrame.
9 | - Tested & working on: IE 5.5+, FF 3+, Opera 11.16+, Safari 4+, Chrome 14+, iOS 3+, Android 2.3+, Android Chrome 28+.
10 | - **iOS 6 bug fix** without user-agent sniffing.
11 | - **Firefox 4 - 10 function mismatch normalization**.
12 | - Doesn't modify native functions unless specified.
13 | - AMD compliant.
14 |
15 | #### Install options
16 |
17 | `npm i request-frame --save` ** | ** `bower i request-frame` ** | ** [src](https://github.com/julienetie/request-frame/tree/master/dist) ** | ** [release](https://github.com/julienetie/request-frame/releases)
18 |
19 |
20 | ```javascript
21 | import requestFrame from 'request-frame'; // ES6
22 | ```
23 |
24 | ```javascript
25 | // AMD, IIFE
26 | ```
27 |
28 | ```javascript
29 | const requestFrame = require('request-frame'); // CJS
30 | ```
31 |
32 |
33 | ### The API:
34 | #### Assign the timing functions:
35 | *requestFrame( request | cancel | native )* request is default.
36 | ```javascript
37 | var request = requestFrame('request'); // window.requestAnimationFrame | setTimeout
38 | var cancel = requestFrame('cancel'); // window.cancelAnimationFrame | cancelTimeout
39 | ```
40 | #### Or re/ assign native functions:
41 | ```javascript
42 | requestFrame('native'); // re/ declares requestAnimationFrame & cancelAnimationFrame
43 | ```
44 | Below is just an example of the requestAnimationFrame API, see links: [MDN](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame), [MSDN](https://msdn.microsoft.com/en-us/library/windows/apps/hh453388.aspx) & [W3](http://www.w3.org/TR/2011/WD-html5-20110525/timers.html).
45 |
46 | #### Loop something:
47 | ```javascript
48 | var requestId;
49 |
50 | function something( useTimeStamp ){
51 |
52 | // Do something here
53 |
54 | requestId = request(something);
55 | }
56 |
57 | requestId = request(something); // Assigns Id & calls "something"
58 | ```
59 |
60 | #### Cancel something:
61 |
62 | ```javascript
63 | cancel(requestId); // Cancels frame request
64 | ```
65 |
66 | ### The ideology
67 | request-frame aims to provide an optimal development consistency with the use of animation timing functions across the large number of browsers and devices. This lib is ideal for those who may want to avoid re-assigning native functions, or avoid interfering with other libs that do. requestFrame() is purposely not a constructor. The intention is for requestAnimationFrame to be used once or few times during execution since multiple task are expected to be more efficient via a single requestAnimationFrame loop compared to several instances.
68 |
69 | ### Browsers tested & passing:
70 |
71 | Supports everything from IE5+
72 |
73 |
74 | ### Contribute
75 | Just do it!
76 |
77 | #### Test
78 | `npm run test`
79 | To launch port 9999
80 |
81 | - ./test/
82 | - ./test/compatibility-assignation-amd.html
83 | - ./test/compatibility-assignation.html
84 | - ./test/compatibility-native-amd.html
85 | - ./test/compatibility-native.html
86 |
87 | _Browser based testing for RAF is imperative_
88 |
89 | ---
90 |
91 | [MIT License](https://github.com/julienetie/request-frame/blob/master/LICENSE)
92 |
93 | © 2016 Julien Etienne
94 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | var expect = chai.expect,
2 |
3 | err = new ReferenceError('RequestFrame parameter is not a type.'),
4 | native = 'native',
5 | request = 'request',
6 | cancel = 'cancel',
7 | rAF = window.requestAnimationFrame ||
8 | window.mozRequestAnimationFrame ||
9 | window.webkitRequestAnimationFrame,
10 |
11 | cAF = window.cancelAnimationFrame ||
12 | window.mozCancelAnimationFrame ||
13 | window.webkitCancelAnimationFrame ||
14 | window.webkitCancelRequestAnimationFrame;
15 |
16 | function isRequestOrSetFn(func) {
17 |
18 | var reference = func.toString(),
19 | referenceLower = reference.toLowerCase(),
20 | containsRequest = referenceLower.indexOf('request') > -1,
21 | containsSet = referenceLower.indexOf('set') > -1,
22 | results = containsRequest || containsSet ? true : false;
23 | return results;
24 | }
25 |
26 | function isCancellationFn(func) {
27 | var reference = func.toString(),
28 | referenceLower = reference.toLowerCase(),
29 | containsCancel = referenceLower.indexOf('cancel') > -1,
30 | containsClear = referenceLower.indexOf('clear') > -1,
31 | results = containsCancel || containsClear ? true : false;
32 | return results;
33 | }
34 |
35 | function isAnimationFrameFunction(func) {
36 | if (!func) {
37 | return;
38 | }
39 | var reference = func.toString();
40 | reference = reference.indexOf('AnimationFrame') > -1;
41 | return reference;
42 | }
43 |
44 |
45 |
46 | // Production steps of ECMA-262, Edition 5, 15.4.4.14
47 | // Reference: http://es5.github.io/#x15.4.4.14
48 | if (!Array.prototype.indexOf) {
49 | Array.prototype.indexOf = function(searchElement, fromIndex) {
50 |
51 | var k;
52 |
53 | // 1. Let O be the result of calling ToObject passing
54 | // the this value as the argument.
55 | if (this == null) {
56 | throw new TypeError('"this" is null or not defined');
57 | }
58 |
59 | var O = Object(this);
60 |
61 | // 2. Let lenValue be the result of calling the Get
62 | // internal method of O with the argument "length".
63 | // 3. Let len be ToUint32(lenValue).
64 | var len = O.length >>> 0;
65 |
66 | // 4. If len is 0, return -1.
67 | if (len === 0) {
68 | return -1;
69 | }
70 |
71 | // 5. If argument fromIndex was passed let n be
72 | // ToInteger(fromIndex); else let n be 0.
73 | var n = +fromIndex || 0;
74 |
75 | if (Math.abs(n) === Infinity) {
76 | n = 0;
77 | }
78 |
79 | // 6. If n >= len, return -1.
80 | if (n >= len) {
81 | return -1;
82 | }
83 |
84 | // 7. If n >= 0, then Let k be n.
85 | // 8. Else, n<0, Let k be len - abs(n).
86 | // If k is less than 0, then let k be 0.
87 | k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
88 |
89 | // 9. Repeat, while k < len
90 | while (k < len) {
91 | // a. Let Pk be ToString(k).
92 | // This is implicit for LHS operands of the in operator
93 | // b. Let kPresent be the result of calling the
94 | // HasProperty internal method of O with argument Pk.
95 | // This step can be combined with c
96 | // c. If kPresent is true, then
97 | // i. Let elementK be the result of calling the Get
98 | // internal method of O with the argument ToString(k).
99 | // ii. Let same be the result of applying the
100 | // Strict Equality Comparison Algorithm to
101 | // searchElement and elementK.
102 | // iii. If same is true, return k.
103 | if (k in O && O[k] === searchElement) {
104 | return k;
105 | }
106 | k++;
107 | }
108 | return -1;
109 | };
110 | }
111 |
112 |
113 | var RA = requestFrame('request');
114 | var CA = requestFrame('cancel');
115 | /**
116 | * Need to add iOS 6 + ff 4-10 bug checks.
117 | */
118 |
119 |
120 | describe('requestFrame', function() {
121 | it('Should throw an error if type is not valid', function() {
122 | expect(function() {
123 | requestFrame('');
124 | }).to
125 | .throw('RequestFrame parameter is not a type.');
126 | });
127 | });
128 |
129 |
130 |
131 | describe('Native type', function() {
132 | before(function() {
133 | requestFrame(native);
134 | var hasNativeRequestFunction = window.requestAnimationFrame === rAF,
135 | hasNativeCancellationFunction = window.requestAnimationFrame === cAF;
136 | });
137 |
138 | it('Should return nothing', function() {
139 | expect(requestFrame(native)).to.not.be.ok;
140 | });
141 |
142 | it('Should set requestAnimationFrame as request or set function', function() {
143 | expect(isRequestOrSetFn(window.requestAnimationFrame)).to.be.ok;
144 | });
145 |
146 | it('Should set cancelAnimationFrame as request or set function', function() {
147 | expect(isCancellationFn(window.cancelAnimationFrame)).to.be.ok;
148 | });
149 |
150 | it('Should provide a matching pair of start and cancellation functions ', function() {
151 | expect(isAnimationFrameFunction(RA) === isAnimationFrameFunction(CA)).to.be.ok;
152 | });
153 | });
154 |
155 |
156 |
157 | describe('Request type', function() {
158 | it('Should return a request or set function', function() {
159 | expect(isRequestOrSetFn(RA)).to.be.ok;
160 | });
161 | });
162 |
163 |
164 |
165 | describe('Cancel type', function() {
166 | it('Should return a cancellation function', function() {
167 | expect(isCancellationFn(CA)).to.be.ok;
168 | });
169 | });
170 |
171 |
172 |
173 | describe('Request & cancel in conjunction', function() {
174 | it('Should provide a matching pair of start and cancellation functions ', function() {
175 | expect(isAnimationFrameFunction(RA) === isAnimationFrameFunction(CA)).to.be.ok;
176 | });
177 | });
178 |
--------------------------------------------------------------------------------
/src/request-frame.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {String} type - request | cancel | native.
3 | * @return {Function} Timing function.
4 | */
5 | export default function requestFrame(type) {
6 | // The only vendor prefixes required.
7 | const vendors = ['moz', 'webkit'];
8 |
9 | // Disassembled timing function abbreviations.
10 | const aF = 'AnimationFrame';
11 | const rqAF = 'Request' + aF;
12 |
13 | // Checks for firefox 4 - 10 function pair mismatch.
14 | const mozRAF = window.mozRequestAnimationFrame;
15 | const mozCAF = window.mozCancelAnimationFrame;
16 | const hasMozMismatch = mozRAF && !mozCAF;
17 |
18 | // Final assigned functions.
19 | var assignedRequestAnimationFrame;
20 | var assignedCancelAnimationFrame;
21 |
22 | // Initial time of the timing lapse.
23 | var previousTime = 0;
24 |
25 | var requestFrameMain;
26 |
27 | // Date.now polyfill, mainly for legacy IE versions.
28 | if (!Date.now) {
29 | Date.now = function() {
30 | return new Date().getTime();
31 | };
32 | }
33 |
34 | /**
35 | * hasIOS6RequestAnimationFrameBug.
36 | * @See {@Link https://gist.github.com/julienetie/86ac394ec41f1271ff0a}
37 | * - for Commentary.
38 | * @Copyright 2015 - Julien Etienne.
39 | * @License: MIT.
40 | */
41 | function hasIOS6RequestAnimationFrameBug() {
42 | const webkitRAF = window.webkitRequestAnimationFrame;
43 | const rAF = window.requestAnimationFrame;
44 |
45 | // CSS/ Device with max for iOS6 Devices.
46 | const hasMobileDeviceWidth = screen.width <= 768 ? true : false;
47 |
48 | // Only supports webkit prefixed requestAnimtionFrane.
49 | const requiresWebkitprefix = !(webkitRAF && rAF);
50 |
51 | // iOS6 webkit browsers don't support performance now.
52 | const hasNoNavigationTiming = window.performance ? false : true;
53 |
54 | const iOS6Notice = `setTimeout is being used as a substitiue for
55 | requestAnimationFrame due to a bug within iOS 6 builds`;
56 |
57 | const hasIOS6Bug = requiresWebkitprefix && hasMobileDeviceWidth &&
58 | hasNoNavigationTiming;
59 |
60 | const bugCheckresults = (timingFnA, timingFnB, notice) => {
61 | if (timingFnA || timingFnB) {
62 | console.warn(notice);
63 | return true;
64 | } else {
65 | return false;
66 | }
67 | }
68 |
69 | const displayResults = (hasBug, hasBugNotice, webkitFn, nativeFn) => {
70 | if (hasBug) {
71 | return bugCheckresults(webkitFn, nativeFn, hasBugNotice);
72 | } else {
73 | return false;
74 | }
75 | }
76 |
77 | return displayResults(hasIOS6Bug, iOS6Notice,webkitRAF, rAF);
78 | }
79 |
80 | /**
81 | * Native clearTimeout function.
82 | * @return {Function}
83 | */
84 | function clearTimeoutWithId(id) {
85 | clearTimeout(id);
86 | id = null;
87 | }
88 |
89 | /**
90 | * Based on a polyfill by Erik, introduced by Paul Irish &
91 | * further improved by Darius Bacon.
92 | * @see {@link http://www.paulirish.com/2011/
93 | * requestanimationframe-for-smart-animating}
94 | * @see {@link https://github.com/darius/requestAnimationFrame/blob/
95 | * master/requestAnimationFrame.js}
96 | * @callback {Number} Timestamp.
97 | * @return {Function} setTimeout Function.
98 | */
99 | function setTimeoutWithTimestamp(callback) {
100 | let immediateTime = Date.now();
101 | let lapsedTime = Math.max(previousTime + 16, immediateTime);
102 | return setTimeout(function() {
103 | callback(previousTime = lapsedTime);
104 | },
105 | lapsedTime - immediateTime);
106 | }
107 |
108 | /**
109 | * Queries the native function, prefixed function
110 | * or use the setTimeoutWithTimestamp function.
111 | * @return {Function}
112 | */
113 | function queryRequestAnimationFrame() {
114 | if (Array.prototype.filter) {
115 | assignedRequestAnimationFrame = window['request' + aF] ||
116 | window[vendors.filter(function(vendor) {
117 | if (window[vendor + rqAF] !== undefined)
118 | return vendor;
119 | }) + rqAF] || setTimeoutWithTimestamp;
120 | } else {
121 | return setTimeoutWithTimestamp;
122 | }
123 | if (!hasIOS6RequestAnimationFrameBug()) {
124 | return assignedRequestAnimationFrame;
125 | } else {
126 | return setTimeoutWithTimestamp;
127 | }
128 | }
129 |
130 | /**
131 | * Queries the native function, prefixed function
132 | * or use the clearTimeoutWithId function.
133 | * @return {Function}
134 | */
135 | function queryCancelAnimationFrame() {
136 | let cancellationNames = [];
137 | if (Array.prototype.map) {
138 | vendors.map(function(vendor) {
139 | return ['Cancel', 'CancelRequest'].map(
140 | function(cancellationNamePrefix) {
141 | cancellationNames.push(vendor +
142 | cancellationNamePrefix + aF);
143 | });
144 | });
145 | } else {
146 | return clearTimeoutWithId;
147 | }
148 |
149 | /**
150 | * Checks for the prefixed cancelAnimationFrame implementation.
151 | * @param {Array} prefixedNames - An array of the prefixed names.
152 | * @param {Number} i - Iteration start point.
153 | * @return {Function} prefixed cancelAnimationFrame function.
154 | */
155 | function prefixedCancelAnimationFrame(prefixedNames, i) {
156 | let cancellationFunction;
157 | for (; i < prefixedNames.length; i++) {
158 | if (window[prefixedNames[i]]) {
159 | cancellationFunction = window[prefixedNames[i]];
160 | break;
161 | }
162 | }
163 | return cancellationFunction;
164 | }
165 |
166 | // Use truthly function
167 | assignedCancelAnimationFrame = window['cancel' + aF] ||
168 | prefixedCancelAnimationFrame(cancellationNames, 0) ||
169 | clearTimeoutWithId;
170 |
171 | // Check for iOS 6 bug
172 | if (!hasIOS6RequestAnimationFrameBug()) {
173 | return assignedCancelAnimationFrame;
174 | } else {
175 | return clearTimeoutWithId;
176 | }
177 | }
178 |
179 | function getRequestFn() {
180 | if (hasMozMismatch) {
181 | return setTimeoutWithTimestamp;
182 | } else {
183 | return queryRequestAnimationFrame();
184 | }
185 | }
186 |
187 | function getCancelFn() {
188 | return queryCancelAnimationFrame();
189 | }
190 |
191 | function setNativeFn() {
192 | if (hasMozMismatch) {
193 | window.requestAnimationFrame = setTimeoutWithTimestamp;
194 | window.cancelAnimationFrame = clearTimeoutWithId;
195 | } else {
196 | window.requestAnimationFrame = queryRequestAnimationFrame();
197 | window.cancelAnimationFrame = queryCancelAnimationFrame();
198 | }
199 | }
200 |
201 | /**
202 | * The type value "request" singles out firefox 4 - 10 and
203 | * assigns the setTimeout function if plausible.
204 | */
205 |
206 | switch (type) {
207 | case 'request':
208 | case '':
209 | requestFrameMain = getRequestFn();
210 | break;
211 |
212 | case 'cancel':
213 | requestFrameMain = getCancelFn();
214 | break;
215 |
216 | case 'native':
217 | setNativeFn();
218 | break;
219 | default:
220 | throw new Error('RequestFrame parameter is not a type.');
221 | }
222 | return requestFrameMain;
223 | }
224 |
--------------------------------------------------------------------------------
/dist/request-frame.es.js:
--------------------------------------------------------------------------------
1 | /**
2 | * request-frame - requestAnimationFrame & cancelAnimationFrame polyfill for optimal cross-browser development.
3 | * @version v1.5.3
4 | * @license MIT
5 | * Copyright Julien Etienne 2015 All Rights Reserved.
6 | */
7 | /**
8 | * @param {String} type - request | cancel | native.
9 | * @return {Function} Timing function.
10 | */
11 | function requestFrame(type) {
12 | // The only vendor prefixes required.
13 | const vendors = ['moz', 'webkit'];
14 |
15 | // Disassembled timing function abbreviations.
16 | const aF = 'AnimationFrame';
17 | const rqAF = 'Request' + aF;
18 |
19 | // Checks for firefox 4 - 10 function pair mismatch.
20 | const mozRAF = window.mozRequestAnimationFrame;
21 | const mozCAF = window.mozCancelAnimationFrame;
22 | const hasMozMismatch = mozRAF && !mozCAF;
23 |
24 | // Final assigned functions.
25 | var assignedRequestAnimationFrame;
26 | var assignedCancelAnimationFrame;
27 |
28 | // Initial time of the timing lapse.
29 | var previousTime = 0;
30 |
31 | var requestFrameMain;
32 |
33 | // Date.now polyfill, mainly for legacy IE versions.
34 | if (!Date.now) {
35 | Date.now = function () {
36 | return new Date().getTime();
37 | };
38 | }
39 |
40 | /**
41 | * hasIOS6RequestAnimationFrameBug.
42 | * @See {@Link https://gist.github.com/julienetie/86ac394ec41f1271ff0a}
43 | * - for Commentary.
44 | * @Copyright 2015 - Julien Etienne.
45 | * @License: MIT.
46 | */
47 | function hasIOS6RequestAnimationFrameBug() {
48 | const webkitRAF = window.webkitRequestAnimationFrame;
49 | const rAF = window.requestAnimationFrame;
50 |
51 | // CSS/ Device with max for iOS6 Devices.
52 | const hasMobileDeviceWidth = screen.width <= 768 ? true : false;
53 |
54 | // Only supports webkit prefixed requestAnimtionFrane.
55 | const requiresWebkitprefix = !(webkitRAF && rAF);
56 |
57 | // iOS6 webkit browsers don't support performance now.
58 | const hasNoNavigationTiming = window.performance ? false : true;
59 |
60 | const iOS6Notice = `setTimeout is being used as a substitiue for
61 | requestAnimationFrame due to a bug within iOS 6 builds`;
62 |
63 | const hasIOS6Bug = requiresWebkitprefix && hasMobileDeviceWidth && hasNoNavigationTiming;
64 |
65 | const bugCheckresults = (timingFnA, timingFnB, notice) => {
66 | if (timingFnA || timingFnB) {
67 | console.warn(notice);
68 | return true;
69 | } else {
70 | return false;
71 | }
72 | };
73 |
74 | const displayResults = (hasBug, hasBugNotice, webkitFn, nativeFn) => {
75 | if (hasBug) {
76 | return bugCheckresults(webkitFn, nativeFn, hasBugNotice);
77 | } else {
78 | return false;
79 | }
80 | };
81 |
82 | return displayResults(hasIOS6Bug, iOS6Notice, webkitRAF, rAF);
83 | }
84 |
85 | /**
86 | * Native clearTimeout function.
87 | * @return {Function}
88 | */
89 | function clearTimeoutWithId(id) {
90 | clearTimeout(id);
91 | }
92 |
93 | /**
94 | * Based on a polyfill by Erik, introduced by Paul Irish &
95 | * further improved by Darius Bacon.
96 | * @see {@link http://www.paulirish.com/2011/
97 | * requestanimationframe-for-smart-animating}
98 | * @see {@link https://github.com/darius/requestAnimationFrame/blob/
99 | * master/requestAnimationFrame.js}
100 | * @callback {Number} Timestamp.
101 | * @return {Function} setTimeout Function.
102 | */
103 | function setTimeoutWithTimestamp(callback) {
104 | let immediateTime = Date.now();
105 | let lapsedTime = Math.max(previousTime + 16, immediateTime);
106 | return setTimeout(function () {
107 | callback(previousTime = lapsedTime);
108 | }, lapsedTime - immediateTime);
109 | }
110 |
111 | /**
112 | * Queries the native function, prefixed function
113 | * or use the setTimeoutWithTimestamp function.
114 | * @return {Function}
115 | */
116 | function queryRequestAnimationFrame() {
117 | if (Array.prototype.filter) {
118 | assignedRequestAnimationFrame = window['request' + aF] || window[vendors.filter(function (vendor) {
119 | if (window[vendor + rqAF] !== undefined) return vendor;
120 | }) + rqAF] || setTimeoutWithTimestamp;
121 | } else {
122 | return setTimeoutWithTimestamp;
123 | }
124 | if (!hasIOS6RequestAnimationFrameBug()) {
125 | return assignedRequestAnimationFrame;
126 | } else {
127 | return setTimeoutWithTimestamp;
128 | }
129 | }
130 |
131 | /**
132 | * Queries the native function, prefixed function
133 | * or use the clearTimeoutWithId function.
134 | * @return {Function}
135 | */
136 | function queryCancelAnimationFrame() {
137 | let cancellationNames = [];
138 | if (Array.prototype.map) {
139 | vendors.map(function (vendor) {
140 | return ['Cancel', 'CancelRequest'].map(function (cancellationNamePrefix) {
141 | cancellationNames.push(vendor + cancellationNamePrefix + aF);
142 | });
143 | });
144 | } else {
145 | return clearTimeoutWithId;
146 | }
147 |
148 | /**
149 | * Checks for the prefixed cancelAnimationFrame implementation.
150 | * @param {Array} prefixedNames - An array of the prefixed names.
151 | * @param {Number} i - Iteration start point.
152 | * @return {Function} prefixed cancelAnimationFrame function.
153 | */
154 | function prefixedCancelAnimationFrame(prefixedNames, i) {
155 | let cancellationFunction;
156 | for (; i < prefixedNames.length; i++) {
157 | if (window[prefixedNames[i]]) {
158 | cancellationFunction = window[prefixedNames[i]];
159 | break;
160 | }
161 | }
162 | return cancellationFunction;
163 | }
164 |
165 | // Use truthly function
166 | assignedCancelAnimationFrame = window['cancel' + aF] || prefixedCancelAnimationFrame(cancellationNames, 0) || clearTimeoutWithId;
167 |
168 | // Check for iOS 6 bug
169 | if (!hasIOS6RequestAnimationFrameBug()) {
170 | return assignedCancelAnimationFrame;
171 | } else {
172 | return clearTimeoutWithId;
173 | }
174 | }
175 |
176 | function getRequestFn() {
177 | if (hasMozMismatch) {
178 | return setTimeoutWithTimestamp;
179 | } else {
180 | return queryRequestAnimationFrame();
181 | }
182 | }
183 |
184 | function getCancelFn() {
185 | return queryCancelAnimationFrame();
186 | }
187 |
188 | function setNativeFn() {
189 | if (hasMozMismatch) {
190 | window.requestAnimationFrame = setTimeoutWithTimestamp;
191 | window.cancelAnimationFrame = clearTimeoutWithId;
192 | } else {
193 | window.requestAnimationFrame = queryRequestAnimationFrame();
194 | window.cancelAnimationFrame = queryCancelAnimationFrame();
195 | }
196 | }
197 |
198 | /**
199 | * The type value "request" singles out firefox 4 - 10 and
200 | * assigns the setTimeout function if plausible.
201 | */
202 |
203 | switch (type) {
204 | case 'request':
205 | case '':
206 | requestFrameMain = getRequestFn();
207 | break;
208 |
209 | case 'cancel':
210 | requestFrameMain = getCancelFn();
211 | break;
212 |
213 | case 'native':
214 | setNativeFn();
215 | break;
216 | default:
217 | throw new Error('RequestFrame parameter is not a type.');
218 | }
219 | return requestFrameMain;
220 | }
221 |
222 | export default requestFrame;
223 |
--------------------------------------------------------------------------------
/dist/request-frame.js:
--------------------------------------------------------------------------------
1 | /**
2 | * request-frame - requestAnimationFrame & cancelAnimationFrame polyfill for optimal cross-browser development.
3 | * @version v1.5.3
4 | * @license MIT
5 | * Copyright Julien Etienne 2015 All Rights Reserved.
6 | */
7 | (function (global, factory) {
8 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
9 | typeof define === 'function' && define.amd ? define(factory) :
10 | (global.requestFrame = factory());
11 | }(this, (function () { 'use strict';
12 |
13 | /**
14 | * @param {String} type - request | cancel | native.
15 | * @return {Function} Timing function.
16 | */
17 | function requestFrame(type) {
18 | // The only vendor prefixes required.
19 | var vendors = ['moz', 'webkit'];
20 |
21 | // Disassembled timing function abbreviations.
22 | var aF = 'AnimationFrame';
23 | var rqAF = 'Request' + aF;
24 |
25 | // Checks for firefox 4 - 10 function pair mismatch.
26 | var mozRAF = window.mozRequestAnimationFrame;
27 | var mozCAF = window.mozCancelAnimationFrame;
28 | var hasMozMismatch = mozRAF && !mozCAF;
29 |
30 | // Final assigned functions.
31 | var assignedRequestAnimationFrame;
32 | var assignedCancelAnimationFrame;
33 |
34 | // Initial time of the timing lapse.
35 | var previousTime = 0;
36 |
37 | var requestFrameMain;
38 |
39 | // Date.now polyfill, mainly for legacy IE versions.
40 | if (!Date.now) {
41 | Date.now = function () {
42 | return new Date().getTime();
43 | };
44 | }
45 |
46 | /**
47 | * hasIOS6RequestAnimationFrameBug.
48 | * @See {@Link https://gist.github.com/julienetie/86ac394ec41f1271ff0a}
49 | * - for Commentary.
50 | * @Copyright 2015 - Julien Etienne.
51 | * @License: MIT.
52 | */
53 | function hasIOS6RequestAnimationFrameBug() {
54 | var webkitRAF = window.webkitRequestAnimationFrame;
55 | var rAF = window.requestAnimationFrame;
56 |
57 | // CSS/ Device with max for iOS6 Devices.
58 | var hasMobileDeviceWidth = screen.width <= 768 ? true : false;
59 |
60 | // Only supports webkit prefixed requestAnimtionFrane.
61 | var requiresWebkitprefix = !(webkitRAF && rAF);
62 |
63 | // iOS6 webkit browsers don't support performance now.
64 | var hasNoNavigationTiming = window.performance ? false : true;
65 |
66 | var iOS6Notice = 'setTimeout is being used as a substitiue for \n requestAnimationFrame due to a bug within iOS 6 builds';
67 |
68 | var hasIOS6Bug = requiresWebkitprefix && hasMobileDeviceWidth && hasNoNavigationTiming;
69 |
70 | var bugCheckresults = function bugCheckresults(timingFnA, timingFnB, notice) {
71 | if (timingFnA || timingFnB) {
72 | console.warn(notice);
73 | return true;
74 | } else {
75 | return false;
76 | }
77 | };
78 |
79 | var displayResults = function displayResults(hasBug, hasBugNotice, webkitFn, nativeFn) {
80 | if (hasBug) {
81 | return bugCheckresults(webkitFn, nativeFn, hasBugNotice);
82 | } else {
83 | return false;
84 | }
85 | };
86 |
87 | return displayResults(hasIOS6Bug, iOS6Notice, webkitRAF, rAF);
88 | }
89 |
90 | /**
91 | * Native clearTimeout function.
92 | * @return {Function}
93 | */
94 | function clearTimeoutWithId(id) {
95 | clearTimeout(id);
96 | }
97 |
98 | /**
99 | * Based on a polyfill by Erik, introduced by Paul Irish &
100 | * further improved by Darius Bacon.
101 | * @see {@link http://www.paulirish.com/2011/
102 | * requestanimationframe-for-smart-animating}
103 | * @see {@link https://github.com/darius/requestAnimationFrame/blob/
104 | * master/requestAnimationFrame.js}
105 | * @callback {Number} Timestamp.
106 | * @return {Function} setTimeout Function.
107 | */
108 | function setTimeoutWithTimestamp(callback) {
109 | var immediateTime = Date.now();
110 | var lapsedTime = Math.max(previousTime + 16, immediateTime);
111 | return setTimeout(function () {
112 | callback(previousTime = lapsedTime);
113 | }, lapsedTime - immediateTime);
114 | }
115 |
116 | /**
117 | * Queries the native function, prefixed function
118 | * or use the setTimeoutWithTimestamp function.
119 | * @return {Function}
120 | */
121 | function queryRequestAnimationFrame() {
122 | if (Array.prototype.filter) {
123 | assignedRequestAnimationFrame = window['request' + aF] || window[vendors.filter(function (vendor) {
124 | if (window[vendor + rqAF] !== undefined) return vendor;
125 | }) + rqAF] || setTimeoutWithTimestamp;
126 | } else {
127 | return setTimeoutWithTimestamp;
128 | }
129 | if (!hasIOS6RequestAnimationFrameBug()) {
130 | return assignedRequestAnimationFrame;
131 | } else {
132 | return setTimeoutWithTimestamp;
133 | }
134 | }
135 |
136 | /**
137 | * Queries the native function, prefixed function
138 | * or use the clearTimeoutWithId function.
139 | * @return {Function}
140 | */
141 | function queryCancelAnimationFrame() {
142 | var cancellationNames = [];
143 | if (Array.prototype.map) {
144 | vendors.map(function (vendor) {
145 | return ['Cancel', 'CancelRequest'].map(function (cancellationNamePrefix) {
146 | cancellationNames.push(vendor + cancellationNamePrefix + aF);
147 | });
148 | });
149 | } else {
150 | return clearTimeoutWithId;
151 | }
152 |
153 | /**
154 | * Checks for the prefixed cancelAnimationFrame implementation.
155 | * @param {Array} prefixedNames - An array of the prefixed names.
156 | * @param {Number} i - Iteration start point.
157 | * @return {Function} prefixed cancelAnimationFrame function.
158 | */
159 | function prefixedCancelAnimationFrame(prefixedNames, i) {
160 | var cancellationFunction = void 0;
161 | for (; i < prefixedNames.length; i++) {
162 | if (window[prefixedNames[i]]) {
163 | cancellationFunction = window[prefixedNames[i]];
164 | break;
165 | }
166 | }
167 | return cancellationFunction;
168 | }
169 |
170 | // Use truthly function
171 | assignedCancelAnimationFrame = window['cancel' + aF] || prefixedCancelAnimationFrame(cancellationNames, 0) || clearTimeoutWithId;
172 |
173 | // Check for iOS 6 bug
174 | if (!hasIOS6RequestAnimationFrameBug()) {
175 | return assignedCancelAnimationFrame;
176 | } else {
177 | return clearTimeoutWithId;
178 | }
179 | }
180 |
181 | function getRequestFn() {
182 | if (hasMozMismatch) {
183 | return setTimeoutWithTimestamp;
184 | } else {
185 | return queryRequestAnimationFrame();
186 | }
187 | }
188 |
189 | function getCancelFn() {
190 | return queryCancelAnimationFrame();
191 | }
192 |
193 | function setNativeFn() {
194 | if (hasMozMismatch) {
195 | window.requestAnimationFrame = setTimeoutWithTimestamp;
196 | window.cancelAnimationFrame = clearTimeoutWithId;
197 | } else {
198 | window.requestAnimationFrame = queryRequestAnimationFrame();
199 | window.cancelAnimationFrame = queryCancelAnimationFrame();
200 | }
201 | }
202 |
203 | /**
204 | * The type value "request" singles out firefox 4 - 10 and
205 | * assigns the setTimeout function if plausible.
206 | */
207 |
208 | switch (type) {
209 | case 'request':
210 | case '':
211 | requestFrameMain = getRequestFn();
212 | break;
213 |
214 | case 'cancel':
215 | requestFrameMain = getCancelFn();
216 | break;
217 |
218 | case 'native':
219 | setNativeFn();
220 | break;
221 | default:
222 | throw new Error('RequestFrame parameter is not a type.');
223 | }
224 | return requestFrameMain;
225 | }
226 |
227 | return requestFrame;
228 |
229 | })));
230 |
--------------------------------------------------------------------------------