Hugo

Creating a unique id for repeated custom shortcode

Hi all,

I have created a custom shortcode to display audio with a waveform using wavesurfer.js. Inefficiencies aside from including the javascript everytime I call the shortcode how can I create a unique identifier for each repeated use of the shortcode in my Markdown?

Shortcode

<script src="https://unpkg.com/wavesurfer.js"></script>
<div id="waveform">
    <script type="text/javascript">
        
        var wavesurfer = WaveSurfer.create({
            container: document.querySelector('#waveform'),
            barWidth: 2,
            barHeight: 1, // the height of the wave
            barGap: null // the optional spacing between bars of the wave, if not provided will be calculated in legacy format
        });

        wavesurfer.load("/{{ index .Params 0 }}");
    </script>
    <button class="btn btn-primary" data-action="play" onclick="wavesurfer.playPause()">Play / Pause</button>
</div>

The div and variable WaveSurfer.create is assigned to need to be unique as what happens now is the button that is created with each call of the shortcode end up only working on the audio file which is downloaded and rendered first. I also need to be able to reference those randomly assigned variables to the onclick field of the button too.

Ideally I’d have a random hash, or some incremental knowledge of how many shortcodes are in the file.

Any advice here?

One way ist to use Scratch

Use an int value and every use will increment it. Build an id with this value.

Or you can create a hash value from the name of the mp3 file and use this

Excellent, thanks @ju52 ju52 - ill let you know how this goes.

Another way is to take an md5 checksum of whatever field makes each copy of the shortcode unique. For instance, I implemented a view/hide toggle on a bootstrap-based site by checksumming the text to be hidden:

{{ $id := substr (md5 .Inner) 0 16 }}
{{ $label := (.Get 0 | default "view/hide") }}
<p><a role="button" class="btn btn-success btn-sm" data-toggle="collapse" href="#collapse{{$id}}" aria-expanded="false" aria-controls="collapse">{{$label}}</a></p>
<div class="collapse" id="collapse{{$id}}">{{ .Inner | emojify }}</div>

-j

1 Like

This is a great solution! Works for me (but only once). Now I only get one rendering of the waveform shortcode. Code below.

{{ $unique_id := substr (md5 .Inner) 0 16 }}
{{ $unique_id }}

<div id="{{$unique_id}}">
    <script type="text/javascript">
        
        var $unique_id = WaveSurfer.create({
            container: document.querySelector("#{{$unique_id}}"),
            barWidth: 1,
            barHeight: 1, // the height of the wave
            
        });

        $unique_id.load("/{{ index .Params 0 }}");
    </script>
    <button class="btn btn-primary" data-action="play" onclick="$unique_id.playPause()">Play | Pause</button>
</div>

Code for full site:

Looking at the source code, its because $unique_id doesn’t actually assign anything. Is there a way that I can use $unique_id inside Javascript?

You may find the .Ordinal useful.

1 Like

Okay so I have a good grasp now on using .Scratch but the largest issue now is I cannot template javascript. Following the advice on changing my mediaType config so that javascript is rendered with variables I can am a step closer, however, using {{$unique_id}} makes something like:

var {{$unique_id}} = WaveSurfer.create()

become:

var "3198392817d" = WaveSurfer.create()

but I want:

var 3198392817d = WaveSurfer.create()

Any tips?

{{ print $unique_id }}

More about print tells the golang doc
https://golang.org/pkg/fmt/

I’m not sure this is the solution I want.

Changing my shortcode to this:

{{ $unique_id := substr (md5 .Inner) 0 16 }}

<div id="{{$unique_id}}">
    <script type="text/javascript">
        var {{ print $unique_id }} = WaveSurfer.create({
            container: document.querySelector('#{{$unique_id}}'),
            barWidth: 1,
            barHeight: 1, // the height of the wave
            barGap: null
        });

        {{ print $unique_id }}.load("/audio/{{ index .Params 0 }}");
    </script>
    <button class="btn btn-primary" data-action="play" onclick="{{ print $unique_id }}.playPause()">Play | Pause</button>
</div>

Renders the HTML like so:

<div id="fd2b8ec6d0672f70">
    <script type="text/javascript">
        var "fd2b8ec6d0672f70" = WaveSurfer.create({
            container: document.querySelector('#fd2b8ec6d0672f70'),
            barWidth: 1,
            barHeight: 1, 
            barGap: null
        });

        "fd2b8ec6d0672f70".load("/audio/testin.wav");
    </script>
    <button class="btn btn-primary" data-action="play" onclick="&#34;fd2b8ec6d0672f70&#34;.playPause()">Play | Pause</button>
</div>

Which throws the error:

Unexpected string literal "fd2b8ec6d0672f70". Expected a parameter pattern or a ')' in parameter list

Again, most of this looks right except for the js variables!

Thanks for your patience @ju52

With my understanding of programming languages, the var is only valid inside of the script. There is NO need to replace it!

Right! So I can just use x for all the stuff inside the tags? I think the problem I’m getting then is as you can see there is some nonsense in the string in the but apart from that it should work if the variables are scoped correctly.

can not test it now :frowning:

{{ print “%s” $unique_id }} should do it better.
or do {{ print “var%s” $unique_id }} to get a name starting with letters

I’m going to reframe this question in a new post as I think the goal posts have moved significantly!