Search code examples
javascriptbrowserrequirejsamdclassiejs

Why does this cause "Mismatched anonymous define()" in requireJS?


I'm using a module called classie.js, whose codes can be viewed below:

/*!
 * classie - class helper functions
 * from bonzo https://github.com/ded/bonzo
 * 
 * classie.has( elem, 'my-class' ) -> true/false
 * classie.add( elem, 'my-new-class' )
 * classie.remove( elem, 'my-unwanted-class' )
 * classie.toggle( elem, 'my-class' )
 */

/*jshint browser: true, strict: true, undef: true */
/*global define: false */

( function( window ) {

'use strict';

// class helper functions from bonzo https://github.com/ded/bonzo

function classReg( className ) {
  return new RegExp("(^|\\s+)" + className + "(\\s+|$)");
}

// classList support for class management
// altho to be fair, the api sucks because it won't accept multiple classes at once
var hasClass, addClass, removeClass;

if ( 'classList' in document.documentElement ) {
  hasClass = function( elem, c ) {
    return elem.classList.contains( c );
  };
  addClass = function( elem, c ) {
    elem.classList.add( c );
  };
  removeClass = function( elem, c ) {
    elem.classList.remove( c );
  };
}
else {
  hasClass = function( elem, c ) {
    return classReg( c ).test( elem.className );
  };
  addClass = function( elem, c ) {
    if ( !hasClass( elem, c ) ) {
      elem.className = elem.className + ' ' + c;
    }
  };
  removeClass = function( elem, c ) {
    elem.className = elem.className.replace( classReg( c ), ' ' );
  };
}

function toggleClass( elem, c ) {
  var fn = hasClass( elem, c ) ? removeClass : addClass;
  fn( elem, c );
}

var classie = {
  // full names
  hasClass: hasClass,
  addClass: addClass,
  removeClass: removeClass,
  toggleClass: toggleClass,
  // short names
  has: hasClass,
  add: addClass,
  remove: removeClass,
  toggle: toggleClass
};

//transport
if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( classie );
} else {
  //browser global
  window.classie = classie;
}

})( window );

And I wrote this in HTML:

<script data-main="js/main.js" src="bower_components/requirejs/require.js"></script>
<script src="js/classie.js"></script>

Then the browser complains:

[Error] Error: Mismatched anonymous define() module: [object Object]
http://requirejs.org/docs/errors.html#mismatch
    defaultOnError (require.js, line 141)
    onError (require.js, line 545)
    intakeDefines (require.js, line 1229)
    (anonymous function) (require.js, line 1416)

What seems weird to me is the last lines in classie.js:

//transport
if ( typeof define === 'function' && define.amd ) {
  // AMD
  define( classie );
} else {
  //browser global
  window.classie = classie;
}

It looks like classie.js tries its best to keep compatible with AMD because it test whether define is a function and has amd attribute before using it. But unfortunately this caused an error in the browser. Shouldn't requirejs the most famous library that implements AMD? Why doesn't it work?


Solution

  • As you discovered, classie is designed to be loaded with an AMD loader. So when you load it, it detect that an AMD loader is present and calls define.

    The problem is that you are trying to load it with a script element. AMD modules must be loaded through their loader, not directly through script. This is why you are getting the error message you are getting.