Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
4 posts Page 1 of 1
There is nothing quite like helpful as parsing strings with cms:each.

However, for many years CouchCMS had it wrong, outputting k_count starting with '0', which is counter intuitive for end-users. How 'count' can be zero in a non-empty string?
Also, it was always a overly-complicated task to get total number of elements in a separated string, since coders must introduce a new variable etc.., not to mention that total count of elements was not available before the cms:each ends its routine.

Respecting the default behavior( actually, respecting your existing codes with cms:each ) I made a simple tweak that allows to use system variable k_total_count or k_count_total ( 100% identical to make it easy to remember without looking into docs ) inside the cms:each loop on every pass.

If you, just like me, have common sense and like counting to start from '1' then use new parameter startcount and make it startcount='1'( similar to the same existing parameter in cms:repeat ). This way the last k_count and k_total_count will 100% match.

As usual, all codes below go to /couch/addons/kfunctions.php

Code: Select all

$FUNCS->add_event_listener( 'alter_tag_each_execute', array('CustomTags', 'each_with_total') );

class CustomTags{ // ignore this line if you already have this in k_functions.php, and place the following function inside the class.

   // Splits up a string (var) along seprator (sep) returning each value in a loop as item (as)
   function each_with_total( $tag_name, $params, $node, &$html ){
      global $FUNCS, $CTX;
      extract( $FUNCS->get_named_vars(
               array( 'var'=>'',
                     'as'=>'item',
                     'sep'=>'|',
                     'startcount'=>'0'
                    ),
               $params)
            );

      if( !$sep ) $sep = '|';
      if( $sep == '\r\n' ){
         $sep = "\n";
      }
      elseif( $sep == '\r' ){
         $sep = "\r";
      }
      elseif( $sep == '\n' ){
         $sep = "\n";
      }
      elseif( $sep == '\t' ){
         $sep = "\t";
      }
      else{
         $use_preg=1;
      }
      $startcount = is_numeric( $startcount ) ? intval( $startcount ) : 0;

      if( $var ){
         if( $use_preg ){
            $arr_vars = array_map( "trim", preg_split( "/(?<!\\\)\\".$sep."/", $var ) ); // allows escaping of separator with a backslash
         }
         else{
            $arr_vars = array_map( "trim", explode( $sep, $var ) );
         }

      }

      $children = $node->children;
      
      $count = count($arr_vars);
      for( $x=0; $x<$count; $x++ ){
         $CTX->set( 'k_count', $x + $startcount );
            $CTX->set( 'k_count_total', $count );
            $CTX->set( 'k_total_count', $count );
            $CTX->set( 'k_total', $count );
            $CTX->set( 'k_total_records', $count );
            $CTX->set( 'k_step', ( $startcount ) ? $x + $startcount : $x + 1 );
            $CTX->set( 'k_current_record', ( $startcount ) ? $x + $startcount : $x + 1 );
         if( $use_preg ){
            $CTX->set( $as, str_replace( '\\'.$sep, $sep, $arr_vars[$x] ) ); //unescape separator
         }
         else{
            $CTX->set( $as, $arr_vars[$x] );
         }

         foreach( $children as $child ){
            $html .= $child->get_HTML();
         }
      }
      return 1; // prevent the original tag from executing as we have set the output above
   }

}
Code updated.
Inside the cms:each tag now available following variables:
Shows totals:
k_count, k_count_total, k_total_count, k_total, k_total_records
Shows current iteration:
k_step, k_current_record
Hi Trendoman,

cheers for this - it has been very useful.

This was our previous code to attempt to get an equivalent of k_total_records.

Code: Select all
<cms:each keywords sep=','>
   <cms:if k_count = '1'><cms:set max = '1' 'global'/></cms:if>
   <cms:if k_count = '2'><cms:set max = '2' 'global'/></cms:if>
   <cms:if k_count = '3'><cms:set max = '3' 'global'/></cms:if>
   <cms:if k_count = '4'><cms:set max = '3' 'global'/></cms:if>
</cms:each>


but now we can just replace the variable 'max' with k_total_records.

Thanks!
You are welcome :)


A sample code to implode a string with adding comma and space. Now possible the same tactic as in <cms:pages /> with
Code: Select all
<cms:if k_paginated_bottom = '0' >, </cms:if>


Code: Select all
<cms:each keywords sep=',' as='key' >
   <cms:show key /><cms:if k_current record lt k_total_records >, </cms:if>
</cms:each>
4 posts Page 1 of 1

Who is online

In total there is 1 user online :: 0 registered, 0 hidden and 1 guest
(based on users active over the past 5 minutes)

Users browsing this forum: No registered users and 1 guest