How to make shortcode for random image?

I’d like to use random images (upon reload, probably) and I guess the best way to present this to the content-provider is to have a shortcode with a list of images and eventually options like refresh after a time or upon reload.

The shortcode would probably need to generate the appropriate javascript like in: javascript example for random images

Being quite new to hugo, how do I set this up?

tnx

/Simon

Just to expand on this, I now have a static page (see below) doing more or less what I want. Question is how to add this as shortcode.

I suppose the javascript block should be in static/js/randomimg.js or something and included in the header.html partial.

Then I’d probably need a file in layouts/shortcodes/randomimage.html with some template magic to generate the block inside the body element…

My question is: what would be a good way to pass parameters, I’d like to define image size and name in the parameters, and also provide a list of image filenames. In my mind it would look something like:

{{< randomimage width=300 height=200 name=canvas >}}
img1.jpg
img2.jpg
...
{{< /randomimage >}}

is this possible?
or would it have to be something like:

{{< randomimage width=300 height=200 name=canvas img1.jpg img2.jpg ... >}}

sample static page:

<html>
<head>
<script>
var imgElem;
var imgArr;

//assuming imgElem and imgArr are set:
function displayRndImage () {
        var num = Math.floor(Math.random() * imgArr.length);
        var imgfile =  imgArr[num];
        imgElem.src = imgfile;
        console.log(imgfile);
}

function displayRandomImage (canvas, imgs) {
        var num = Math.floor(Math.random() * imgs.length);
        var imgfile =  imgs [num];
        imgElem = document.getElementById(canvas);
        imgElem.src = imgfile;
        console.log(imgfile);
}

function playRandomImage (canvas, imgs, delay) {
        imgElem = document.getElementById(canvas);
        imgArr = imgs;
        var intervalx = setInterval(displayRndImage , delay );
}       
</script>

</head>
<body>
<img width="300" height="200" src="" id="canvas" />
<script>
        var images = ["nature-040.jpg", "nature-041.jpg", "nature-042.jpg", "nature-043.jpg", "nature-044.jpg", "nature-045.jpg", "nature-046.jpg", "nature-047.jpg", "nature-048.jpg", "nature-049.jpg"];
        displayRandomImage("canvas", images);
        playRandomImage("canvas", images, 2000);
</script>
</body>
</html>

If you want to use the canvas for showing random images on multiple pages it’s a good idea to wrap the HTML template in a shortcode.

Since you use a shortcode I assume you want to show random images in multiple places of your website. Do you always want to use the same set of images for all canvases?

If this is the case you don’t have to pass the paths of the images to the shortcode. Instead you could create a special folder for your random images in the static directory.

In the next step you can create a list of all files in the special folder that we created a moment ago by using the readDir template function. The functions returns a list of filenames that can be assigned to imgArr.

Furthermore, I assume that imgElem is the HTML element that should display the random images.

Hi digitalcraftsman, thanks for your reply!

“canvas” is just the name of the image element, it could be anything.
I like the idea of using a function to fill the array with image filenames.

the markdown content should be able to contain a number of “randomimage” shortcodes with different sets of images. My idea was to either provide them as parameters to the shortcode or (but I don’t know if this is possible) as a plain text list between the starting and end tag…

So far, I’m still struggling to even get a basic testing shortcode to work :sweat: :confused:

The functions and variables (global due to the interval timer) should be included only once, so that should not be in the shortcode template, but in a header partial.

BTW, I’m using it on top of your material-docs theme :smiley: tnx!

It’s not working yet, though not far away…

  1 <!-- start randomimage -->
  2 <img {{ with .Get "width"}}width="{{ . }}"{{end}} {{ with .Get "height" }}height="{{ . }}"{{end}}  src="" {{with .Get "name"}}id="{{ . }}"{{end}} />
  3 <script>
  4         var images = [
  5         {{with .Get "imgdir" }} 
  6                 {{ $files := readDir .  }}
  7                 {{ range $files }}
  8                         {{ .Name |urlize}},
  9                 {{end}}
 10          {{end}}
 11         ];
 12         {{with .Get "name"}}
 13                 displayRandomImage("{{.}}", images);
 14         {{end}}
 15 </script>
 16 <!-- end randomimage -->

This code generates something that looks ok, but the .Name only contains the filename, not the path. So I need a path or something to prepend to that to generate valid urls… How can I do that?

What I currently get is:

<img width="300" height="200"  src="" id="bla" />
<script>
	var images = [
	 
		
		
			"img_8344.jpg",
		
			"img_8350.jpg",
		
			"img_8376.jpg",
		
			"img_8389.jpg",
		
			"img_8399.jpg",
		
			"img_8424.jpg",
		
			"img_8432.jpg",
		
			"img_8437.jpg",
		
			"img_8438.jpg",
		
			"img_8442.jpg",
		
			"img_8464.jpg",
		
			"img_8634.jpg",
		
			"img_8713.jpg",
		
	 
	];
	
		displayRandomImage("bla", images);
	
</script>

the actual url (running hugo locally) of these images are like:
http://localhost:1313/pictures/horizontaal/IMG_8437.jpg

So there’s also a lower-casing thingy going on I see…

I think I’m nearly there, but not quite yet.

Cheers

Simon

I’ve got something working :slightly_smiling:

The fix is a bit ugly, I think, I changed the javascript function to accept baseurl as parameter and I pass this from the shortcode parameter to the javascript function. Also I removed the urlize filter, since that lowercased the name.

<!-- start randomimage -->
<img {{ with .Get "width"}}width="{{ . }}"{{end}} {{ with .Get "height" }}height="{{ . }}"{{end}}  src="" {{with .Get "name"}}id="{{ . }}"{{end}} />
<script>
        var images = [
        {{with .Get "imgdir" }} 
                {{ $files := readDir .  }}
                {{ range $files }}
                        {{ .Name }},
                {{end}}
         {{end}}
        ];
        displayRandomImage("{{ .Get "name"}}", {{ .Get "baseurl" }}, images);
</script>
<!-- end randomimage -->

I’m now using the parameters directly, instead of through a “with” construction. (I’m quite confused about the variable scope in hugo :confounded:)