I had a module in Drupal 6 and Ι'm trying to move to drupal 7.
All my old javascript files that used jquery were using the "$" variable. I know I can (should?) use the wrap method :

(function ($) {
  // Original JavaScript code.
})(jQuery);

but this method breaks all the code. I expain :
I include a script in my tpl.php file : drupal_add_js(path_to_theme().'/js/painter.js');
The poor old painter.js used to create a variable this way :

var font = "myfont";

and all my scripts could use this variable because it was in the same scope. If I use the wrap method :

(function ($) {
//Suppose there is some jquery stuff in here too
 var font = "myfont";
})(jQuery);

the font variable is created in a function and thus it becomes a local variable. Of course I could remove the "var"
keyword and it would be ok but it's not just one variable we are talking about. An other solution would be to include this code at the top of my tpl :

<script type="text/javascript">
$=jQuery;
</script>

but I think there must be a good reason not to fall back to the drupal 6 way of coding.

Any help?

Comments

jaypan’s picture

What does the other code you have that is relying on this variable look like? And why can't you wrap it all in the wrapper instead of having it separate?

Contact me to contract me for D7 -> D10/11 migrations.

jimmykarily’s picture

You are right. I didn't make it very clear.
I found a script that builds a font object in javascript with the installed fonts on the client system (from a predefined list). I include the script and I use the font variable on my other scripts. I can merge all the files in one but usually its the opposite I should be doing. I mean, merging every library and script I want to use in one file is quite limiting and not allways good. There may be scripts that will be loaded only if needed and I should repeat this copy paste for every upgrade of every script I want to use. Do you think that setting "$" to jQuery will lead to problems? I googled around to see why $ shouldn't be jQuery any more, but I didn't find a list with the colliding librabries.

BlakeLucchesi’s picture

I too would really like to know more about the decisions behind moving to this style of implementation (specifically in regards to Drupal core). If you find any links to patches or information about it can you please follow up to let us know.

jaypan’s picture

Using this code results in safer code. There are two reasons for this. The first is because the whole code is wrapped in an anonymous function. This means that any functions/variables defined inside the function are only valid in the scope of the function. This prevents collisions with other modules that may make use of the same names. The other is that they have set jQuery to no conflict mode. When setting it to no conflict, the $ sign stops working, as it can collide with other javascript libraries. Instead of using the $ sign, you have to use the full word jQuery. But, they pass jQuery into the function, and inside the function it is given a value of $. This allows the dollar sign to be used, without risking conflict with other libraries.

Contact me to contract me for D7 -> D10/11 migrations.

hargobind’s picture

Part of the reason that D7 uses the wrapped approach is because technically it's "cleaner". While cleanliness on small sites really doesn't matter much, Drupal was built to handle some of the largest sites out there, and sometimes those sites can get pretty complex. You can read more about why the wrapper is necessary in Drupal 7 here: https://drupal.org/update/modules/6/7#javascript_compatibility.

Part of Drupal's mission in cleanliness is avoiding clutter in the global namespace. Therefore if you're wanting to store one or more variables, I recommend two approaches:

1 ) Use the Drupal.settings approach as shown in this example or in drupal_add_js().
Effectively this creates a JavaScript object called Drupal.settings.my_module with whatever properties you specified during the creation of the object.

2 ) Use the "Module Export" approach listed here. With that approach, you would attach all your variables inside the wrapper like this: my.some_var = 'some_val'; And then globally (i.e. from other scripts), you would reference them as MODULE.some_var.