.JS File into our Homepage - doesnt work

Hello at all,

We need some support please with out Homepage. We want to add a special effect, like Snowfall on our Homepage.
I found a german Site with following codes:

And a Script.JS file.
What i already did?
-Create a txt file and paste the script and save as snowfall.js
At the mainpage where we have our background pictures, i try to upload the snowfall.js file. But this doesnt work for me - “wrong filename”
After this i want copy - paste this Line unter our normal text:

Is this the right way i try to do this?

On the Grav Site i see .js files are possible to bind in.
Im very glad if you can support me little bit.
Im new with Grav so please try to explain me éverything little bit more precise.

Thanks for all
best regards johnny.

You can do this by adding the following in the base.html.twig script block:

{% block javascripts %}
 //Here are the rest of the javascript assets
// {% do assets.addJs('theme://js/site.js', { group: 'bottom' }) %}
 {% if page.home == true %}
     {% do assets.addInlineJs(
        '
          your javascript here    
       ', {group:'bottom'}) %}
 {% endif %}
{% endblock %}

{% block assets deferred %}
    {{ assets.all()|raw }}
{% endblock %}

If your script is very long and you want to call it from an external file, you can do the same as the rest, calling it like this:

{% do assets.addJs('theme://js/custom.js', { group: 'bottom' }) %} within your if page.home condition

To complete it, take a look at:

Sorry, im absolut newbie with this theme.

i Upload a picture. Like this i try it. But it doesnt work. With “scriptblock” you mean on any Page(i want, so the mainpage) i can poste your script:

{% block javascripts %}
//Here are the rest of the javascript assets
// {% do assets.addJs(‘theme://js/site.js’, { group: ‘bottom’ }) %}
{% if page.home == true %}
{% do assets.addInlineJs(

your javascript here
', {group:‘bottom’}) %}
{% endif %}
{% endblock %}

{% block assets deferred %}
{{ assets.all()|raw }}
{% endblock %}

and in the middle of your script, i just fill it with my script?
Thats what i try atm.

The second way “if the script is too long” i will try it now.

I can’t see the code in your image well. Can you copy that code here, wrapped in a block with triple quotes like this ``` (opening and closing).

Before posting the comment, make sure in the preview that the code is displayed correctly

It’s just a copy of your code

Sorry, I’m on my phone and I can’t view the image correctly. I will see it at weekend

Thanks for your answer.

i hope you can see direct the script behind the link:
https://www.go4u.de/files/javascript/snowflakes/snowflakes.js

Here the script: I hope it isnt not too long for the answer:
////////////////////////////////////////////////////////////////////////
// SnowFlakes-Script (c) 2022, Dominik Scholz / go4u.de Webdesign
////////////////////////////////////////////////////////////////////////

let snowflakes = (function() {

///////////////////////////// configuration ////////////////////////////

const defaultConfig = {
	amount: 40, // amount of flakes
	color: ['#AAAACC', '#DDDDFF', '#CCCCDD', '#F3F3F3', '#F0FFFF'], // random colors
	fontType: ['Arial Black', 'Arial Narrow', 'Times', 'Comic Sans MS'], //	random fonts
	flakeChar: '*', // char used for flake
	speed: .05, // speed of flakes
	size: [8, 22], // minimum/maximum flake font size
	drift: 15, // horizontal drift
};

///////////////////////////// private vars /////////////////////////////

let config = {},
	flakes = [],
	bodyWidth = 0,
	bodyHeight = 0,
	count = 0,
	lastInterval = 0,
	initialized = false,
	running = false;

////////////////////////////// functions ///////////////////////////////

// auto start on document load
function autostart(userConfig)
{
	window.addEventListener('load', function() { start(userConfig); });
}


// start snow
function start(userConfig)
{
	if (running)
		return;

	running = true;
	config = mergeObjects(userConfig || {}, defaultConfig);
	resize();

	// add new flakes
	while (config.amount > flakes.length)
		createFlake(flakes.length);

	// init snowflakes
	if (!initialized)
	{
		initialized = true;
		window.addEventListener('resize', resize);

		let style = document.createElement('style');
		style.innerHTML = '.js-anim-snowflake { user-select: none; position: absolute; left: 0; top: 0; zIndex: 20000; }';
		document.getElementsByTagName('head')[0].appendChild(style);

		lastInterval = time();
		window.requestAnimationFrame(move);
	}
}


// stop snow
function stop()
{
	running = false;

	let i, l = flakes.length;
	for (i = 0; i < l; i++)
		if (flakes[i].y <= config.size[1])
			removeFlake(i);
}


// return running status
function isRunning()
{
	return running;
}


// creates a new snowflake
function createFlake(i)
{
	let el, f, s;
	
	if (!flakes[i])
	{
		// create new dom el
		el = document.createElement('div');
		el.className = 'js-anim-snowflake';
		el.innerHTML = config.flakeChar;
		flakes[i] = {
			el: el,
			x: 0,
			y: 0,
			size: 0,
			count: 0
		};
		document.getElementsByTagName('body')[0].appendChild(el);
	}

	f = flakes[i];

	// create flake object
	f.size = randomIntFromRange(config.size);
	f.x = randomIntFromRange([config.drift + 1, bodyWidth - config.drift - f.size - 3]);
	f.y = -f.size - randomIntFromRange([0, bodyHeight]);
	f.count = randomIntFromRange([0, 10000]);

	// init flake
	s = f.el.style;
	s.transform = 'translate(0, -' + f.size + 'px)';
	s.color = randomItemFromArray(config.color);
	s.family = randomItemFromArray(config.fontType);
	s.fontSize = f.size + 'px';

}


// remove an existing snowflake
function removeFlake(i)
{
	flakes[i].el.parentNode.removeChild(flakes[i].el);
	flakes[i] = null;
}


// move existing flakes
function move()
{
	window.requestAnimationFrame(move);
	
	// calculate movement factor
	let t = time(),
		dif = t - lastInterval,
		l = flakes.length,
		d = dif * config.speed * config.size[1],
		i, flake, x, y;
		
	lastInterval = t;
	count += dif * config.speed / 20;
	
	for (i = 0; i < l; i++)
	{
		if (null === flakes[i])
		{
			if (running)
				createFlake(i);
			else
				continue;
		}

		flake = flakes[i];
		flake.y += d / flake.size;
		
		// restart existing flake
		if (flake.y + flake.size >= bodyHeight)
		{
			if (running)
				createFlake(i);
			else
				removeFlake(i);
			continue;
		}

		x = flake.x + Math.sin(flake.count + count) * config.drift;
		y = flake.y;

		flake.el.style.transform = 'translate(' + Math.floor(x) + 'px, ' + Math.floor(y) + 'px)';
	}
}


// calculate new positions for all flakes
function resize()
{
	// save old width
	let oldWidth = bodyWidth;

	// get new width and height
	bodyWidth = getWindowWidth() - config.size[1];
	bodyHeight = getWindowHeight() - config.size[1];

	// calculate correction ratio
	let ratio = bodyWidth / oldWidth;
		
	// for all flakes
	for (let i = 0, l = flakes.length, flake; i < l; i++)
	{
		flake = flakes[i];
		if (!flake)
			continue;

		// do width correction
		flake.x *= ratio;
		
		// restart existing flake
		if ((flake.y + flake.size) >= bodyHeight)
			createFlake(i);
	}
}


// get window width
function getWindowWidth()
{
	let w = Math.max(self.innerWidth || 0, window.innerWidth || 0);
	
	if (document.documentElement)
		w = Math.max(w, document.documentElement.clientWidth || 0);
	if (document.body)
	{
		w = Math.max(w, document.body.clientWidth || 0);
		w = Math.max(w, document.body.scrollWidth || 0);
		w = Math.max(w, document.body.offsetWidth || 0);
	}
	
	return w;
}


// get window height
function getWindowHeight()
{
	let h = Math.max(self.innerHeight || 0, window.innerHeight || 0);
	
	if (document.documentElement)
		h = Math.max(h, document.documentElement.clientHeight || 0);
	if (document.body)
	{
		h = Math.max(h, document.body.clientHeight || 0);
		h = Math.max(h, document.body.scrollHeight || 0);
		h = Math.max(h, document.body.offsetHeight || 0);
	}
	
	return h;
}


// get current time
function time()
{
	return +new Date();
}


// return a random integer from a given range
function randomIntFromRange(a)
{
	return Math.floor(a[0] + Math.random() * (a[1] - a[0]));
}


// return a random array element
function randomItemFromArray(a)
{
	return a[Math.floor(Math.random() * a.length)];
}


// merge arrays
function mergeObjects(a, b)
{
	let i, c = {};
	for (i in b) { c[i] = b[i]; }
	for (i in a) { c[i] = a[i]; }
	return c;
}


// return public methods
return {
	autostart: autostart,
	start: start,
	stop: stop,
	isRunning: isRunning
}

}());

snowflakes.autostart();

My first Question:

I need to copy - Paste your script and my script inside. for exampe under “pages” - “home” - “home” here is the header titel. after this sentence i have to paste your script?

for example:

{% block javascripts %}
//Here are the rest of the javascript assets
// {% do assets.addJs(‘theme://js/site.js’, { group: ‘bottom’ }) %}
{% if page.home == true %}
{% do assets.addInlineJs(

your javascript here ? ??? HERE I PASTE MY SCRIPT IN THIS LANE??? :slight_smile:
', {group:‘bottom’}) %}
{% endif %}
{% endblock %}

{% block assets deferred %}
{{ assets.all()|raw }}
{% endblock %}

This was literally the first sentence what @pmoreno suggested

That doesnt work for me. My Homepage was after changing the script, very long. Like a long text or something under the main line. Difficult to explain.

now, i found where to paste the script.

But i need again little bit support please. i was trying to add the script in the base.html.twig

But it doesnt work. Then i was trying add the script in the “site.js” under “Javascript”.

It also not work for me. what am i doing wrong. :))

Sorry, but I think first of all you need a basic understanding of Twig and how Grav assets pipeline works. All info can be found at

Hi, sorry, I thought you knew what I was doing wrong and were still thinking about why and why. Unfortunately you can’t upload screenshots here but I’m doing it right now. I upload pictures of what I have already done and what the result is via other sites. Okay, I’ll read through the Grav Basics - my English isn’t the best, I hope I understand it.

Here is a picture: gravpage hosted at ImgBB — ImgBB

After this procedure 1. edit then 2. base.html.twig then 3. all the way down I then inserted the script & in the time where it says: insert the quick flake script here.

Yes, that’s how I went about it.
I also added the same thing via site.js under “javascript”.

The result was that nothing changed on the site. There were no snowflakes.

Put your whole snoflakes script into a separate JS file. Then add that file to the pipelnie via assets.addJs()

Good Morning, thanks for all! what had am i doing:

-i create a new site1.js file(under user/themes/quark/js) , i paste my script in this new file.
-then i go to twig - user/themes/quark/templates/partials
and i change the name Site.js in Site1.js. I hope i do not lost anything on the original homepage. (i did not create the hp, who would have thought :P)
-but if i copy the hole block and paste it under the “site.js” block, i get an error on the page with “the block javascripts has already been defined line 30”
so i was trying the change the block von Site.js in Site1.js and it works. i hope its correct what i did.
-now i have snowflakes :slight_smile: :slight_smile: here the result: Home | LSB Laserschweißtechnik Bertschinger
-and now i have to check how can i have more snowflakes. Done - i guess its enough snow :-))

edit:
for all unknown peoples (like me). here the right way:
i have in this block two lines for time for:
{% do assets.addJs(‘theme://js/site.js’, {group:‘bottom’}) %}
{% do assets.addJs(‘theme://js/site1.js’, {group:‘bottom’}) %}

One time it is loading my Site.js.
and in the site1.js there is my snowflake script and it works really good.

Everything i changed on my snowflake script for more, bigger & litte bit faster snowflakes.
Here the script:
////////////////////////////////////////////////////////////////////////
// SnowFlakes-Script (c) 2022, Dominik Scholz / go4u.de Webdesign
////////////////////////////////////////////////////////////////////////

let snowflakes = (function() {

///////////////////////////// configuration ////////////////////////////

const defaultConfig = {
	amount: 400, // amount of flakes
	color: ['#AAAACC', '#DDDDFF', '#CCCCDD', '#F3F3F3', '#F0FFFF'], // random colors
	fontType: ['Arial Black', 'Arial Narrow', 'Times', 'Comic Sans MS'], //	random fonts
	flakeChar: '*', // char used for flake
	speed: .08, // speed of flakes
	size: [18, 32], // minimum/maximum flake font size
	drift: 17, // horizontal drift
};

///////////////////////////// private vars /////////////////////////////

let config = {},
	flakes = [],
	bodyWidth = 0,
	bodyHeight = 0,
	count = 0,
	lastInterval = 0,
	initialized = false,
	running = false;

////////////////////////////// functions ///////////////////////////////

// auto start on document load
function autostart(userConfig)
{
	window.addEventListener('load', function() { start(userConfig); });
}


// start snow
function start(userConfig)
{
	if (running)
		return;

	running = true;
	config = mergeObjects(userConfig || {}, defaultConfig);
	resize();

	// add new flakes
	while (config.amount > flakes.length)
		createFlake(flakes.length);

	// init snowflakes
	if (!initialized)
	{
		initialized = true;
		window.addEventListener('resize', resize);

		let style = document.createElement('style');
		style.innerHTML = '.js-anim-snowflake { user-select: none; position: absolute; left: 0; top: 0; zIndex: 20000; }';
		document.getElementsByTagName('head')[0].appendChild(style);

		lastInterval = time();
		window.requestAnimationFrame(move);
	}
}


// stop snow
function stop()
{
	running = false;

	let i, l = flakes.length;
	for (i = 0; i < l; i++)
		if (flakes[i].y <= config.size[1])
			removeFlake(i);
}


// return running status
function isRunning()
{
	return running;
}


// creates a new snowflake
function createFlake(i)
{
	let el, f, s;
	
	if (!flakes[i])
	{
		// create new dom el
		el = document.createElement('div');
		el.className = 'js-anim-snowflake';
		el.innerHTML = config.flakeChar;
		flakes[i] = {
			el: el,
			x: 0,
			y: 0,
			size: 0,
			count: 0
		};
		document.getElementsByTagName('body')[0].appendChild(el);
	}

	f = flakes[i];

	// create flake object
	f.size = randomIntFromRange(config.size);
	f.x = randomIntFromRange([config.drift + 1, bodyWidth - config.drift - f.size - 3]);
	f.y = -f.size - randomIntFromRange([0, bodyHeight]);
	f.count = randomIntFromRange([0, 10000]);

	// init flake
	s = f.el.style;
	s.transform = 'translate(0, -' + f.size + 'px)';
	s.color = randomItemFromArray(config.color);
	s.family = randomItemFromArray(config.fontType);
	s.fontSize = f.size + 'px';

}


// remove an existing snowflake
function removeFlake(i)
{
	flakes[i].el.parentNode.removeChild(flakes[i].el);
	flakes[i] = null;
}


// move existing flakes
function move()
{
	window.requestAnimationFrame(move);
	
	// calculate movement factor
	let t = time(),
		dif = t - lastInterval,
		l = flakes.length,
		d = dif * config.speed * config.size[1],
		i, flake, x, y;
		
	lastInterval = t;
	count += dif * config.speed / 20;
	
	for (i = 0; i < l; i++)
	{
		if (null === flakes[i])
		{
			if (running)
				createFlake(i);
			else
				continue;
		}

		flake = flakes[i];
		flake.y += d / flake.size;
		
		// restart existing flake
		if (flake.y + flake.size >= bodyHeight)
		{
			if (running)
				createFlake(i);
			else
				removeFlake(i);
			continue;
		}

		x = flake.x + Math.sin(flake.count + count) * config.drift;
		y = flake.y;

		flake.el.style.transform = 'translate(' + Math.floor(x) + 'px, ' + Math.floor(y) + 'px)';
	}
}


// calculate new positions for all flakes
function resize()
{
	// save old width
	let oldWidth = bodyWidth;

	// get new width and height
	bodyWidth = getWindowWidth() - config.size[1];
	bodyHeight = getWindowHeight() - config.size[1];

	// calculate correction ratio
	let ratio = bodyWidth / oldWidth;
		
	// for all flakes
	for (let i = 0, l = flakes.length, flake; i < l; i++)
	{
		flake = flakes[i];
		if (!flake)
			continue;

		// do width correction
		flake.x *= ratio;
		
		// restart existing flake
		if ((flake.y + flake.size) >= bodyHeight)
			createFlake(i);
	}
}


// get window width
function getWindowWidth()
{
	let w = Math.max(self.innerWidth || 0, window.innerWidth || 0);
	
	if (document.documentElement)
		w = Math.max(w, document.documentElement.clientWidth || 0);
	if (document.body)
	{
		w = Math.max(w, document.body.clientWidth || 0);
		w = Math.max(w, document.body.scrollWidth || 0);
		w = Math.max(w, document.body.offsetWidth || 0);
	}
	
	return w;
}


// get window height
function getWindowHeight()
{
	let h = Math.max(self.innerHeight || 0, window.innerHeight || 0);
	
	if (document.documentElement)
		h = Math.max(h, document.documentElement.clientHeight || 0);
	if (document.body)
	{
		h = Math.max(h, document.body.clientHeight || 0);
		h = Math.max(h, document.body.scrollHeight || 0);
		h = Math.max(h, document.body.offsetHeight || 0);
	}
	
	return h;
}


// get current time
function time()
{
	return +new Date();
}


// return a random integer from a given range
function randomIntFromRange(a)
{
	return Math.floor(a[0] + Math.random() * (a[1] - a[0]));
}


// return a random array element
function randomItemFromArray(a)
{
	return a[Math.floor(Math.random() * a.length)];
}


// merge arrays
function mergeObjects(a, b)
{
	let i, c = {};
	for (i in b) { c[i] = b[i]; }
	for (i in a) { c[i] = a[i]; }
	return c;
}


// return public methods
return {
	autostart: autostart,
	start: start,
	stop: stop,
	isRunning: isRunning
}

}());

snowflakes.autostart();

A little christmas story with a happy ending. With your consistently friendly tone you have made the world to a better place. Thumbs up :christmas_tree:

We’ll try to fix your problem, although the answers you’ve provided in the post are not very clear.

1 Copy your snowflakes.js file to the user/themes/quark/js folder.
2. In the /user/themes/quark/templates/partials/base.html.twig file modify add these lines after line 32 (in javascript block, after {% do assets.addJs('theme://js/site.js', {group:'bottom'}) %})

{% if page.home == true %}
{% do assets.addJs('theme://js/snowflakes.js', { group: 'bottom' }) %}
{% endif %}
  1. Save the base.html.twig file, clear the Grav cache and reload again.

Please keep the following in mind in future replies to this post:

  1. Do not attach screenshots, but the code directly in the post.
  2. There are some essential aspects before raising your problem: search this forum for similar solutions and search Grav Help.