(322/365)

The nice thing about is how quickly one can get a site up and running.

The tricky part of it is understanding its directory architecture. This can become more difficult if using a user predefined theme, especially if one wants to one’s custom spin on nonexistent parameters.

(323/365)

One will learn that one will need to copy (usually) the whole file from the themes directory and mirror its directory structure onto the root level.

This can be quite a nuisance if one wants to change just one value.

Show thread

(324/365)

Learning about the directory architecture opened the gates of writing custom partials.

I previous knew of their existence depending on the specific theme and usually could avoid them by injecting custom .

Now that I have been hired to work on a professional site, especially after propagating why to use over , I shall use the framework to its standards and fullest capabilities.

Show thread

(327/365)

To inject custom in , one will either need to activate it in the config

[markup.goldmark.renderer]unsafe = true

or pipe the string with safeHTML.

Show thread

(328/365)

The initial partial that is created is a button for .

This is done by saving a paypal param in the meta data of the article and then injected as an anchor tag onto the button.

The styling of the button is saved in a custom header partial that the theme provides.

Show thread

(329/365)

This approach sounds quite good on paper, but carts don’t work so simplistically.

Although this might sound like a headache initially, in the long run it is quite beneficial.

The paypal cart or form has a couple values which are important.

The main one is the form id. This exists in either case of purchasing an item from a single button or from a dropdown.

In the case of a dropdown selection, then the keys and values of the table cells are important.

Show thread

(330/365)

Now that these factors are known, one gets start building the params’ structure. The easiest is to have a param for the form id and an array of items for the store catalogue.

Each item of the array has a key, a value, and a image.

Further one can setup special params for the other table variables, though from brief comparison over three separate forms, they seem to stay constant.

Show thread

(338/365)

The code from looks like the image with these variables:

  • <PAYPAL_TOKEN> is the main PayPal hook, so it knows how to update the store relative to all further actions taken within the form
  • <PAYPAL_INIT_REFERENCE> usually as on0
  • <PAYPAL_INIT_VALUE> is usually equivalent to <PAYPAL_ITEM_1_VALUE>
  • <PAYPAL_INIT_NAME> is usually equivalent to <PAYPAL_ITEM_1_NAME>
  • <PAYPAL_ITEM_1_NAME> is usually equal to <PAYPAL_ITEM_1_VALUE>
  • <PAYPAL_ITEM_2_NAME> is usually equal to <PAYPAL_ITEM_2_VALUE>
Show thread

(339/365)

Through the abstraction of these variables and using the power of an array in the meta of as , one can create an item like in the image.

The array in this example is called paypalItems and each element has the properties: name, value, image. Further properties of the meta are paypal as the <PAYPAL_TOKEN>, price should align with the price within the cart, paypalHeadName as <PAYPAL_INIT_REFERENCE>
paypalHeadValue as <PAYPAL_INIT_VALUE>.

Of course one could optimize the code somewhat by removing the variables that have INIT_(VALUE|NAME) within them and replacing them by the first item 1_(VALUE|NAME). And replacing <PAYPAL_INIT_REFERENCE> with on0.

Show thread

(340/365)

Now we will create a partial called paypal-button.html within the layouts/partials/ directory. We want to call this partial like

{{ partial "paypal-button" (dict "paypal" .Params.paypal "items" .Params.paypalItems "headName" .Params.paypalHeadName "headValue" .Params.paypalHeadValue) }}

within a list template (either the default or another partial).

Show thread
Follow

(341/365)

The question now is how to build the partial. Since is a static site generator that focuses on using static elements like raw and , one quickly realizes the options to continue further are not many.

One could try to use the CSS option:checked property and other pseudo classes within the <option> HTML tag to turn on and off the various choices within the array. Though this becomes quite difficult to reference items outside of the <option> tag and can make the whole thing an UX nightmare.

(342/365)

First we want to resolve the UX nightmare issue by designing the UI usable.

Let’s go with this arrangement of items:

  • title of item
  • image of item
  • drop-down to choose the item

This means we want to create some kind of callback that updates the prior two components that are dependent on the selection within the drop-down. Thus, we will need to extend with while using .

Show thread

(343/365)

Time to make an overview of what we have so far:

(image Initial)

Since we are already using the callback approach, it would be better to move out everything that is not viable to the form. Thus making the overview more like

(image Reformed)

Show thread

(344/365)

Let’s say we would implement this pseudo code for the subdirectory content/post/store. It would work fine for one product in the subdirectory store.

Now let’s add a second product that also has the same form (339) with different values.

If one would change either drop-down, both would update. The reason is that the callback is only checking for the class change and not for an unique class.

References

Show thread

(345/365)

The next step is to create an unique value. Luckily has a built in command via

{{ $uniqueID := .File.UniqueID }}

which needs to be placed within a range tag meaning within

{{ range .Pages }}

So the whole list.html file would look like the image. We are also passing in the "uniqueID" $uniqueID as the last parameter in the dict for the partial "paypal-button".

Show thread

(348/365)

In 342 the first mention of using a callback function is used without any concrete description of how it shall be built. From the last image one needs to change the partial reference to be saved as a variable which is then piped with safeHTML, so

{{ $itemsOutput := partial "paypal-button" (dict "paypal" .Params.paypal "items" .Params.paypalItems "headName" .Params.paypalHeadName "headValue" .Params.paypalHeadValue "uniqueID" $uniqueID) }}

and the rendering is done via

{{ $itemsOutput | safeHTML }}

Show thread

(349/365)

Further within the partial, since safeHTML will be used one can parse string using and syntax within . As an example

{{ $output := "" }}

{{ $output = print $output "<span>Example</span>" }}

{{ return $output }}

This creates a <span>-tag with the text Example after safeHTML pipe is applied.

Show thread

(351/365)

Now that the exists, it shall be converted into syntax as described in 349. As in the image, some functions are used like printf and other Hugo functions to loop over the variables that are saved as an array type.

Show thread

(352/365)

This code will generate dynamically based off of the length of the paypalItem or .items variable and use the first element of it as the default value (line 9).

Next one will extend the code with more CSS classes to ease the referencing of the JavaScript actions.

Show thread

(353/365)

Looking at the code in the image that will be parsed over using the printf function.

First one creates a change event listener function that is bound to the id of item-select-$uniqueID. The <select>-tag shall be added the id attribute in line 13 (351).

Additionally a custom attribute data-image shall be created and placed on the <option>-tag in line 15 (351). This holds the path to the image value within the paypalItems element.

Outside of the partial the classes selected-value and selected-image need to be defined. They present the respective values from paypalItems element.

In the initial case, lines 10-11 will be called that take the value from the first element in the paypalItems array. Defined from {{ $selectedValue := index .items 0 }} which shall be prepended before the JavaScript code.

Show thread

(354/365)

The whole code of the partial looks like in the image.

A lot of this code can be squashed to save space for the cost of readability.

Show thread

(355/365)

Now that the partial is complete, look back at its parent. Combining the code from 345 and 348 one gets this image.

The problem of this code so far is that it doesn’t check if the $itemsOutput exists. Further there are no checks that the array .Params.paypalItems has any items and there is no default case.

Show thread

(356/365)

Now one shall add the missing checks and default cases. Further one shall add the CSS classes mentioned in 353.

The result is seen in the image.

Show thread
Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.