How do you add a simple javascript function in Sage 9?

This is related to my other post but I’m really struggling with the most basic thing in Sage 9.

All I’m trying to do is define a new function:

function do_something(){ console.log('doing something'); }

Then in my blade template:

jQuery(document).ready(function(){ do_something(); }

This couldn’t be more simple!

But all I’m getting are reference errors - ReferenceError: do_something is not defined and it doesn’t seem to matter whether my function is in main.js or a seperate file which I enqueue. This is so frustrating!

I’m not that up to speed on ES6 or eslint, nor webpack for that matter, so I realise that this is probably just my lack of understanding and that I’m going to need to brush up my skillset but if you could explain to me what I need to do in simple terms, I’d really appreciate it.

Kevin

2 Likes

You could try putting it in assets/scripts/routes/common.js under the init function if its a global function, here is a working example.
export default {
init() {
// JavaScript to be fired on all pages
$(".hamburger").click(function() {
$(this).toggleClass(“is-active”);
$("#primary_nav").toggleClass(“is-active”);
});
},
finalize() {
// JavaScript to be fired on all pages, after page specific JS is fired
},
};

Hi there,

That works for binding events to stuff but I’m talking about adding a very bog standard javascript function - something that I can call from any template at any time. If I add my do_something function to assets/scripts/routes/common.js I just get a reference error!

Kevin

I have problems with JS all the time, have you tried just creating your custom.js file in assets/scripts and importing it into main.js?

I am enqueueing a seperate file in setup.php at the moment because I intend to have all my ajax functions in it, so I need to localize the ajax_script. However I did also try importing the file straight into main.js as well with no luck!

I really don’t understand why the most basic javascript handling has been overcomplicated to the point where I can’t wrap my head around how write a simple function?!?! Is it just me?

Kevin

1 Like

If using jQuery, it might depend on the version, I agree, I think Sage 9 is pretty good but have problems with some imports, especially from node_modules regarding javascript and others like font-awesome (I just link to cdn for that now in head.blade). It seems strange that you cant load a small function though, mine seem to load OK. Is it an error in Chrome dev tools or from jshint? Is it a vanilla project via composer or a GitHub prebuilt one? You are welcome to try mine on GitHub, it is just using Bulma CSS file, jQuery 3 and hamburgers which you can replace with anything you like just remove them (and link to font-awesome in head.blade if you don’t need it). But it has app.blade set to pull in different headers for the front page and others and custom templates for the actual pages and extra widgets for large footer in setup.php. I use an edited web pack.config file to get rid of constant errors which prevent building, that’s in there. Functions seem to work OK although there are only a couple, so yours might as well. Its got Advanced custom fields also added and woocommerce support. If you are stuck give it a try, its latest sage 9.
https://github.com/minimallinux/sage9bulma.git still needs a couple of things for footer but you would probably design your own anyway.

Hi,

Thanks, I’d really like to try and understand what’s going on with my implementation though, you’re right it does seem so odd!

As a test I’ve just amended my enqueued file in the dist/scripts directory - basically removing ALL of the webpack stuff and just leaving my function. Hey presto… that worked!!! So this is something to do with webpack, which I really don’t understand at all. Is there something I need to do to the webpack config to get it to exclude this file or something - thoughts??

Kevin

Hi, the problem with that is that on rebuild/further build your amendments will be overwritten so you have to keep altering it. That’s not really ideal.Dist is for the processed files which should start off in the assets directory. You don’t want it to exclude your function, you want it to be processed and added to main or common.js, which enables you to call it from anywhere. Also, you shouldn’t actually have to enqueue the file at all if it is imported to main.js. It’s just a document ready function and should really probably be in common.js under init function which makes it available globally, or you can add a conditional for individual pages there. This should definitely be a very simple task so I don’t know what the problem is. Webpack is set up to do quite a lot of things in Sage which would take possibly days to do otherwise so it’s probably better to leave it unless you know a lot about it other than remove the jshint stuff which I don’t bother with.
I would say there is possibly an error in your Sage setup somewhere.

Yes I agree with you, I was just testing to see if the function worked without the webpack stuff in the file and it did, but I don’t get why in all honesty.

So if you were to put a simple function into your common.js how would you actually do it? What would it look like and how would you call it?

Kevin

Presuming its ajQuery function, in common.js under the init function it is initiated on app load automatically. So take the one I used earlier
export default {
init() {
// JavaScript to be fired on all pages
$(".hamburger").click(function() {
$(this).toggleClass(“is-active”);
$("#primary_nav").toggleClass(“is-active”);
});

This is global and is called by the click action on the hamburger icon, there is nothing in the template file other than tags and classes/ids.





Its not in hamburger docs but I simply added another call to toggle the primary_nav opacity (in css) from 0 to the active state which is 1 in the same click event.

There’s no call in the template (header.blade). As far as I am aware it doesn’t need to be a document ready function here, as it is loaded already on app boot.
Just to make sure right now I removed the hamburger toggle to ensure there is nothing in the hamburger code doing anything, and it worked fine (the primary_nav fade in/out)
So although its a very simple example, it does work and should work for other functions.
Obviously, it depends on what you want to do, you may have to echo some functions or use script tags but if they are present in your dist folder they should work. You want to use ajax, but as that is part of jQuery there shouldn’t be a problem. jQuery version I am on here is 3.3.1, earlier versions have some things deprecated so it may be worth checking that out.

Hi,

No I don’t mean jquery binding, that works fine for me. I mean a simple javascript function with the function keyword. Like my original function above -

function do_something(){ console.log('doing something'); }

if you put that in your common.js file, and call it on your template using

jQuery(document).ready(function(){ do_something(); }

Does that work for you?

I’m trying to work out if it is a problem with my configuration.

Cheers for help so far
Kevin

I just added the function in common.js and it compiled in to dist, appearing in main.js (that’s where its supposed to go!) So I am just having a look now, but get a no-unused-var error unless I also call the function in common.js. Not very helpful as although it works (console message displayed) changing it to a document.write displays only the message and no other page content. But I think it’s the correct place to put it. Blade templates have a way of using javascript, might help to check out the docs at https://laravel.com/docs/5.6/blade#blade-and-javascript-frameworks for a way of using the function in specific page templates. (probably an echo or similar). However still have to find a way of declaring the function, which I think you definitely can do, in common.js. I think its along the right lines, just needs a bit of figuring out ! You can create custom templates for any page in either views or partials as long as app.blade is set up correctly, and just assign them from Wordpress Admin in the dropdown when you create a page.

Update, yes the jQuery(document).ready(function(){ do_something(); } call works in my front page template using script tags, so I do get a console log.

Hi, thanks for checking, could you post your full common.js for me to take a look then?? That would be helpful

document.write removes all the page content, however !

Common.js below
export default {
init() {
// JavaScript to be fired on all pages
$(".hamburger").click(function() {
$(this).toggleClass(“is-active”);
$("#primary_nav").toggleClass(“is-active”);
});
function do_something() {
console.log(‘doing something’);
}
do_something();
},
finalize() {
// JavaScript to be fired on all pages, after page specific JS is fired
},
};

Have to call the function there aswell to avoid no-unused-vars error.

I used // eslint-disable-next-line no-unused-vars above the function to clear that error

And this works for you in your template? So why’s it not working for me then? I really don’t get this

Kevin

Yes it works but only if you also call the function in common like above, otherwise nothing.

In Template

Screenshot (ignore file not found errors!

Let me know if you figure out a better way as I would definitely like to know. Being able to add custom javascript is a big plus and can save using resource hogging plugins.

Template code is not showing in Discourse, but its just script tags with the call in it.

Well thanks for looking, I don’t think this is just a ‘big plus’ for me it’s essential and I can’t believe that it’s this difficult to add a simple a javascript function.

Can anyone else shed any light on this issue? If I can’t find a solution I’m going to have to revert to Sage 8.5 because I’ve built lots of sites with this exact thing without any problems using that!

Kevin