Categories > TinyButStrong general >

Order of processing onload/onshow with nested absolute blocks

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs
By: Rudy
Date: 2009-12-01
Time: 10:05

Order of processing onload/onshow with nested absolute blocks

Hi Skrol29,

thank you for the great new 3.5 release.

I have a question regarding the order of processing onload/onshow-blocks. How exactly does TBS this internally?

The point is, I lately had a _really long_ list with parentgrp and many conditionals. Performance was poor with the list becoming bigger and bigger, at last it took nearly 60 seconds to show up. After many tries I found it was the onshow (you mentioned that somewhere in a post), and that because I clearly missunderstood all the years how TBS processes this blocks.

The example is too complicated to post as is, but the point are constructs like this:
HTML:
[onshow;block=begin;when [data.printresult]=1]
  [onshow;block=begin;when [data.outertype]=1]
    <p>data.outertype is 1.</p>
    [onshow;block=begin;when [overview.manualmodulestype]=0]
      <p>Some data to show when data.outertype=1 and data.innertype=0.</p>
    [onshow;block=end]
    [onshow;block=begin;when [overview.manualmodulestype]=1]
      <p>Some data to show when data.outertype=1 and data.innertype=1.</p>
    [onshow;block=end]
  [onshow;block=end]

  [onshow;block=begin;when [data.outertype]=0]
    <p>data.outertype is 0.</p>
    [onshow;block=begin;when [overview.manualmodulestype]=0]
      <p>Some data to show when data.outertype=0 and data.innertype=0.</p>
    [onshow;block=end]
    [onshow;block=begin;when [overview.manualmodulestype]=1]
      <p>Some data to show when data.outertype=0 and data.innertype=1.</p>
    [onshow;block=end]
  [onshow;block=end]
[onshow;block=end]

I used absolute block definition.

Assume a data row being
$data[0] = array('printresult'=>0, 'outertype'=>1, 'innertype'=>0);

Now I would have expected TBS to process it in this way:

1. Step : clear all data in outermost surrounding block ([onshow;block=begin;when [data.printresult]=1])
2. Step : do nothing, since there's no more blocks

But it seems TBS works differently. It also considers the inner blocks and processes them, even if there are only more absolute blocks inside and nothing there which could overlap. This had a really huge performance impact on the script.

I solved it with an ondata-function and magnet to obtain the expected behavior:
PHP:
$data[0] = array('printresult'=>NULL, 'outertype'=>1, 'innertype'=>0);
HTML:
<!-- [data.printresult;magnet=_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_] -->
  [onshow;block=begin;when [data.outertype]=1]
    <p>data.outertype is 1.</p>
    [onshow;block=begin;when [overview.manualmodulestype]=0]
      <p>Some data to show when data.outertype=1 and data.innertype=0.</p>
    [onshow;block=end]
    [onshow;block=begin;when [overview.manualmodulestype]=1]
      <p>Some data to show when data.outertype=1 and data.innertype=1.</p>
    [onshow;block=end]
  [onshow;block=end]

  [onshow;block=begin;when [data.outertype]=0]
    <p>data.outertype is 0.</p>
    [onshow;block=begin;when [overview.manualmodulestype]=0]
      <p>Some data to show when data.outertype=0 and data.innertype=0.</p>
    [onshow;block=end]
    [onshow;block=begin;when [overview.manualmodulestype]=1]
      <p>Some data to show when data.outertype=0 and data.innertype=1.</p>
    [onshow;block=end]
  [onshow;block=end]
This way the blocks are already cleared during the merging process before onshow and performance clearly now is better (from 60s to 13s).

Can you please explain how TBS works while processing the onshow? Are there better ways to accomplish the desired behaviour?

Thank you.
Rudy
By: Rudy
Date: 2009-12-01
Time: 10:31

Re: Order of processing onload/onshow with nested absolute blocks

Sorry there's an error in the example, consider overview.manualmodulestype being data.innertype.
By: Skrol29
Date: 2009-12-01
Time: 11:08

Re: Order of processing onload/onshow with nested absolute blocks

Hi Rudy,

TBS does process the [onshow] blocks as you expect, which is the logical way.

TBS searches for the next [onshow] block. When it founds one, it displays or delete the content, including any TBS tags. Then it searches for next [onshow] block.

If you haven't the result you expect it is maybe because your [overview] and [data] fields are not yet merged when method Show() is called. You can check this by changing your code like this:
//$TBS->Show();
echo $TBS->Source; exit;
This prevent TBS from merging [onshow] tags. And so you can check "when" conditions.

You can also have the following test to see that the inner content of an [onshow] block is not precessed when deleted.
Add this snippet in your PHP script before the $TBS->Show():
$x = 0;
function f_test($FieldName,&$Value) {
    global $x;
    $x++;
}
Then add this inside the first [onshow] block:
x here : [onshow.x;onformat=f_test]
And add this after and outside the first [onshow] block:
x there : [onshow.x]

I can give those other details:
Because you are using explicit syntax, TBS will search the end of the first [onshow;block=begin;...] tag just after it. It will met another opening [onshow] tag, and will continue  its search until it has the good end of the first [onshow] tag.
This search is in fact quite fast, but you can see that if the first [onshow] tag was defined relatively to an XML/HTML tag, it could be faster because it wouldn't need to count embedded [onshow] tags.
You can also improve the search by using suffix on the [onshow] tags.
Suffix for automatic TBS tags are explained here:
http://www.tinybutstrong.com/manual.php#html_block_auto
For example :
[onshow_print;block=begin;when [data.printresult]=1]
  [onshow_outer;block=begin;when [data.outertype]=1]
  ...
  [onshow_outer;block=end]
[onshow_print;block=end]

I hope this answers correctly to your question,
By: Rudy
Date: 2009-12-08
Time: 20:20

Re: Order of processing onload/onshow with nested absolute blocks

Hi Skrol29,

Thank you much for this good explanation.

This means the performance increase in my overview-table happened because with magnet I already cleared the onshow-blocks during merge, and so many of conditionals did not have to be checked when $tbs->show() was called, which then processes the entire merged template a second time. It looks a little ugly in the template but does it's job.

Within a table often I can't use an element such as a div or span for enclosure for magnet and have to use the line-syntax _+_+_ ... - for magnet, in this case really a really long one. Do you think this additionally slows the onshow down?

Is there any other, faster and more flexible way to define an "absolute" magnet (from a starttag to an endtag)? The goal is to delete a set of elements during merge without actually writing the value in the template. I solved this within a comment but something like this would be cleaner: (pseudo code follows)

<thead>[data.printresult;magnet=thead;noprint]
  <tr><td></td></tr>[onshow;block=_;when [data.something]=1]
</thead>

[data.printresult;magnet=begin;noprint]
<thead>
  <tr><td></td></tr>[onshow;block=_;when [data.something]=1]
</thead>
[magnet=end]

Did i miss this in the manual or is there really no way to do so?

Thanks again.
Rudy
By: Skrol29
Date: 2009-12-09
Time: 10:06

Re: Order of processing onload/onshow with nested absolute blocks

Hi Rudy,

Parameter "magnet" only works with XML/HTML tags. There is no way to define them on an absolute position. On the other hand, magnet is always more expensive in process than a conditional block.

This should be a bit faster:
[onshow;block=begin;when [data.printresult]!='']
  <thead>
    <tr><td></td></tr>[onshow;block=_;when [data.something]=1]
  </thead>
[onshow;block=begin]

But your big problem is that your "data" block is multiplying conditionals [onshow] block. Then TBS has to find and merge a large number of conditional [onshow] blocks. This can be optimized if you use conditional sections directly on the "data" block. Conditional sections of blocks are faster because they can be cached. But they cannot be hierarchical.
Here is how you could do:
[data;block=begin;when [data.printresult].[data.outertype].[data.innertype]=1.1.0]
  <p>data.outertype is 1.</p>
  <p>Some data to show when data.outertype=1 and data.innertype=0.</p>
[data;block=end]

[data;block=begin;when [data.printresult].[data.outertype].[data.innertype]=1.1.1]
  <p>data.outertype is 1.</p>
  <p>Some data to show when data.outertype=1 and data.innertype=1.</p>
[data;block=end]

[data;block=begin;when [data.printresult].[data.outertype].[data.innertype]=1.0.0]
  <p>data.outertype is 0.</p>
  <p>Some data to show when data.outertype=0 and data.innertype=0.</p>
[data;block=end]

[data;block=begin;when [data.printresult].[data.outertype].[data.innertype]=1.0.1]
  <p>data.outertype is 0.</p>
  <p>Some data to show when data.outertype=0 and data.innertype=1.</p>
[data;block=end]