<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
<channel>
  <title>TinyButStrong Forum</title>
  <description>TinyButStrong Forum in English</description>
  <link>http://www.tinybutstrong.com/</link>
  <item>
   <title>Speed up block processing with onload instead of onshow</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=13045</link>
   <description>This may be obvious to anyone reading, but it is easy to forget. If you are using blocks and subblocks in your template, it may be considerably longer by the time TBS gets to the onshow event. If you have a block like this:<br />
<br />
&#91;code]<br />
&lt;table&gt;<br />
  &lt;tr&gt;<br />
    &lt;td&gt;&#91;myBlock.fieldName;block=table;]&lt;/td&gt;<br />
    &lt;td&gt;&#91;onshow.totalFields;]&lt;/td&gt;<br />
  &lt;/tr&gt;<br />
&lt;/table&gt;<br />
&#91;/code]<br />
<br />
Where myBlock is a semi-large array or object (meaning you will have several tables at the end) - you can save a lot of processing by simply changing onshow to onload. If you choose an earlier event, you can merge the tag once, when the template loads, instead of once for every item in myBlock. <br />
<br />
I think it would be safe to say whenever possible, you should use the earliest event you can. With that in mind, I am trying to determine the order of tag processing. I believe it goes like this:<br />
<br />
&#91;code]<br />
//assuming:<br />
$TBS-&gt;LoadTemplate(&quot;path/to/template&quot;);<br />
$TBS-&gt;MergeBlock('blockName', $arrayOrObject);<br />
$TBS-&gt;Show();<br />
<br />
1. onload<br />
2. ondata<br />
3. blockName<br />
4. onshow<br />
&#91;/code]<br />
<br />
Though &#91;var] and &#91;val] fields don't fit into this ordering, I will try to explain them. &#91;var] and &#91;val] fields are a little different as they will merge based on the tag they are used with.<br />
<br />
&#91;var] fields will merge at the same time as whatever they are included with and have no understanding of the field you are currently merging (you could not use var.field to access blockName.field - use val for that), e.g. the var in this example will merge when blockName merges:<br />
<br />
&#91;code]<br />
$myGlobal = 'go';<br />
...<br />
&lt;p&gt;<br />
&#91;blockName.field;block=p;when &#91;var.myGlobal]='go']<br />
&lt;/p&gt;<br />
&#91;/code]<br />
<br />
&#91;val] fields are equal to the current data item. For example, you would use:<br />
<br />
&#91;code]<br />
//good<br />
&#91;blockName.field;when &#91;val]='OK']<br />
&#91;/code]<br />
<br />
Instead of:<br />
<br />
&#91;code]<br />
//bad<br />
&#91;blockName.field;when &#91;blockName.field]='OK']<br />
&#91;/code]<br />
<br />
I hope anyone reading will feel free to correct, clarify, or expand on my explanation of this.</description>
   <pubDate>2013-02-14 00:31:00</pubDate>
  </item><item>
   <title>Downsize subtemplate file size to increase speed</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=13024</link>
   <description>I have an application that uses potentially many subtemplates and my processing time was increasing a lot based on how many sub templates I included, despite having relatively little TBS interaction in the subtemplates. I found file size/length to be a real contributor to this delay. Skrol29 helped my put together a quick php script that I run whenever I edit a subtemplate to cut out the unneeded parts and save a smaller version to the cache, while maintaining my WYSIWYG versions in a source folder. <br />
<br />
I did this for OpenTBS with .docx files because they happen to save a lot of extraneous information - I probably would not have noticed a problem with a less junk-filled WYSIWYG system. This version is pretty specific to my use of the drawing canvas and pictures as well as shapes, but the structure could be adapted to cut out whatever extra junk you want. This is also useful if you are using parameter 'getpart' in you file inclusion, if you always include the same &quot;part&quot; and it is much smaller than your overall subtemplate.<br />
<br />
&#91;code]<br />
&lt;?php<br />
include_once('includes/tbs_class.php');<br />
include_once('includes/tbs_plugin_opentbs.php');<br />
$TBS = new clsTinyButStrong;<br />
$TBS-&gt;Plugin(TBS_INSTALL, OPENTBS_PLUGIN);<br />
<br />
$LOC_DOCX = 'templates/docx/';<br />
class subTemplate{<br />
    var $filename = '',<br />
        $docx_path = 'templates/docx/',<br />
        $xml_path = 'templates/xml/',<br />
        $TBS = null;<br />
    function __construct(clsTinyButStrong $TBS, $filename){<br />
        $this-&gt;TBS = $TBS;<br />
        $f = pathinfo($filename);<br />
        $this-&gt;filename = $f&#91;'filename'];<br />
    }<br />
    public function load_document(){<br />
        echo 'Loading document.xml from '.$this-&gt;filename.'.docx... ';<br />
        $this-&gt;TBS-&gt;LoadTemplate($this-&gt;docx_path.$this-&gt;filename.'.docx#word/document.xml');<br />
        return $this;<br />
    }<br />
    public function strip_gfxdata(){<br />
        echo 'Stripping gfxdata... ';<br />
        while ($x = clsTbsXmlLoc::FindStartTagHavingAtt($this-&gt;TBS-&gt;Source, 'o:gfxdata', 0) ) {<br />
            $x-&gt;ReplaceAtt('o:gfxdata', '');<br />
            $this-&gt;TBS-&gt;Source = str_replace(' o:gfxdata=&quot;&quot;', '', $this-&gt;TBS-&gt;Source);<br />
        }<br />
        return $this;<br />
    }<br />
    public function use_only_block($blockName){<br />
        echo 'Stripping to only '.$blockName.'... ';<br />
        $this-&gt;TBS-&gt;Source = $this-&gt;TBS-&gt;getBlockSource($blockName);<br />
        return $this;<br />
    }<br />
    public function save(){<br />
        echo 'Saving &lt;a href=&quot;'.$this-&gt;xml_path.$this-&gt;filename.'.xml&quot;&gt;'.$this-&gt;filename.'.xml&lt;/a&gt;... ';<br />
        $file = fopen($this-&gt;xml_path.$this-&gt;filename.'.xml', 'w');<br />
        fwrite($file, $this-&gt;TBS-&gt;Source);<br />
        fclose($file);<br />
        echo 'Done. &lt;strong&gt;'.number_format(filesize($this-&gt;xml_path.$this-&gt;filename.'.xml')/1024,1).'KB&lt;/strong&gt;&lt;br&gt;';<br />
    }<br />
}<br />
<br />
//get list of all subtemplates<br />
function get_templates($dir){<br />
    $templates = array();<br />
    $files = scandir($dir);<br />
    foreach($files as $file){<br />
        $f = pathinfo($file);<br />
        if($f&#91;'extension'] == 'docx'){<br />
            $templates&#91;] = $file;<br />
        }<br />
    }<br />
    echo &quot;&lt;strong&gt;&quot;.count($templates).' templates to process&lt;/strong&gt;&lt;br&gt;';<br />
    return $templates;<br />
}<br />
//process subtemplates and save them to xml folder for use<br />
function make_templates($templates){<br />
    global $TBS;<br />
    echo &quot;&lt;ol&gt;&quot;;<br />
    foreach($templates as $template){<br />
        $sub = new subTemplate($TBS, $template);<br />
        echo &quot;&lt;li&gt;&quot;;<br />
        $sub-&gt;load_document();<br />
        $sub-&gt;strip_gfxdata();<br />
        $sub-&gt;use_only_block('mcAlt');<br />
        $sub-&gt;save();<br />
        echo &quot;&lt;/li&gt;&quot;;<br />
    }<br />
    echo &quot;&lt;/ol&gt;&quot;;<br />
}<br />
<br />
$templates = get_templates($LOC_DOCX);<br />
make_templates($templates);<br />
<br />
?&gt;<br />
&#91;/code] <br />
<br />
I hope someone finds this useful - it took my execution time from about 15 seconds to 2.</description>
   <pubDate>2013-01-31 19:57:27</pubDate>
  </item><item>
   <title>Block with headergrp having Page Break before except for the first occurence</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=13023</link>
   <description>Hello,<br />
<br />
Let us suppose you have a document that has as its first paragraph a title for the whole document. For example: &quot;PROGRAM FOR 2013&quot;<br />
And then the second paragraph, containing a block with headergroup. For example: &#91;BLK_RES.TRIMESTER;BLOCK=W:P;HEADERGRP=TRIMESTER] TRIMESTER].<br />
The field &quot;trimester&quot; of every record contains &quot;First&quot; or &quot;Second&quot; or &quot;Third&quot; or &quot;Fourth&quot;.<br />
If you want that every new trimester section begin on a new page, you can apply the format &quot;Page Break Before&quot; to the paragraph that contains the trimester.<br />
But the problem is that you will have also the first semester beginning on a new page (page 2), leaving behind the document title as one line alone on the first page.<br />
<br />
How can you prevent this separation of the first occurence of the breaking field trimester from the very beginning of the document.<br />
<br />
The simple solution I found is to:<br />
 1- make sure Word has a different header for the first page;<br />
 2- Move the first paragraph (title of the whole document) in this header, so that my breaking field &quot;trimester&quot; is now in the first paragraph of the main text.<br />
Since Word ignore the &quot;Page Break Before&quot; format for the first paragraph of the main text, your first trimester will not be separated form the document title (in this case: &quot;PROGRAM FOR 2013&quot;.<br />
<br />
I hope this tip can be useful to somebody.</description>
   <pubDate>2013-01-31 13:57:48</pubDate>
  </item><item>
   <title>Clean up proofErr and w:rsid tags in Word documents</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12995</link>
   <description>If you are using Word to make your template, you may have problems periodically with TBS tags not merging due to being broken up by extra blocks of code inserted by Word. This extra code is not noticeable in Word, but sometimes it seems to mangle the TBS tag too much to be recognized. When this happens, you can do two things that will clean up your document.<br />
<br />
1) Select any tags (&#91;onshow;data;noerr;], e.g.) in your document and go to the review tab (I am using Word 2010 here, but 2007 is very similar). Click 'Language' &gt; 'Set Proofing Language' (2010) or 'Set Language' in the 'Proofing' division (2007). Then check the box 'Do not check spelling or grammar'. This will prevent Word from adding those extra proofErr tags (and breaking up your TBS tags). It will also remove any that already exist in your document. (Or you can run spell check and ignore everything)<br />
<br />
2) The w:rsID tags are a little trickier. There is a hidden option you can access through the macro editor (Alt + F11 will bring it up). Once you are in the macro editor, Ctrl + G will open the 'Immediate Window'. If you paste the following code into the Immediate Window:<br />
<br />
&#91;code]<br />
Application.Options.StoreRSIDOnSave = False<br />
&#91;/code]<br />
<br />
And then save your document (you do not need to save the macro with the document, it just applies to your Word session), it will remove all of the extra w:rsid tags breaking up your TBS tags.<br />
<br />
Notes on editing:<br />
You will want to apply these changes at the end of editing, before you save. If you come back later and edit your document, it will forget that you don't want spell checking and grammar. You can remind it by setting the language again, or by running Spell Check and telling it to ignore all of the problems it encounters. I edited my document more after running the macro I mentioned (in a new Word session, when my Immediate Window was clear again) and my w:rsid tags did not come back, but I suspect they would return if I edited enough. <br />
<br />
There is one more potentially problematic tag: <br />
<br />
&#91;code]<br />
&lt;w:bookmarkStart w:id=&quot;0&quot; w:name=&quot;_GoBack&quot;/&gt;<br />
&lt;w:bookmarkEnd w:id=&quot;0&quot;/&gt;<br />
&#91;/code]<br />
<br />
which will insert itself wherever it pleases (from what I understand, it has something to do with moving your screen back to your previous edit if you hit undo, so it attaches itself to the edit before last?). I haven't done much experimenting with this yet, it may not interfere with TBS tags, and I'm not totally sure where it shows up.<br />
<br />
Hope this helps.</description>
   <pubDate>2013-01-18 23:27:39</pubDate>
  </item><item>
   <title>Re: Use a batch file to simplify OpenTBS templating</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12944</link>
   <description>Thanks for sharing this tip.<br />
<br />
By the way, OpenTBS is based on a PHP class that is able to manage ZIP archive un full PHP.<br />
http://www.tinybutstrong.com/tools.php<br />
<br />
This can give ideas to build your batch above in PHP (if have it in PHP may have any utility, which is not sure).</description>
   <pubDate>2013-01-07 10:30:34</pubDate>
  </item><item>
   <title>Re: Adding comments that won't mess up debug formatting</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12930</link>
   <description>Yes, the OpenTBS Debug mode. </description>
   <pubDate>2012-12-28 02:28:08</pubDate>
  </item><item>
   <title>Example of Joomla application: simple search with more preparations</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12278</link>
   <description>Here is the source code and to install procedure for a small Joomla application that works with the TBS plug-in.<br />
<br />
This application present a search area, and the result of the search trough a table in the Joomla database.<br />
But it also:<br />
- checks the TBS version<br />
- allows template which are a full HTML page<br />
- allows one CSS style sheet in the template<br />
- allows additional both GET and POST parameters<br />
<br />
Installation:<br />
-------------<br />
1) create a folder &quot;applications/simple_search&quot; under the Joomla folder.<br />
2) put the following files<br />
3) create a new Joomla article with the following contents: {tbs}script=applications/simple_search/index.php{/tbs}<br />
4) in the TBS plug-in parameters (under Joomla plug-ins), add the article id to the hallowed ids.<br />
<br />
Files:<br />
------<br />
<br />
index.php<br />
&#91;code]<br />
&lt;?php<br />
<br />
/* Simple Search application<br />
   Skrol29, 2012-03-01<br />
*/<br />
<br />
if (!isset($TBS)) exit(&quot;This application can work only under Joomla.&quot;);<br />
<br />
// Check TBS version<br />
if (version_compare($TBS-&gt;Version,'3.6.0')&lt;0) {<br />
	$TBS-&gt;Source = utf8_encode(&quot;This applciation require TinyButStrong Template Engine version 3.6.0 ou higher. The installed version is &quot;.$TBS-&gt;Version.&quot;.&quot;);<br />
	return; // back to Joomla<br />
}<br />
<br />
// Retrieve user parameters<br />
global $what;<br />
$what = isset($_REQUEST&#91;'what']) ? $_REQUEST&#91;'what'] : ''; // text to search<br />
<br />
// Build The URL to the current article<br />
global $art_url;<br />
$art_id = $TBS-&gt;JoomlaArticle-&gt;id;<br />
$art_url = JRoute::_(ContentHelperRoute::getArticleRoute($art_id));<br />
$art_url .= (strpos($art_url,'?')===false) ? '?' : '&amp;'; // ensure compatibility with the Short URL mode of Joomla<br />
<br />
<br />
// Load the template<br />
$TBS-&gt;JoomlaScript = $PrmLst&#91;'script'];<br />
f_load_template($TBS, 'tpl_main.html', 'Simple Search');<br />
<br />
if ($what=='') {<br />
	// nothing to search<br />
	$TBS-&gt;MergeBlock('c', 'clear');<br />
} else {<br />
	$sql = &quot;<br />
	SELECT id, name<br />
	FROM jos_components<br />
	WHERE (name LIKE '%&quot;.str_replace(&quot;'&quot;, &quot;''&quot;, $what).&quot;%')<br />
	ORDER BY id<br />
	&quot;;<br />
	$TBS-&gt;MergeBlock('c', 'mysql', $sql);<br />
}<br />
<br />
/* END : do not use exit() nore TBS-&gt;Show() in order to let Joomla continue the process<br />
*/<br />
return; // go back to Joomla<br />
<br />
// ------------------------------------------------------<br />
// ------------------------------------------------------<br />
<br />
function f_load_template(&amp;$TBS, $modele, $titre='') {<br />
<br />
	if ($titre!=='') $TBS-&gt;JoomlaArticle-&gt;title = utf8_encode($titre);<br />
<br />
	$TBS-&gt;LoadTemplate(dirname(__FILE__).'/'.$modele);<br />
<br />
	// search and delete the &lt;body&gt; element<br />
	$p = strpos($TBS-&gt;Source, '&lt;body');<br />
	if ($p!==false) {<br />
		$p = strpos($TBS-&gt;Source, '&gt;', $p);<br />
		if ($p!==false) $TBS-&gt;Source = substr($TBS-&gt;Source, $p+1);<br />
	}<br />
	$p = strpos($TBS-&gt;Source, '&lt;/body');<br />
	if ($p!==false) $TBS-&gt;Source = substr($TBS-&gt;Source, 0, $p);<br />
	<br />
	// Add the CSS<br />
	$TBS-&gt;Source = '&lt;link rel=&quot;stylesheet&quot; href=&quot;'.dirname($TBS-&gt;JoomlaScript).'/style.css&quot; type=&quot;text/css&quot; /&gt;'.&quot;\r\n&quot;.$TBS-&gt;Source;<br />
	<br />
}<br />
&#91;/code]<br />
<br />
tpl_main.html<br />
&#91;code]<br />
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;<br />
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br />
&lt;head&gt;<br />
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;<br />
&lt;title&gt;Search&lt;/title&gt;<br />
&lt;link href=&quot;style.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;form action=&quot;&#91;onshow.art_url;htmlconv=no]&quot; method=&quot;post&quot;&gt;<br />
  Search for:<br />
    &lt;input type=&quot;text&quot; name=&quot;what&quot; value=&quot;&#91;onshow.what]&quot;/&gt;<br />
    &lt;input type=&quot;submit&quot; name=&quot;btn_ok&quot; value=&quot;OK&quot; /&gt;<br />
&lt;/form&gt;<br />
&lt;p&gt;Result:&lt;/p&gt;<br />
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;4&quot; class=&quot;btable&quot;&gt;<br />
  &lt;tr&gt;<br />
    &lt;th bgcolor=&quot;#999999&quot;&gt;Id&lt;/th&gt;<br />
    &lt;th bgcolor=&quot;#999999&quot;&gt;Name&lt;/th&gt;<br />
  &lt;/tr&gt;<br />
  &lt;tr&gt;<br />
    &lt;td&gt;&#91;c.id;block=tr]&lt;/td&gt;<br />
    &lt;td&gt;&#91;c.name]&lt;/td&gt;<br />
  &lt;/tr&gt;<br />
  &lt;tr class=&quot;nodata&quot;&gt;<br />
    &lt;td colspan=&quot;2&quot;&gt;&#91;c;block=tr;nodata]No item found&lt;/td&gt;<br />
  &lt;/tr&gt;<br />
&lt;/table&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;<br />
<br />
&#91;/code]<br />
<br />
style.css<br />
&#91;code]<br />
.msg-ok {<br />
	color: #060;<br />
}<br />
.msg-err {<br />
	color: #F00;<br />
}<br />
.nodata {<br />
	background-color:#F96;<br />
}<br />
<br />
table.btable {<br />
	width:auto;<br />
}<br />
table.btable td, th {<br />
	padding:2px;<br />
}<br />
table.btable a {<br />
	text-decoration:none;<br />
}<br />
<br />
&#91;/code]<br />
</description>
   <pubDate>2012-03-02 02:41:54</pubDate>
  </item><item>
   <title>Example of Joomla application: very simple search</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12277</link>
   <description>Here is the source code and the install procedure for a very basic Joomla application that works with the TBS plug-in.<br />
<br />
This application present a search area, and the result of the search trough a table in the Joomla database.<br />
<br />
Installation:<br />
-------------<br />
1) create a folder &quot;applications/simple_search&quot; under the Joomla folder.<br />
2) put the following files<br />
3) create a new Joomla article with the following contents: {tbs}script=applications/simple_search/index.php{/tbs}<br />
4) in the TBS plug-in parameters (under Joomla plug-ins), add the article id to the hallowed ids.<br />
<br />
Files:<br />
------<br />
<br />
index.php<br />
&#91;code]<br />
&lt;?php<br />
<br />
/* Simple Search application<br />
   Skrol29, 2012-03-01<br />
*/<br />
<br />
if (!isset($TBS)) exit(&quot;This application can work only under Joomla.&quot;);<br />
<br />
// Retrieve user parameters<br />
global $what;<br />
$what = isset($_POST&#91;'what']) ? $_POST&#91;'what'] : ''; // text to search<br />
<br />
// Load the template<br />
$TBS-&gt;JoomlaArticle-&gt;title = 'Simple Search';<br />
$TBS-&gt;LoadTemplate(dirname(__FILE__).'/tpl_main.html');<br />
<br />
if ($what=='') {<br />
	// nothing to search<br />
	$TBS-&gt;MergeBlock('c', 'clear');<br />
} else {<br />
	$sql = &quot;<br />
	SELECT id, name<br />
	FROM jos_components<br />
	WHERE (name LIKE '%&quot;.str_replace(&quot;'&quot;, &quot;''&quot;, $what).&quot;%')<br />
	ORDER BY id<br />
	&quot;;<br />
	$TBS-&gt;MergeBlock('c', 'mysql', $sql);<br />
}<br />
<br />
/* END : do not use exit() nore TBS-&gt;Show() in order to let Joomla continue the process<br />
*/<br />
return; // go back to Joomla<br />
&#91;/code]<br />
<br />
tpl_main.html<br />
&#91;code]<br />
&lt;form action=&quot;&quot; method=&quot;post&quot;&gt;<br />
  Search for:<br />
    &lt;input type=&quot;text&quot; name=&quot;what&quot; value=&quot;&#91;onshow.what]&quot;/&gt;<br />
    &lt;input type=&quot;submit&quot; name=&quot;btn_ok&quot; value=&quot;OK&quot; /&gt;<br />
&lt;/form&gt;<br />
&lt;p&gt;Result:&lt;/p&gt;<br />
&lt;table border=&quot;1&quot; cellspacing=&quot;0&quot; cellpadding=&quot;4&quot;&gt;<br />
  &lt;tr&gt;<br />
    &lt;th bgcolor=&quot;#999999&quot;&gt;Id&lt;/th&gt;<br />
    &lt;th bgcolor=&quot;#999999&quot;&gt;Name&lt;/th&gt;<br />
  &lt;/tr&gt;<br />
  &lt;tr&gt;<br />
    &lt;td&gt;&#91;c.id;block=tr]&lt;/td&gt;<br />
    &lt;td&gt;&#91;c.name]&lt;/td&gt;<br />
  &lt;/tr&gt;<br />
  &lt;tr class=&quot;nodata&quot;&gt;<br />
    &lt;td colspan=&quot;2&quot;&gt;&#91;c;block=tr;nodata]No item found&lt;/td&gt;<br />
  &lt;/tr&gt;<br />
&lt;/table&gt;<br />
&#91;/code]</description>
   <pubDate>2012-03-02 02:31:43</pubDate>
  </item><item>
   <title>delete colmuns in a Ms Word document</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12243</link>
   <description>Hello,<br />
<br />
Here is a TBS plug-in that enhances OpenTBS and enables you to delete some columns in a table of an Ms Word documents.<br />
<br />
tbs_plugin_delcol.php<br />
&#91;code]<br />
&lt;?php<br />
<br />
/* <br />
<br />
This TBS plug-ins enables you to delete the columns you want in any table of an Ms Word Document.<br />
It is supposed to be used with OpenTBS.<br />
 <br />
Version 1.00<br />
Skrol29, 2011-10-07<br />
 <br />
Installation:<br />
--------------<br />
 <br />
  $TBS = new clsTinyButStrong;<br />
  $TBS-&gt;Plugin(TBS_INSTALL, OPENTBS_PLUGIN);<br />
  $TBS-&gt;Plugin(TBS_INSTALL, DELCOL_PLUGIN);<br />
 <br />
Use:<br />
----<br />
<br />
You have to put a TBS field anywhere inside the table with the following parameters:<br />
The field will be erased and the specified columns will be deleted. <br />
<br />
 * ope=delcol<br />
 * colnum   = the column numbers to delete, separated with commas (first colmun is number 1).<br />
 * colshift = (optional) if parameter &quot;colnum&quot; has only on value then &quot;colshift&quot; extends the number of columns to delete to the left of to the rigth.<br />
   <br />
Both parameters &quot;colnum&quot; and &quot;colshift&quot; can contain  &#91;val] and &#91;var] fields.<br />
   <br />
Examples:<br />
---------<br />
<br />
&#91;onload;ope=delcol;colnum=2,4,6]         =&gt; will delete columns {2,5,6}<br />
&#91;onload;ope=delcol;colnum=2;colshift=2]  =&gt; will delete columns {2,3,4}<br />
&#91;onload;ope=delcol;colnum=2;colshift=-1] =&gt; will delete columns {1,2}<br />
<br />
&#91;onload.col_to_delete;ope=delcol;colnum=&#91;val];colshift=2] =&gt; will delete 3 colmuns staring to column number $col_to_delete<br />
<br />
 <br />
*/<br />
<br />
define('DELCOL_PLUGIN','clsTbsDeleteColumn');<br />
<br />
class clsTbsDeleteColumn {<br />
<br />
  function OnInstall() {<br />
    $this-&gt;Version = '1.00'; // Versions of installed plug-ins can be displayed using &#91;var..tbs_info] since TBS 3.2.0<br />
    return array('OnOperation');<br />
  }<br />
<br />
  function replaceTbsFields($Prm, $Value) {<br />
    $this-&gt;TBS-&gt;meth_Merge_AutoVar($Prm, true);<br />
    $Prm = str_replace($this-&gt;TBS-&gt;_ChrVal, $Value, $Prm);<br />
    return $Prm;<br />
  }<br />
  <br />
  function OnOperation($FieldName,&amp;$Value,&amp;$PrmLst,&amp;$Txt,$PosBeg,$PosEnd,&amp;$Loc) {<br />
<br />
    if ($PrmLst&#91;'ope']!='delcol') return; // activated only if delcol parameter is used<br />
<br />
    if (!isset($PrmLst&#91;'colnum'])) return;<br />
  <br />
    // List of columns converted into an array<br />
    if (is_array($Value)) $Value = implode(',', $Value);<br />
    <br />
    $col_lst = $this-&gt;replaceTbsFields($PrmLst&#91;'colnum'], $Value);<br />
  <br />
    $col_lst = str_replace(' ', '', $col_lst);<br />
    if ( ($col_lst=='') || ($col_lst=='0') ) return false; // nothing to do<br />
    <br />
    $col_lst = explode(',', $col_lst);<br />
    $col_nbr = count($col_lst);<br />
    <br />
    for ($c=0; $c&lt;$col_nbr; $c++) $col_lst&#91;$c] = intval($col_lst&#91;$c]); // Conversion into numeric<br />
  <br />
    // Add column by shifting<br />
    if (isset($PrmLst&#91;'colshift'])) {<br />
      $col_shift = intval($this-&gt;replaceTbsFields($PrmLst&#91;'colshift'], $Value));<br />
      if ($col_shift&lt;&gt;0) {<br />
        $step = ($col_shift&gt;0) ? -1 : +1;<br />
        for ($s = $col_shift; $s&lt;&gt;0; $s = $s + $step) {<br />
          for ($c=0; $c&lt;$col_nbr; $c++) $col_lst&#91;] = $col_lst&#91;$c] + $s;<br />
        }<br />
      }<br />
    }<br />
<br />
    // Delete the TBS field<br />
    $Txt = substr_replace($Txt, '', $PosBeg, $PosEnd - $PosBeg + 1);<br />
<br />
    // Look for the source of the table<br />
    $Loc = clsTbsXmlLoc::findElement($Txt, 'w:tbl', $PosBeg, false);<br />
    <br />
    if ($Loc===false) return false;<br />
    $Src = $Loc-&gt;GetTxt();<br />
<br />
    $this-&gt;deleteElements($Src, 'w:tblGrid', 'w:gridCol', $col_lst);<br />
    $this-&gt;deleteElements($Src, 'w:tr', 'w:tc', $col_lst);<br />
<br />
    $Loc-&gt;ReplaceTxt($Src);<br />
<br />
    return false; // avoid the mergin of the field<br />
    <br />
  }<br />
<br />
  function deleteElements(&amp;$Txt, $ParentTag, $Tag, $ColLst) {<br />
  <br />
    $ColLst = array_unique($ColLst, SORT_NUMERIC); // delete double columns<br />
    sort($ColLst, SORT_NUMERIC); // sort<br />
    $ColMax = $ColLst&#91;(count($ColLst)-1)]; // last column to delete<br />
  <br />
    $ParentPos = 0;<br />
    $TotalDelNbr = 0;<br />
    while ($ParentLoc = clsTbsXmlLoc::findElement($Txt, $ParentTag, $ParentPos, true)) {<br />
      $ParentTxt = $ParentLoc-&gt;GetTxt();<br />
      $ColNum = 0;<br />
      $ColPos = 0;<br />
      $Continue = true;<br />
      $DelNbr = 0;<br />
      while ($Continue &amp;&amp; ($ColLoc = clsTbsXmlLoc::findElement($ParentTxt, $Tag, $ColPos, true)) ) {<br />
        $ColNum++;<br />
        if ($ColNum&gt;$ColMax) {<br />
          // stop the search<br />
          $Continue = false;<br />
        } elseif (array_search($ColNum,$ColLst)===false) {<br />
          // ne deletation<br />
          $ColPos = $ColLoc-&gt;PosEnd + 1;<br />
        } else {<br />
          // deleteation<br />
          $DelNbr++;<br />
          $ColLoc-&gt;ReplaceTxt('');<br />
        }<br />
      }<br />
      if ($DelNbr&gt;0) $ParentLoc-&gt;ReplaceTxt($ParentTxt);<br />
      $TotalDelNbr = $TotalDelNbr + $DelNbr;<br />
      $ParentPos = $ParentLoc-&gt;PosEnd + 1;<br />
    }<br />
<br />
    return $TotalDelNbr;<br />
    <br />
  }<br />
<br />
}<br />
<br />
/* An instance of clsTbsXmlLoc representes a location of an XML element (&lt;tag&gt;...&lt;/tag&gt;) in a TXT contents.<br />
   Attributes are no <br />
*/<br />
class clsTbsXmlLoc {<br />
<br />
  var $PosBeg;<br />
  var $PosEnd;<br />
  var $SelfClosing;<br />
  var $Txt;<br />
<br />
  // crate an instance with the given parameters<br />
  function __construct(&amp;$Txt, $PosBeg, $PosEnd, $SelfClosing = false) {<br />
    $this-&gt;Txt = &amp;$Txt;<br />
    $this-&gt;PosBeg = $PosBeg;<br />
    $this-&gt;PosEnd = $PosEnd;<br />
    $this-&gt;SelfClosing = $SelfClosing;<br />
  }<br />
<br />
  // return the len of the locator<br />
  function GetLen() {<br />
    return $this-&gt;PosEnd - $this-&gt;PosBeg + 1;<br />
  }<br />
  <br />
  // return the source of the locator<br />
  function GetTxt() {<br />
    return substr($this-&gt;Txt, $this-&gt;PosBeg, $this-&gt;GetLen() );<br />
  }<br />
  <br />
  // replace the source of the locator in the TXT contents<br />
  // update the locator's positions<br />
  function ReplaceTxt($new) {<br />
    $len = $this-&gt;GetLen(); // avoid PHP error : Strict Standards: Only variables should be passed by reference<br />
    $this-&gt;Txt = substr_replace($this-&gt;Txt, $new, $this-&gt;PosBeg, $len);<br />
    $this-&gt;PosEnd = $this-&gt;PosEnd + strlen($new) - $len;<br />
  }<br />
<br />
  // search an element in the TXT contents, and return an object if it is found<br />
  static function findElement(&amp;$Txt, $Tag, $PosBeg, $Forward) {<br />
<br />
    $PosBeg = clsTinyButStrong::f_Xml_FindTagStart($Txt, $Tag, true , $PosBeg, $Forward, true);<br />
    if ($PosBeg===false) return false;<br />
    <br />
    $PosEnd = strpos($Txt, '&gt;', $PosBeg);<br />
    if ($PosEnd===false) return false;<br />
    <br />
    $SelfClosing = (substr($Txt, $PosEnd-1, 1)=='/');<br />
    if (!$SelfClosing) {<br />
      $PosEnd = clsTinyButStrong::f_Xml_FindTagStart($Txt, $Tag, false, $PosEnd, true , true);<br />
      if ($PosEnd===false) return false;<br />
      $PosEnd = strpos($Txt, '&gt;', $PosEnd);<br />
      if ($PosEnd===false) return false;<br />
    }<br />
    <br />
    $XmlLoc = new clsTbsXmlLoc($Txt, $PosBeg, $PosEnd, $SelfClosing);<br />
    <br />
    return $XmlLoc;<br />
<br />
  }<br />
  <br />
}<br />
&#91;/code]<br />
</description>
   <pubDate>2012-02-17 00:08:43</pubDate>
  </item><item>
   <title>Re: Writing out &#91;</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=12067</link>
   <description>Hi,<br />
<br />
The answer is here:<br />
http://www.tinybutstrong.com/support.php#faq_protect</description>
   <pubDate>2011-11-17 20:59:29</pubDate>
  </item><item>
   <title>Shorten HTML text and close open tags</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=11936</link>
   <description>Hi,<br />
<br />
I'd like to share what I use to shorten html text with TBS. This format function shortens the text to the &quot;snippet_length&quot; and closes open (allowed) html tags (p, strong, em, blockquote), after operation (something I wish &quot;ope=max:n;maxhtml&quot; would do :)).<br />
<br />
usage: <br />
&#91;code]<br />
&#91;myblock.longhtmldescription;onformat=fmt_html_snippet;snippet_length=200]<br />
&#91;/code]<br />
Also accepts the optional parameters add_if_cut and add_not_cut, both of which can hold text or markup to be added to the shortened (or not shortened) html text. These are not the &quot;...&quot;, those are added by default if needed.<br />
<br />
&#91;code]<br />
  function fmt_html_snippet($fieldname, &amp; $html, &amp; $params) {<br />
    $html = strip_tags(($html), '&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;br&gt;&lt;blockquote&gt;'); //allowed html elements<br />
    $length = isset($params&#91;'snippet_length']) ? (int)$params&#91;'snippet_length'] : 0; //how long should the snippet be<br />
    $add_if_cut = isset($params&#91;'add_if_cut']) ? $params&#91;'add_if_cut'] : ''; //to add if cut (e.g. &quot;(more..)&quot; or a link<br />
    $add_not_cut = isset($params&#91;'add_not_cut']) ? $params&#91;'add_not_cut'] : ''; //to add if text was short enough and has not been cut<br />
    if ($length &gt; 0 &amp;&amp; mb_strlen(strip_tags($html)) &gt; $length) {<br />
      $text_length = $html_length = 0;<br />
      $lt = mb_strpos($html, '&lt;');<br />
      if ($lt !== false) {<br />
        $gt = mb_strpos($html, '&gt;');<br />
        $text_length = $lt;<br />
        $html_length = $gt - $lt + 1;<br />
        while ($gt &gt; $lt &amp;&amp; $lt !== false) {<br />
          $lt = mb_strpos($html, '&lt;', $gt);<br />
          $text_length += $lt - $gt - 1;<br />
          if ($text_length &gt;= $length) {<br />
            break;<br />
          }<br />
          $gt = mb_strpos($html, '&gt;', $lt);<br />
          $html_length += $gt - $lt + 1;<br />
        }<br />
        $charcount = $html_length + $length;<br />
      } else {<br />
        $charcount = $length;<br />
      }<br />
      $html = mb_substr($html, 0, $charcount-1).'...';<br />
      preg_match_all(&quot;#&lt;(&#91;a-z]+)( .*)?(?!/)&gt;#iU&quot;, $html, $result);<br />
      $openedtags= $result&#91;1];<br />
      preg_match_all(&quot;#&lt;/(&#91;a-z]+)&gt;#iU&quot;, $html, $result);<br />
      $closedtags = array_reverse($result&#91;1]);<br />
      foreach($closedtags as $ckey =&gt; $closedtag) {<br />
        foreach($openedtags as $okey =&gt; $openedtag) {<br />
          if ($openedtag == $closedtag) {<br />
            unset($openedtags&#91;$okey]);<br />
            break;<br />
          }<br />
        }<br />
      }<br />
      $openedtags = array_reverse($openedtags);<br />
      foreach($openedtags as $tag) {<br />
        if ($tag != 'br') {<br />
          $html .= '&lt;/'.$tag.'&gt;';<br />
        }<br />
      }<br />
      $html = $html . $add_if_cut;<br />
    } else {<br />
      $html = $html. $add_not_cut;<br />
    }<br />
  }<br />
&#91;/code]<br />
<br />
Hope this is useful to someone.<br />
<br />
Bye<br />
Rudy</description>
   <pubDate>2011-09-11 23:30:57</pubDate>
  </item><item>
   <title>Re: link translation for images in template</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=11716</link>
   <description>Thanks for your tip.<br />
I must say I used a similar way for managing this TBS site that may display some pages in both paths &quot;/&quot; and &quot;/fr/&quot;.</description>
   <pubDate>2011-05-26 00:47:39</pubDate>
  </item><item>
   <title>Cross Tab Report Generator</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=11666</link>
   <description>Here for you, TBS user that would like to know how to create cross-tab report and then combine with Dynamic Columns of our powerfull TBS Templating system ...<br />
<br />
&#91;code]<br />
&lt;?php<br />
/**<br />
 * Yan Friskantoni @ 2011<br />
 * version super alpha 0.01 ;)<br />
 * Generate Cross Tab data of array<br />
 * Example: <br />
 * <br />
 * // $r would be the source of data, you can supplied the data from query like $r = $db-&gt;GetArray('select bar,count(bar) from foo group by bar'); <br />
 * $r = array();<br />
 * $r&#91;]= array('user_code' =&gt; '123456', 'TestName' =&gt; 'Uji Coba', 'TheoryName'=&gt; 'Dasar Komputer', 'AnswerRight' =&gt; 0, 'nQuestions' =&gt; 2 );<br />
 * $r&#91;]= array( 'user_code' =&gt; '123456', 'TestName' =&gt; 'Uji Coba', 'TheoryName'=&gt; 'Bahasa Inggris', 'AnswerRight' =&gt; 0, 'nQuestions' =&gt; 20 );<br />
 * $r&#91;]= array( 'user_code' =&gt; '1234567890', 'TestName' =&gt; 'Uji Coba', 'TheoryName'=&gt; 'Dasar Komputer', 'AnswerRight' =&gt; 5, 'nQuestions' =&gt; 2 );<br />
 * $r&#91;]= array( 'user_code' =&gt; '1234567890', 'TestName' =&gt; 'Uji Coba', 'TheoryName'=&gt; 'Bahasa Inggris', 'AnswerRight' =&gt; 0, 'nQuestions' =&gt; 20 );<br />
 * <br />
 * // call back function<br />
 * $nRightAnswer = 0;<br />
 * function onBeforeRowSaved($drowSrc, &amp;$dcurr_row)<br />
 * {<br />
 *     global $nRightAnswer;<br />
 *     $dcurr_row&#91;'TotalRightAnswer'] = $nRightAnswer; // add new column ...<br />
 *     $nRightAnswer = 0;<br />
 * }<br />
 * // watch for by reference paramaters<br />
 * function afterCTSet($drowSrc, &amp;$dcurr_row, $theField, $theValue)<br />
 * {<br />
 *     global $nRightAnswer;<br />
 *     $nRightAnswer += $theValue;<br />
 *     //echo &quot;AFTER CTSET $nRightAnswer $theField - $theValue&quot;;<br />
 * }<br />
 * <br />
 * $columns = array(); // columns will hold the cross tab column of field that you want to be the source of columns field ...<br />
 * $dt = &amp;generateCrossTab($r, 'TheoryName', 'AnswerRight', &amp; $columns<br />
 *         , array('nQuestions') // skip or hide the field <br />
 *         , array('onBeforeRowSaved' =&gt; 'onBeforeRowSaved', 'afterCTSet' =&gt; 'afterCTSet') // call back function<br />
 *         );<br />
 * // if succed then arrange how our data shown ... see how we combine $columns and the other column<br />
 * $columns = array_merge(array('user_code', 'TestName'), $columns, array('TotalRightAnswer'));<br />
 * // START TEST ... used show source for more idea<br />
 * var_dump($dt, $columns);<br />
 * echo &quot;\n&quot;;<br />
 * foreach($columns as $c)<br />
 * {<br />
 *     printf(&quot;&#91;%26s]&quot;,$c);<br />
 * }<br />
 * echo &quot;\n&quot;;<br />
 * foreach($dt as $i)<br />
 * {<br />
 *     foreach($columns as $c)<br />
 *     {<br />
 *         printf(&quot;&#91;%26s]&quot;,$i&#91;$c]);<br />
 *     }<br />
 *     echo &quot;\n&quot;;<br />
 * }<br />
 * @param type $srcData source of data<br />
 * @param type $ctFieldCol cross tab field<br />
 * @param type $ctFieldValue cross tab value<br />
 * @param type $ctColumns special Columns of CrossTab<br />
 * @param type $fieldToSkip what field to skip when it saved into data?<br />
 * @param type $callbackArray call back function .. see example and code :D to know how to used it ;)<br />
 * @return type arranged data in cross tab<br />
 */<br />
function &amp; generateCrossTab(&amp;$srcData, <br />
            $ctFieldCol, $ctFieldValue, &amp;$ctColumns, $fieldToSkip = null, $callbackArray = null )<br />
    {<br />
        $data = array();<br />
        $the_row = array();<br />
        $startCrossValue = '';<br />
        $isSaveCtColumns = true;<br />
        $ctColumns = array(); // columns of crosstab<br />
        foreach($srcData as $rowSrc)<br />
        {<br />
            if(isset($startCrossValue&#91;0]) &amp;&amp; <br />
                    $startCrossValue != $rowSrc&#91;$ctFieldCol])<br />
            {<br />
                $the_row&#91;$rowSrc&#91;$ctFieldCol]] = $rowSrc&#91;$ctFieldValue]; // add to row, value of ct become field name<br />
                if($isSaveCtColumns) $ctColumns&#91;] = $rowSrc&#91;$ctFieldCol];<br />
                if(isset($callbackArray&#91;'afterCTSet'])) $callbackArray&#91;'afterCTSet']($rowSrc, &amp;$the_row, $rowSrc&#91;$ctFieldCol], $rowSrc&#91;$ctFieldValue]);<br />
            }<br />
            else // a new row has been reached then save to data<br />
            {<br />
                if(!isset($startCrossValue&#91;0]))<br />
                {<br />
                    $startCrossValue = $rowSrc&#91;$ctFieldCol];<br />
                }<br />
                else<br />
                {<br />
                    if(isset($callbackArray&#91;'onBeforeRowSaved'])) $callbackArray&#91;'onBeforeRowSaved']($rowSrc, &amp;$the_row);<br />
                    $data&#91;] = $the_row;<br />
                    $isSaveCtColumns = false;<br />
                }<br />
                $the_row = array();<br />
                $the_row&#91;$rowSrc&#91;$ctFieldCol]] = $rowSrc&#91;$ctFieldValue]; // add to row, value of ct become field name<br />
                if($isSaveCtColumns) $ctColumns&#91;] = $rowSrc&#91;$ctFieldCol];<br />
                if(isset($callbackArray&#91;'afterCTSet'])) $callbackArray&#91;'afterCTSet']($rowSrc, &amp;$the_row, $rowSrc&#91;$ctFieldCol], $rowSrc&#91;$ctFieldValue]);<br />
                // -----------------------<br />
                // save grouped value<br />
                // -----------------------<br />
                // first, dont save crosstab field and value<br />
                $skipper = array($ctFieldCol, $ctFieldValue);<br />
                if(isset($fieldToSkip&#91;0]))<br />
                { // skip field to show?<br />
                    $skipper = array_merge($skipper, $fieldToSkip);<br />
                }<br />
                foreach($rowSrc as $key =&gt; $val)<br />
                {<br />
                    if(array_key_exists($key, $skipper))<br />
                        continue;<br />
                    $the_row&#91;$key] = $val;<br />
                }<br />
            }<br />
        }<br />
        if(count($the_row)&gt;0) // for the last row ...<br />
        {<br />
            if(isset($callbackArray&#91;'onBeforeRowSaved'])) $callbackArray&#91;'onBeforeRowSaved']($rowSrc, &amp;$the_row);<br />
            $data&#91;] = $the_row;<br />
            unset($the_row);<br />
        }<br />
        return $data;<br />
    }<br />
<br />
?&gt;<br />
&#91;/code]</description>
   <pubDate>2011-05-09 05:46:38</pubDate>
  </item><item>
   <title>Re: Conditional Display of HTML Pending Database Field</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=11408</link>
   <description>Ok, found the answer with the addition of the &quot;mtype=m+m&quot; parameter. However, I'm still not sure why the other code would not work. If hyperlink field is not empty, why would the &#91;eventsblock.eventtitle;block=span;when &#91;eventsblock.hyperlink]=''] section even show? Obviously, the &quot;mtype=m+m&quot; is cleaner.<br />
<br />
&#91;code]<br />
&lt;dt&gt;&lt;a href=&quot;&#91;eventsblock.hyperlink;magnet=a;mtype=m+m]&quot;&gt;&#91;eventsblock.eventtitle;block=span;when &#91;eventsblock.#]+-1;bmagnet=div]&lt;/a&gt;&lt;/dt&gt;<br />
&#91;/code]</description>
   <pubDate>2011-02-20 22:44:33</pubDate>
  </item><item>
   <title>Re: Efficient pagination with MySQL 4.0.x and TBS</title>
   <link>http://www.tinybutstrong.com/forum.php?msg_id=11388</link>
   <description>Thank you for your sharing! Chiry!<br />
I found some tutorial about pagination in php  listed on the site  you submit.<br />
It is great helpful for me! <br />
PHPKode is a grant site!</description>
   <pubDate>2011-02-14 07:08:44</pubDate>
  </item>
</channel>
</rss>