0

I have several javascript files in custom modules containing many functions which are used across the code. In D6 I simply added them during hook_init() and it was fine.

drupal_add_js("/scripts/jquery.url.js", array('group' => JS_LIBRARY));
drupal_add_js("/scripts/jquery.cookie.js", array('group' => JS_LIBRARY));
drupal_add_js("/scripts/mymod.funcs.js", array('group' => JS_DEFAULT));
...
drupal_add_js("/scripts/otherfuncs.js", array('group' => JS_DEFAULT));

However, in D7, I am now getting the "$ is not a function". Wrapping all my code as described in the D6 to 7 conversion wasnt't seeming to work since I was then getting "<one of my functions> is not defined". Using

var $ = jQuery.noConflict();

at the start of my 'parent' file resolved the error. But that doesn't seem like a good idea either. Below is an example of the javascript.

//in main file: mymod.funcs.js, global functions
function my_storage(key) { return value; }

//in another file: otherfuncs.js
Drupal.behaviors.myMod = { attach: myMod_Splash }

function myMod_Display(splash) { ... }  
function myMod_Splash() { 
  var splash = my_storage('splash'); 
  if (splash) { myMod_Display(splash); } 
}

What is wrong when simply wrapping all of it with the recommended? What else should be done, aside from converting the function groups to objects (which still wouldn't necessarily resolve the wrapping problem)?

EDIT: I was wrapping my code like:

//(function ($) { //tried here
Drupal.behaviors.myMod = { attach: myMod_Splash }

(function ($) { //and here
function myMod_Display(splash) { ... }  
function myMod_Splash() { 
  var splash = my_storage('splash'); 
  if (splash) { myMod_Display(splash); } 
}
})(jQuery);

UPDATE: I just removed the "var $ = jQuery.noConflict();" from my file to begin messing with the problem again, and am now getting no errors at all, in Web/Error Console or Watchdog. None of the code was wrapped. I was constantly clearing cache in Drupal before so really have no clue what is going on now. Could the JS aggregation still have been placing the files in the wrong group, hence loading in a conflicting order?

6
  • I'm not sure why the recommended solution isn't working, but as a workaround, you could try replacing all of the $ in your code with jQuery. Jul 17, 2013 at 20:38
  • 1
    Are you sure you were wrapping correctly? Can we see it? Jul 17, 2013 at 21:02
  • did you try to use jQuery instead $, like 'jQuery(document).ready(function($)'...? in function you can continue using $...
    – mixerowsky
    Jul 18, 2013 at 2:23
  • // at the beginning of added sample makes no sense to me. Also, is it wise to attach function not yet defined? Never really worked for me... but maybe it's more of my prejudice than a real problem.
    – Mołot
    Jul 18, 2013 at 13:37
  • I didn't go so far as to start changing over all the '$' to jQuery since it seemed like it should have been working following the conversion doc. Updated post with example of the function wrapping I (attempted to) put in place. Jul 18, 2013 at 13:38

2 Answers 2

0

By the docs You should wrap your code that way:

(function ($) {

  Drupal.behaviors.exampleModule = {
    attach: function (context, settings) {
      $('.example', context).click(function () {
        $(this).next('ul').toggle('show');
      });
    }
  };

})(jQuery);

What's wrong with other methods? Nothing fundamental, only Drupal's own scripts are not tested to work with them, and redefining $ globally may interfere with non-jQuery libraries some modules use, rendering either their or yours code not working.

For "jQuery is not defined", there are couple of possible problems. My surest bet was to skip drupal_add_js() altogether. Unconditional module (or theme) scripts can be added in info files:

scripts[] = somescript.js

and form related ones can be added directly to a form:

$form['#attached']['js'] = array(
  drupal_get_path('module', 'mymodule') . '/js/a.js',
  drupal_get_path('module', 'mymodule') . '/js/b.js',
);

I prefer to leave conditions in javascript itself, it means I only need one aggregated file for all pages on my site (plus one per form), so this is a performance boost in addition to problem prevention.

0

I was wrapping the functions correctly according to the conversion documentation. This, however, was creating a scope for all the functions that had previously resided globally, which is why I started getting the 'not a function' errors, but the code still worked if all the calls were to functions within the same file (since they were all wrapped in the same anonymous function).

So, the dirty fix was simply to create some global variables and assign the functions to them:

var myfunc;
(function ($) {
    myfunc =
    function myfunc() { ... }
})(jQuery);

While this works (if I get the time) it would be better to create global objects to hold the functions and settings. And, also place the loading of those files in the .info file of the module(s).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.