jensarps / AMD-feature

A loader plugin for AMD loaders
Other
161 stars 10 forks source link

Issues creating a polyfill for matchMedia #5

Closed patocallaghan closed 11 years ago

patocallaghan commented 11 years ago

Hey,

I was happy to find that you'd included functionality recently to allow for direct-loading of Javascript objects.

I took your JSON example and have tried to re-implement it but this time doing matchMedia, a native object used for media queries. It uses this polyfill as a fallback.

While it pretty much looks exactly the same as your example I can't seem to get it to work. Neither in a build or in a non-supporting browser (IE9). Yet if I use it in a supporting browser it works fine. Just for testing sake I swapped the isAvailable test to be return typeof matchMedia === 'undefined'; and it correctly loaded matchMedia.js into Chrome thinking it needed a polyfill.

I keep getting the error matchMedia is undefined on the first line of dynamic.js.

define( {
    'matchMedia': [
        {
            isAvailable: function () {
                // test if native matchMedia is available
                return typeof matchMedia != 'undefined';
            },

            // if so, directly use the matchMedia object as module
            module: matchMedia
        },
        {
            isAvailable: function () {
                // This is the fallback
                return true;
            },

            // return the path to some matchMedia implementation
            implementation: 'matchMedia'
        }
    ]
} );

Any ideas?

Update: I've also found it does the same if I swap it out for the JSON example and try it in IE7 (which has no JSON support). It tells me JSON is undefined yet if I try it in IE8 and reverse the isAvailable test around, it loads the polyfill in IE8 with no problems.

Thanks, Pat

jensarps commented 11 years ago

Hi,

yeah, sorry for that, my JSON example is wrong there: If you try to assign the unknown matchMedia to the module property, you'll run into a ReferenceError. What you need to do is to reference the potentially unknown object through the global object (window in this case), like this:

define( {
  'matchMedia': [
    {
      isAvailable: function () { /* ... */ },

      // if so, directly use the matchMedia object as module
      module: window.matchMedia
    }
    /* ... */
  ]
} );

For the sake of readability, you can also use window.matchMedia in the typeof check.

I'll also update the JSON example.

Thanks for pointing this out!

jensarps commented 11 years ago

Ah, wait, no – the build tool probably doesn't know of a global window property – let me think about this…

jensarps commented 11 years ago

Ok, the only way around this to wrap the module value in a function. For matchMedia, it would look like this:

define({
  'matchMedia': [
    {
      isAvailable: function () {
        // test if native matchMedia is available
        return typeof matchMedia != 'undefined';
      },

      // if so, directly use the matchMedia object as module
      module: function () {
        return matchMedia;
      }
    },
    {
      isAvailable: function () {
        // This is the fallback
        return true;
      },

      // return the path to some matchMedia implementation
      implementation: 'matchMedia'
    }
  ]
});

Please update AMD-Feature to the latest version (1.1.0 as of now).

Thanks again!

patocallaghan commented 11 years ago

Thanks very much for the quick turnaround! I'll give it a go tomorrow and let you know if I have any issues..