olefredrik/FoundationPress

How to add custom.js file to Foundation Press starter template?

Closed this issue ยท 10 comments

Yesterday I realized that adding custom.js file into Foundation Press project is still not well explained in docs. It took me 4 hours to figure out, why my custom.js file is not injected into the website, that no console.log from my custom.js file appears in the console.
I did everything step by step like it is described in docs. But there is one thing missing.

For correct addition of custom.js file, that will be visible for Webpack and file will be injected into the website you have to do:

  1. Create new custom.js file in src/assets/js/. If you will be using jQuery, add import $ from 'jquery'; at the top of the file.
  2. In config.yml, add "src/assets/js/custom.js" to PATHS.entries
    3. In library, folder go to enqueue-scripts.php file and add this line below
    wp_enqueue_script( 'custom', get_stylesheet_directory_uri() . '/dist/assets/js/' . foundationpress_asset_path( 'custom.js' ), array(), null , true );
  3. Build (npm start)
  4. You will now have a custom.js file outputted to the dist/assets/js/ directory and injected into website

What did you expect to happen?
I expected that my file will be simply injected into the website.

What happened instead?
The file was visible for webpack and included into /dist folder but not injected into the website.

Please List the Following:

  • OS & version: Mac OS X Sierra
  • Node version (node -v) [Node v4+ is required] : Node v6.11.5
  • FoundationPress version (see line 3 in package.json): 2.10.4

Adding custom JS within FP doesn't necessarily need to entail adding additional Webpack entry points - you can accomplish this by simply creating modules and importing them within app.js (which is mentioned in the readme).

At the most basic, this would mean creating a 'customModule.js' file within src/assets/js/, which exports a function/object/class/whatever, and then import it within app.js to initialize it.

src/assets/js/customModule.js:
----

export default {
   init() {
        console.log('hello');
        this.something();
    },
    
    something() {
        console.log('something called');
    }
}
back in app.js now:
----

import $ from 'jquery';
import whatInput from 'what-input';
import customModule from './customModule.js'; // add import statement at the top of app.js

$(document).ready(() => {
    customModule.init();
}); // call your custom module however you'd like

// console output in browser:
customModule.js:3 hello
customModule.js:8 something called

Rinse and repeat for every custom module you need.

Have fun!

Thanks. Was looking for exactly the same thing, and also doubted between import via app.js or extra entries in webpack. So thankyou very much

FWIW
The README states it like this btw:
If you need to output additional JavaScript files separate from app.js, do the following:

  • Create new custom.js file in src/assets/js/. If you will be using jQuery, add import $ from 'jquery'; at the top of the file.
  • In config.yml, add src/assets/js/custom.js to PATHS.entries.
  • Build (npm start)
  • You will now have a custom.js file outputted to the dist/assets/js/ directory.

@tomhermans

Be careful though; there is a distinction between outputting additional JS files (the portion you've quoted) and simply adding/importing modules within app.js.

See the first paragraph under, "JavaScript Compilation" in the readme:

All JavaScript files, including Foundation's modules, are imported through the src/assets/js/app.js file. The files are imported using module dependency with webpack as the module bundler.

...which is accurate.

Thanks for clarifying @conorbarclay

I have a related issue:
I want to add a simple js file to my project. I created a file named login.js in the source/assets/js folder. It has one function:
function myLogin() {
alert("login");
}
In the app.js right after window.$ = $; I included this line:
require('./login.js');

Everything compiles fine and looking at the app.js in dist under Chrome dev I can see the function at the bottom of the file.

But when I select a button that was defined with
onclick="myLogin();"
I get this error
Uncaught ReferenceError: myLogin is not defined

Everything I have read states that this should work and since I can see the function in the dist app.js file I am not sure what is wrong here.

You need to make the function globally available, which you can do by adding it as a member of the window object:

window.myLogin = myLogin;

Any reason though why you're not just setting it up as a click handler via the module?

Thanks. That did the trick. I just added it right after the definition. If that is not the correct place please advise.

Any reason though why you're not just setting it up as a click handler via the module?
Other than stupidity? What module are you referring to? It was assigned as a click event for the button.

@aesculus No prob! Glad that worked out for ya. Yep, after the definition is fine.

I was referring to the login function in your example. As opposed to globally-exposing the function, you could always just assign your button an ID or class and handle the click within the module itself:

document.getElementById('#login-button').addEventListener('click', () => {
    console.log('run login function');
});

Depends on context and personal preference though, I guess!

Depends on context and personal preference though, I guess!
I guess this is sort of how I have done it in the past. Old habits. I am a bit leary leaving around a bunch of listeners. :-)

I was thinking though your question was more pointed at why I did not process this as a submit since it is the action button for a form, but then I never really stated that.

Thanks for this thread.
I tried to add my scripts as new entries in gulpfile.babel.js then added

.pipe($.concat('app.js'))

in gulp build() and watch() tasks.
The build goes well and a unique app.js is generated but changes made in my scripts are not reported to this one. I can't figure why. Do you have an explanation ?

Anyway,

require('./custom.js');

is the right way to do so.