Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2022-09-22 09:36:45

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,578
Website

Ways of managing txp:yield and nested / successive shortcodes?

When you nest a shortcode/short-tag in another shortcode, the txp:yield values from the parent shortcode get passed through to the child shortcodes. In some situations that’s quite useful and in others it can lead to unwanted interactions.

Consider this example:

say you have a txp::gallery shortcode that iterates over several image IDs and outputs each via a txp::figure shortcode so you can create grouped image layouts (e.g in columns, grids, whatever). The txp::figure shortcode can also be used on its own.
To make it easier for the end user, I’ve used consistent attribute names on both shortcodes, e.g. width="…" and caption="…" plus a few others like aspect-ratio, lightbox, lazy, etc.

It’s nice to be able to set lightbox, aspect-ratio and lazy loading on the containing txp::gallery shortcode and have those picked up automatically by the txp::figure shortcode within. Without that you’d need all manner of if_yield tags to cover all the attribute combinations for the shortcode within. So far so good.

Less good is width and caption: the width and caption should apply to the gallery, not to every image. I don’t want them to pass through to the child txp::figure shortcode because that will output wide images and a caption with every image.

Possible approaches:

  1. Use different attribute names in the parent tag, e.g. gallery_width and gallery_caption. The end users will have to remember that there are different attribute names … which always goes wrong.
  2. Adapt my CSS to override the figure width and hide the caption when used inside a gallery. That’s possible but not great CSS design, and creates lots of tag-nesting permutations to cover in one’s CSS.
  3. Disable txp:yield pass-thru for certain values, or copy/shift to new yield name within the shortcode.
  4. Some other way I’ve not thought of…

For the moment I’ve tried variant 3 with a txp:php block to duplicate a $txp_yield['name'] to another name (in my case caption -> gallery_caption) for using further down in the code, and to unset the $txp_yield values I don’t want to pass-thru (caption and width). It was a bit fiddly but it works.

However… one two problems remained. It seems that a shortcode cleans up the txp:yield values it has used after execution so that further instances of the shortcode on the page can start afresh. That works for all the txp:yield values set in the shortcode but not for one I duplicated to a new name. I had to add another txp:php snipped to clear it at the end of the shortcode.
Problem #2 is that IIRC some user privileges do not permit the execution of txp:php in shortcodes.

My question: is there a better way?

What (I think) I’m really looking for is a way to set …

<txp:yield name="gallery_caption" value='<txp:yield name="caption" />' />

… or clear …

<txp:yield name="width" value="" />
<txp:yield name="caption" value="" />

a yield value in the code (and have any set values automatically cleared at the close of execution). Can that already be done, or could that be added?


TXP Builders – finely-crafted code, design and txp

Offline

#2 2022-09-22 12:07:16

etc
Developer
Registered: 2010-11-11
Posts: 5,028
Website GitHub

Re: Ways of managing txp:yield and nested / successive shortcodes?

To see what happens here, one should keep in mind that $txp_yield['name'] is a stack (array) of successive name attribute values passed to <txp:output_form />. Each form appends its attributes to this stack on enter and removes them on exit:

<txp:output_form form="parent" name="Homer">
    <!-- name is 'Homer' here -->
    <txp:output_form form="child">
        <!-- name is still 'Homer' -->
    </txp:output_form>
    <txp:output_form form="child" name="Bart">
        <!-- name is 'Bart' now -->
    </txp:output_form>
    <!-- name is 'Homer' again -->
</txp:output_form>

So,

  • you shouldn’t modify $txp_yield manually (at least not like this), since you can destroy other forms attributes.
  • <txp::figure width="" /> inside gallery form should work, provided you treat empty <txp:yield name="width" /> appropriately inside figure form.

As for <txp:php /> inside forms called in the article body, it should work in 4.8.8 whatever user level.

Offline

#3 2022-09-22 13:43:53

jakob
Admin
From: Germany
Registered: 2005-01-20
Posts: 4,578
Website

Re: Ways of managing txp:yield and nested / successive shortcodes?

Thank you – that indeed works! I was overthinking things (again!)

So the solution is comparatively simple:

  • in the child shortcode, explicitly reset any yield variables that should not be passed-thru to it.
  • when using if_yield in the child shortcode, explicitly check for <txp:if_yield name="attribute" value="" not>… because using just <txp:if_yield name="attribute">… returns true and produces output.

TXP Builders – finely-crafted code, design and txp

Offline

#4 2022-09-22 14:31:05

etc
Developer
Registered: 2010-11-11
Posts: 5,028
Website GitHub

Re: Ways of managing txp:yield and nested / successive shortcodes?

jakob wrote #333916:

when using if_yield in the child shortcode, explicitly check for <txp:if_yield name="attribute" value="" not>… because using just <txp:if_yield name="attribute">… returns true and produces output.

You can probably shorten it to <txp:if_yield name="attribute" not value>…, though I’m unsure. And since

The txp::figure shortcode can also be used on its own

I guess you should treat the empty attribute case anyway.

Offline

Board footer

Powered by FluxBB