Alexander Solonik
Alexander Solonik

Reputation: 10250

understanding 3d transform detection code modenizer

i was just going through the code of modenizer , because i need to implement a little feature detection in my small online application . so the check i need is for cssTransform3d I.E to check for 3dTranforms ,if its available in the browser.

tests['csstransforms3d'] = function() {

    var ret = !!testPropsAll('perspective');

                  if ( ret && 'webkitPerspective' in docElement.style ) {

                  injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){
                                              #modernizr{left:9px;position:absolute;height:3px;}
                                              }',
                  function( node, rule ) {
                      ret = node.offsetLeft === 9 && node.offsetHeight === 3;
                  });
    }
    return ret;
};

now check the callback function inside injectElementWithStyles , there are two params being passed , node and rule , who is passing these parameters ? i see nowhere in the global variable declaration that these variables are being declared.

The injectElementWithStles function is as follows ::

injectElementWithStyles = function( rule, callback, nodes, testnames ) {

  var style, ret, node, docOverflow,
      div = document.createElement('div'),
            body = document.body,
            fakeBody = body || document.createElement('body');

  if ( parseInt(nodes, 10) ) {
          while ( nodes-- ) {
          node = document.createElement('div');
          node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
          div.appendChild(node);
      }
  }

            style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
  div.id = mod;
      (body ? div : fakeBody).innerHTML += style;
  fakeBody.appendChild(div);
  if ( !body ) {
            fakeBody.style.background = '';
            fakeBody.style.overflow = 'hidden';
      docOverflow = docElement.style.overflow;
      docElement.style.overflow = 'hidden';
      docElement.appendChild(fakeBody);
  }

  ret = callback(div, rule);
    if ( !body ) {
      fakeBody.parentNode.removeChild(fakeBody);
      docElement.style.overflow = docOverflow;
  } else {
      div.parentNode.removeChild(div);
  }

  return !!ret;

},

now i am relatively new to js , yet i have tried making sense of both these functions , as far as i know a variable or parameter needs to be initialized/declared before being passed ,but i don't see either node or rule being declared , can somebody explain what is happening and what values do these variables take ?

Thank you.

Alex-z.

Upvotes: 0

Views: 75

Answers (1)

Antonio Laguna
Antonio Laguna

Reputation: 9290

So, let me try to explain.

Signature for the injectElementWithStyles is rule, callback, nodes, testnames which means that those are the parameters it's expecting.

When that function is called, it's passing just rule and callback:

injectElementWithStyles(
'@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
 ret = node.offsetLeft === 9 && node.offsetHeight === 3;
});

So, bear in mind that the function is the second parameter to the injectElementWithStyles function. Note that the function being passed (the one that confuses you) is not being invoked just yet, it's being passed as a parameter to the injectElementWithStyles.

Within that function, the callback is called like this:

ret = callback(div, rule);

Which, as you see, matches the signature of the callback passed: That is, div is node and rule is... well... rule.

Is in that moment that the execution flow goes to the troubling function and node will have the value of div (declared in that function) and rule will hold the value of rule (declared in that function too)

Hope this clarifies!


Now, you may want to look at Modernizr.addTest which accepts a rule name and a function to be evaluated that must return true or false. So, in your app, let's say you want to test if you're in production:

Modernizr.addTest('production', function () {
    return window.isProduction;
});

That will add the class production to the HTML element if window.isProduction is true and no-production otherwise.

Upvotes: 1

Related Questions