mrksbnch
mrksbnch

Reputation: 1842

How to ignore requestAnimationFrame in browsers which don't support it

Let's say we have a feature / module, that enhances a website. So it is not really necessary and it uses requestAnimationFrame, which is not supported in older browsers like IE8/9. I could polyfill requestAnimationFrame, but since it's just an enhancement, older browsers should simply ignore it. The code for this module looks more or less like this:

;(function( window, document, undefined ) {
    'use strict';

    // Example Module
    // @constructor
    function Module( el, options ) {            
        // ...
    }

    Module.prototype = {
        init: function() {
            // If requestAnimationFrame is not supported, no alert should pop up        
            alert("init");
        },

        method: function() {
            // If requestAnimationFrame is not supported, no alert should pop up
            alert("start");
        }
    };

    window.Module = Module;

})( window, document );

I can then create a new instance

var instance = new Module(document.getElementById('test'));

and "interact" with it

instance.init();
instance.method();

The problem with this code is that in IE9 an error pops up because IE9 doesn't know "newer" functions like requestAnimationFrame. I could just add an if statement to

if ( window.requestAnimationFrame ) {
    var instance = new Module(document.getElementById('test'));
}

and everywhere I use it. It would be much easier to check for requestAnimationFrame support once somewhere in the module though. If it isn't supported nothing should happen, older browser should just ignore it. So I tried doing something like

// @constructor
function Module( el, options ) {            
    if ( !window.requestAnimationFrame ) {
        return false;
    }
    //...
}

But that doesn't prevent older browsers from executing all methods like ".init()" or ".method()" (in this case). Do I really have to put this if statement in every single method or is there anything else i can do?

Upvotes: 0

Views: 2972

Answers (4)

user663031
user663031

Reputation:

The "polyfill" for RAF is just setTimeout. You can find dozens of examples on the web, usually along the lines of

window.requestAnimationFrame = window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame ||
    ... || 
    function (callback) {
        setTimeout(callback, 1000 / 60);
    };

setTimeout does the same thing as RAF, just at a lower resolution and without being so optimized with the engine's rendering process. (RAF also passes a hirez timestamp to the callback.)

Bottom line is there's no reason to worry about RAF not being available and how to fall back if it's not. Just fall back to setTimeout.

If you really want to go without it if it's not available, then just put the following line at the top of your module

var RAF = window.requestAnimationFrame || ... || function() { };

In other words, define it as a null (no-op) function. Then use RAF variable inside your methods.

Upvotes: 2

slebetman
slebetman

Reputation: 113866

I'm not sure why, when you've already figured out the logic, you choose to implement it as a comment instead. Just replace the comments with code and you're good to go:

Module.prototype = {
    init: function() {
        if(typeof requestAnimationFrame === 'undefined') return;        
        alert("init");
    }
};

Or you can check window.requestAnimationFrame if you prefer.


Additional answer:

How to avoid writing many ifs

You can encapsulate the if statement in your own control structure. As usual in javascript, we use functions to implement new 'syntax':

function restricted (f) {
    return function () {
        if(typeof requestAnimationFrame === 'undefined') return;
        return f.apply(this,arguments);
    }
}

Now you can define your methods using restricted(function... instead of function:

Module.prototype = {
    init: restricted(function() {
        alert("init");
    }),

    method: restricted(function() {
        alert("start");
    })
};

Upvotes: 3

tmaximini
tmaximini

Reputation: 8503

You should definitely polyfill it! It will make your code more concise and it is not 'just an enhancement' for browsers, but in this case also an enhancement for the way you can write and structure your own code. You definitely don't want to go that route that you write methods twice with if blocks. Paul Irish made a great Polyfill for RequestAnimationFrame: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

This advice also applies to other browser features, not just RequestAnimationFrame, there are great polyfills for about any feature, e.g. github.com/es-shims/es5-shim

Upvotes: 1

artm
artm

Reputation: 8584

Not sure but would this work:?

if ( window.requestAnimationFrame ){
     Module.prototype = {
        init: function() {
            // If requestAnimationFrame is not supported, no alert should pop up        
            alert("init");
        },

        method: function() {
            // If requestAnimationFrame is not supported, no alert should pop up
            alert("start");
        }
    };
}
else{
  Module.prototype = {
    init: function() {
    },

    method: function() {
    }
   };
}

Then all browsers cal call init and method but methods won't execute anything if it's not suported. So you only have to make the change in the module.

Upvotes: 0

Related Questions