Bill Farmer

Random thoughts on random subjects

Whatever-o-meter revisited

by Bill Farmer. Categories: Hacking .

I wrote the whatever-o-meter about five years ago in PHP and Javascript as a Wordpress plugin. As I have migrated my blog to Hugo, I thought to have a go at reimplementing it. The exporter I used made a good job of translating the Wordpress custom fields to Hugo front matter parameters. I had to put dashes in quotes, otherwise they get interpreted as [<nil>].

intro: Please answer the following questions carefully and truthfully.
question:
  - You are lying in bed on Monday morning...
result:
  - '%d percent, Perhaps you should consider emigration.'
  - '%d%, Consider taking a long holiday somewhere far away.'
left:
  - Go and jump in the shower quick
right:
  - Jump on him
weights: 2,1,1,1,1
centre:
  - '-'
  - '-'
  - So so
more: https://billthefarmer.github.io/blog/morris-o-meter

The javascript part should just work as it is, the PHP plugin needed re-implementing as a hugo shortcode. The first part of the plugin just outputs svg code to draw the dial and pointer, that was fairly easy to implement, it just has some iteration in it. I had to change the ticks slightly as Hugo doesn’t appear to support floating point arithmetic in templates.

The really difficult part was reading the page parameters, as most of them are optional, and some of the arrays can have bits missing. PHP just coped with that, anything not defined just becomes null. In Hugo I had to make a great deal of use of default and slice to create default values.

{{ with .Page.Params }}
  <div id="first" style="text-align: center">
    <h4>{{ .intro }}</h4>
    <input type="button" value="Start" class="start" id="start" />
  </div>
  {{ $questions := .question }}
  {{ $left_texts := default (slice "No") .left }}
  {{ $centre_texts := default (slice "-") (default .centre .center) }}
  {{ $right_texts := default (slice "Yes") .right }}
  {{ $last_index := sub (len $questions) 1 }}
  {{ range $index, $question := $questions }}
  {{ $left := default "No" (index $left_texts $index) }}
  {{ $centre := default "-" (index $centre_texts $index) }}
  {{ $right := default "Yes" (index $right_texts $index) }}

The other difficult part was extracting optional parameters to pass as json to the javascript. I had to use Scratch inside with blocks to save values. Luckily Scratch.Get returns null if the key doesn’t exist.

{{ with .result }}
{{ $.Scratch.Set "results" . }}
{{ end }}
{{ with (default .colors .colours) }}
{{ $.Scratch.Set "colours" (split . ",") }}
{{ end }}
{{ with .weights }}
{{ $.Scratch.Set "weights" (split . ",") }}
{{ end }}
{{ with .duration }}
{{ $.Scratch.Set "duration" . }}
{{ end }}
{{ with .easing }}
{{ $.Scratch.Set "easing" . }}
{{ end }}
{{ $json := dict "results" ($.Scratch.Get "results") "colours" ($.Scratch.Get "colours")
                 "weights" ($.Scratch.Get "weights") "duration" ($.Scratch.Get "duration")
                 "easing" ($.Scratch.Get "easing") }}
<script type="text/javascript">
  var whatever_data = {{ safeJS (jsonify $json) }};
</script>
{{ end }}

So the generated json looks like this, with nulls for the missing keys.

<script type="text/javascript">
var whatever_data =
  {"colours":null,"duration":null,"easing":null,"results":["%d percent,
    Perhaps you should consider emigration.",...],"weights":["2","1","1","1","1"]};
</script>

The javascript code needed a bit of work to force the weights, which were passed by Hugo as an array of strings, to be interpreted as numbers.

        // Check if weights are defined
        if (weights == null)
        {
            value += $("#value-" + panel).slider("value");
            total++;
        }

        else
        {
            value += $("#value-" + panel).slider("value") *
	        weights[index];
            total += +weights[index];
        }


See Also