Skip to main content

The Cheeky Monkey Media Blog

A few words from the apes, monkeys, and various primates that make up the Cheeky Monkey Super Squad.

Require JS, Grunt, Bower, Foundation and Drupal - Part 2

Require JS, Grunt, Bower, Foundation and Drupal - Part 2

Welcome back. If you just found this, you might want to start with Part 1 before reading on.

Okay, now we’re going into our custom theme folder (that’s based off the STARTER foundation sub-theme. Check out Justin’s Blog post, on how to set that up.

So, now that you’ve got your custom sub-theme folder and files setup, we be changing some things, and adding MOAR files.

Drupal -- showing it some love.

  1. File: [drupal-root-folder]/sites/all/themes/[themename]/[themename].info 

First your .info file. If you’re using foundation, it should have these lines:

  1. ; Theme scripts (minified).
  2. ; Grunt will compress any custom theme scripts matching the _*.js naming convention
  3. ; into app.min.js.
  4. scripts[] = js/app.min.js 

Problem (not really, but it’s not using our workflow).. The issue here is that foundation does a good thing, and compresses all your custom JS into an “app.min.js” file. But, we can’t use require with that, and our require will uglify and compress our custom code anyway. SO, lets comment that out. Put a “;” infront of that “scripts[] = js/app.min.js” line.

Now the template php file.

  1. File: [drupal-root-folder]/sites/all/themes/[themename]/template.php

In your custom theme folder, load up the ‘template.php’ file. Add this line to the top under the <php:

  1. include ('theme-functions.php'); 

Now that theme-functions.php file, that will help Drupal determine if we’re using a ‘development’ environment, or ‘production’.

  1. File: [drupal-root-folder]/sites/all/themes/[themename]/theme-functions.php

  1. /**
  2. * debug switch for debug mode
  3. */
  4. function cmm_is_dev_mode () {
  5. if ( preg_match('/dev$/', $_SERVER['HTTP_HOST']) ) {
  6. return true;
  7. } else {
  8. return false;
  9. }
  10. }

So, this the function that helps us define wether or not we are in a ‘development’ environment or a ‘production’ one. Since I like to have all my ‘dev’ environments end in a .dev domain suffix, it works. But you can tailor it to whatever you use for your local dev environment. In the case of this article, I’m using “drupaltest.dev”. Production would presummably be “drupaltest.com”.

  1. /**
  2. * Path to theme.
  3. */
  4. function cmm_path_to_theme() {
  5. return drupal_get_path('theme', 'drupaltest');
  6. }

Pretty obvious what this one does. Gets the path to your custom sub-theme.

  1. /**
  2. * Helper functions for Require JS include
  3. */
  4. function cmm_rjs_rev() {
  5. return cmm_path_to_theme() ? time() : hashDirectory( drupal_realpath(cmm_path_to_theme() . '/js/src') );
  6. }
  7. function cmm_path_to_rjs_main() {
  8. return '/' . cmm_path_to_theme() . (cmm_is_dev_mode() ? '/js/src' : '/js/dist') . '/main.js?rev=' . cmm_rjs_rev();
  9. }
  10. function cmm_path_to_rjs() {
  11. return '/' . cmm_path_to_theme() . (cmm_is_dev_mode() ? '/js/src' : '/js/dist') . '/vendor/require.js?rev=' . cmm_rjs_rev();
  12. }

Okay, first method just returns a random hash string, that we’ll need for cache busting for requireJS.

Second method there, just returns the proper path to the main.js file, based on if we are on a ‘production’ environment, or ‘development’ environment.

Third method does the same thing, except to the require.js library file itself.

The last method hasDirectory() is what creates that hash string.. Not bothering printing it out here, since… you’ll have it.. you downloaded the source didn’t you.

Change up some template files.

  1. File: [drupal-root-folder]/sites/all/themes/[themename]/templates/html.php.tpl 

I just copied the file from the supplied zurb-foundation templates. And we’re just going to add one line.

  1. <script id="requirejs" data-rev="<?php print cmm_rjs_rev(); ?>" data-main="<?php print cmm_path_to_rjs_main(); ?>" src="<?php print cmm_path_to_rjs(); ?>"></script><script id="requirejs" data-rev="<?php print cmm_rjs_rev(); ?>" data-main="<?php print cmm_path_to_rjs_main(); ?>" src="<?php print cmm_path_to_rjs(); ?>"></script>

That should look familiar. You can see those methods hard at work, printing out the correct paths, to the require.js file, and your main js file that will hold all your custom code. Put that line in the <head>...</head> area.

We’re almost here. Stuff should be loading up and working in drupal now, but lets just take this one step further, and try an example out.

  1. File: [drupal-root-folder]/sites/all/themes/[themename]/js/src/main.js 

So in this file we do one more thing to help get rid of that caching that require js does, when we don’t want it, for development.

  1. var __getrev = function () {
  2. 'use strict';
  3. var rev = document.getElementById('requirejs').getAttribute('data-rev');
  4. return rev || (new Date()).getTime();
  5. };
  6. requirejs.config({
  7. urlArgs: 'rev=' + __getrev()
  8. });

Finally, we can get to our regular scheduled programming, and load up the dependencies, and JS files. In this example, I just load the the ‘homepage’ dependency only IF we are on drupal’s ‘front’ page.

  1. require([
  2. 'jquery',
  3. 'underscore',
  4. 'intentcontext',
  5. ], function ($, _, IntentContext) {
  6. 'use strict';
  7. // DOM ready
  8. $(function() {
  9. // init the DOM elements with intentionJS
  10. IntentContext.intent.elements(document);
  11. IntentContext.intent.on('desktop', function () { });
  12. IntentContext.intent.on('tablet', function () { });
  13. IntentContext.intent.on('mobile', function () { });
  14. // js loaded only on homepage
  15. if ($('body').hasClass('front')) {
  16. require(['homepage']);
  17. }
  18. }); // DOM ready
  19. });

And in our homepage.js file.

  1. File: [drupal-root-folder]/sites/all/themes/[themename]/js/src/modules/homepage.js

  1. define([
  2. 'jquery',
  3. ], function ($) {
  4. 'use strict';
  5. /**
  6. * object constructor
  7. */
  8. var Homepage = function() {
  9. this.init();
  10. };
  11. /**
  12. * init homepage module
  13. */
  14. Homepage.prototype.init = function() {
  15. var self = this;
  16. console.log("Homepage JS Init", self)
  17. };
  18. /**
  19. * DOM ready
  20. */
  21. $(function () {
  22. var home = new Homepage();
  23. });
  24. });

 

So this file, requires ‘jquery’. We then create a new instance, and run it in the .init method -- I also console.log the object, just to see it. You don’t have to follow this same prototyping style of JS programming. But, it find it to be a very scaleable / clean way to work with JS.

 

Hope it wasn’t too painful, happy coding!

 

*cuddles*

 

Download the code from GitHub

Web Development

Would you like to know more about what we do?

View Our Services

Graphic Design Cheeky Monkey

Have a look at some our client work

View Our Work

Cheeky Monkey Discovery

Learn more about Cheeky Monkey Media

About Us

Comments