Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Improvement of html_group_widget (aka: html_radios)

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Plugins
View previous topic :: View next topic  
Author Message
Sesswanna
Smarty n00b


Joined: 17 Dec 2004
Posts: 4

PostPosted: Fri Dec 17, 2004 8:28 pm    Post subject: Improvement of html_group_widget (aka: html_radios) Reply with quote

I found html_group_widget at http://smarty.incutio.com/?page=html_group_widget and it was exactly what I needed for my current project.

The first problem I ran into was that the first function listed on that page has the same name (smarty_function_html_radios) as a function that comes with Smarty v2.6.6. Because I did not wish to overwrite the existing function, I renamed the function to smarty_function_html_group_widget. I then saved the function to my smarty plugins dir as function.html_group_widget.php.

After this, I set to work testing the functionality of this function. I noticed immediately that it seemed to handle the default selection of radios incorrectly. Upon further testing, I noticed that the function did not do any checking at all for checkboxes. As a result, I peered into the source code to see what was going on.

After much examination, I decided to re-write the section of code in smarty_function_html_field_group_output which handles the selections. I did this because the logic present in the function did absolutely no checking for checkboxes. The function had logic which would loop through the parameter $selected, but only for radio buttons (while the html_group_widget function will throw an error if $selected is an array if the type is radio since radio buttons can only have one selection). By changing a few curly braces around, I was able to have the loop executed if the type is not radio.

After this, I noticed that the entire logic for making selections could be re-written and made more efficient. After some coding, I was able to remove the need for any loop.

Here is the original code:
Code:
if ($type == 'radio')
{
   if($value==$selected)
   {
      $_element .= ' checked="checked"';
   }
   else
   {
      foreach ((array)$selected as $_sval)
      {
         if ($value == $_sval)
         {
            $_element .= ' checked="checked"';
         }
      }
   }
}


And here is the improved code:
Code:
if ( $type == 'radio' || !is_array($selected) )
{
   if ($index==$selected)
   {
      $_element .= ' checked="checked"';
   }
}
else
{

   if($selected[$index] == 1)
   {
      $_element .= ' checked="checked"';
   }
}


The majority of the improvement comes from the fact that I added a new parameter to the smarty_function_html_field_group_output function which passes the index of the current field.
As a result, the function definition is now this:
Code:
function smarty_function_html_field_group_output($type, $name, $value, $output, $index, $selected, $events, $title, $access_key, $tab_order, $withids, $extra, $separator, $position, $withlabels )


In the code now, if $selected is not an array it will be an integer storing the index of the $values array parameter to select. If $selected is an array, it stores a 1 at the corresponding index for each checkbox in $values to be selected, and a 0 otherwise.

In otherwords, if the $values array looks like this:
Quote:
values => Array (3)
0 => Basketballs
1 => Monkey Bars
2 => Laser Beams!

then the $selected array must look like this:
Quote:
selected => Array (3)
0 => 1
1 => 1
2 => 0


This would result in the checkboxes for Basketballs and Monkey Bars to be selected, while Laser Beams! is not.

After these fixes, I added an assign parameter (credit goes to the current html_checkboxes function of smarty). When the assign parameter is specified, the output of the function is saved in the specified variable, instead of being output as HTML (very useful for columnizing data in a table, for instance).

The source code with all my changes for html_group_widget is below:
Code:
<?php

/*

Smarty plugin

--------------------------------------------------------------------------------

File: function.html_group_widget.php
Type: function
Name: html_radios
Version: 1.2
Date: 20041218
Purpose: Prints out a list of radio input types or checkboxes
Input: name (optional) - string default "radio"
values (required) - array
options (optional) - associative array
checked (optional) -
   array for checkbox
   string for radio
separator (optional) - ie <br /> or &
class (optional) - name of the class for the radios.
output (optional) - without this one the buttons don't have names
position (optional) - place the output to the left or right of the radio button. default right side
withlabels (optional) - put a <label> tag around the output with for= attrib the same as the id
   Note: without specifying withlabels, no output is shown beside checkboxes/radios
withids (optional) - put an attribute within the <input type="radio" tag
events (optional) - put specific events codes per option/output, eg add
onclick="doSomething(this)" onchange="doSomethingElse(this)"
as an associative array per the keys in options,
or as an array per the values in values
assign (optional) - assign the output as an array to this variable
Author: Christopher Kvarme <christopher.kvarme@flashjab.com>
Credits: Monte Ohrt <monte@ispi.net>
Modified: [20030928] Bill Wheaton <billwheaton@mindspring.com>
Examples: {html_radios values=$ids output=$names}
{html_radios values=$ids name='box' separator='<br>' output=$names}
{html_radios values=$ids checked=$checked separator='<br>' output=$names}
{html_radios values=$ids checked=$checked separator='<br>' output=$names events=$events}
where $events can be an array if not using 'options' as so :
$events = array(
array(
'onclick'=>"alert('clicked option 0')",
'onblur'=>"alert('went to another place from option 0')"
),
array(
'onclick'=>"alert('clicked option 1')",
'onblur'=>"alert('went to another place from option 1')"
)
);
or if using 'options' an $events associative array with the same keys,
eg 'yes'=>'Yes','no'=>'No' as so:
$events = array(
'yes' => 'array(
'onclick'=>"alert('clicked Yes')",
'onblur'=>"alert('went to another place from Yes')"
),
'no' => array(
'onclick'=>"alert('clicked No')",
'onblur'=>"alert('went to another place from No')"
)
);
Modified: [20040823] Christopher M. Black <developer@devonium.com> website: http://www.devonium.com
Fixed id identifiers and label tags to appropriately generate the HTML
Modified: [20041218] Joshua Morse <jmorse@fuse.net>
Fixed bug with how selection of radio/checkboxes was handled.
Added added an assign parameter (credit goes to the current html_checkboxes function of smarty).
When the assign parameter is specified, the output of the function is saved in the specified variable,
instead of being output as HTML (very useful for columnizing data in a table, for instance).

--------------------------------------------------------------------------------
*/

function smarty_function_html_group_widget($params, &$smarty)
{
   require_once $smarty->_get_plugin_filepath('shared', 'escape_special_chars');
   $name = 'radio';
   $type = 'radio';
   $values = null;
   $options = null;
   $selected = null;
   $separator = '';
   $output = null;
   $events = null;
   $withlabels = false;
   $titles = null;
   $tab_orders = null;
   $access_keys = null;
   $position = true;
   $withids = false;
   $extra = "";
   $class = "";
   $style = "";
   $assign = "";
   $assign_temp = array();
   $type = isset($params['type']) ? (string)$params['type'] : $type; //radio or checkbox

   foreach($params as $_key => $_val)
   {
      switch($_key)
      {
         case 'type': // radio or checkbox? def = 'radio'
         case 'name':
         case 'class':
         case 'separator':
         case 'style':
            $$_key = (string)$_val;
            break;

         case 'withids':
         case 'withlabels':
            /* We need ids for the labels to work */
            $params["withids"] = true;
            $$_key = (bool)$_val;
            break;

         case 'checked':
         case 'selected':
            if((string)$_val != null)
            {
               if ($type == 'radio')
               {
                  if(is_array($_val))
                  {
                     $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
                  }
                  else
                  {
                     $selected = (string)$_val;
                  }
               }
               elseif (is_array($_val))
               {
                  $selected = (array)$_val;
               }
               else
               {
                  $selected = (string)$_val;
               }
            }
            break;

         case 'access_keys':
         case 'tab_orders':
         case 'titles':
         case 'events':
         case 'options':
            $$_key = (array)$_val;
            break;

         case 'values':
         case 'outputs':
         case 'output':
            $$_key = array_values((array)$_val);
            break;

         case 'radios':
            $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
            $options = (array)$_val;
            break;

         case 'assign':
            break;

         default:
            $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars((string)$_val).'"';
            break;

      }
   }

   if ( !isset($options) && !isset($values) )
   {
      return ''; /* raise error here? */
   }

   $_html_result = '';

   if (isset($options) && is_array($options))
   {
      foreach ((array)$options as $_key=>$_val)
      {
         $_events = isset($events[$_key]) ? $events[$_key] : '';
         $_title = isset($titles[$_key]) ? $titles[$_key] : '';
         $_access_key = isset($access_keys[$_key]) ? $access_keys[$_key] : '';
         $_tab_order = isset($tab_orders[$_key]) ? $tab_orders[$_key] : '';

         if(!empty($params['assign'])) {
            $assign_temp[] = smarty_function_html_field_group_output($type, $name, $_key, $_val, $_i, $selected, $_events, $_title, $_access_key, $_tab_order, $withids, $extra, $separator, $position, $withlabels);
         }
         else
         {
            $_html_result .= smarty_function_html_field_group_output($type, $name, $_key, $_val, $_i, $selected, $_events, $_title, $_access_key, $_tab_order, $withids, $extra, $separator, $position, $withlabels);
         }
      }
   }
   else
   {
      foreach ((array)$values as $_i=>$_key)
      {
         $_val = isset($output[$_i]) ? $output[$_i] : '';
         $_events = isset($events[$_i]) ? $events[$_i] : '';
         $_title = isset($titles[$_i]) ? $titles[$_i] : '';
         $_access_key = isset($access_keys[$_i]) ? $access_keys[$_i] : '';
         $_tab_order = isset($tab_orders[$_i]) ? $tab_orders[$_i] : '';

         if(!empty($params['assign'])) {
            $assign_temp[] = smarty_function_html_field_group_output($type, $name, $_key, $_val, $_i, $selected, $_events, $_title, $_access_key, $_tab_order, $withids, $extra, $separator, $position, $withlabels);
         }
         else
         {
            $_html_result .= smarty_function_html_field_group_output($type, $name, $_key, $_val, $_i, $selected, $_events, $_title, $_access_key, $_tab_order, $withids, $extra, $separator, $position, $withlabels);
         }
      }
   }

   if(!empty($params['assign'])) {
      $smarty->assign($params['assign'], $assign_temp);
   }
   else
   {
      return $_html_result;
   }

}

function smarty_function_html_field_group_output($type, $name, $value, $output, $index, $selected, $events, $title, $access_key, $tab_order, $withids, $extra, $separator, $position, $withlabels )
{
   // probably should put something for accessKey too... naugh
   if ($withlabels)
   {
      $_output = "<label for=\"label" . smarty_function_escape_special_chars($name) . $value . "\"";

      if($access_key)
      {
         $_output .= ' accesskey="' . smarty_function_escape_special_chars($access_key) . '"';
      }

      if($tab_order)
      {
         $_output .= ' taborder="' . smarty_function_escape_special_chars($tab_order) . '"';
      }

      if($title)
      {
         $_output .= " title=\"" . smarty_function_escape_special_chars($title) . "\"";
      }

      $_output .= ">" . $output . "</label>";
   }

   $_element = '<input type="'.$type.'" name="'
   . smarty_function_escape_special_chars($name) . '" value="'
   . smarty_function_escape_special_chars($value) . '"';

   if ( isset($selected) )
   {
      if ( $type == 'radio' || !is_array($selected) )
      {
         if ($index==$selected)
         {
            $_element .= ' checked="checked"';
         }
      }
      else
      {

         if($selected[$index] == 1)
         {
            $_element .= ' checked="checked"';
         }
      }
   }

   foreach ((array)$events as $eventname => $eventcode)
   {
      $_element .= " " . $eventname . "=\"". $eventcode . "\"";
   }

   if($title)
   {
      $_element .= ' title="' . smarty_function_escape_special_chars($title) . '"';
   }

   if($withids)
   {
      $_element .= " id=\"label" . smarty_function_escape_special_chars($name) . $value . "\"";
   }

   if($class)
   {
      $_element .= " class=\"" . smarty_function_escape_special_chars($class) . "\"";
   }

   $_element .= " " . $extra . " />";

   if($position)
   {
      $_element .= $_output . $separator . "\n";
   }
   else
   {
      $_element = $_output . $_element . $separator . "\n";
   }

   return $_element;
}
?>


Last edited by Sesswanna on Sun Dec 19, 2004 12:12 am; edited 1 time in total
Back to top
View user's profile Send private message
Sesswanna
Smarty n00b


Joined: 17 Dec 2004
Posts: 4

PostPosted: Sun Dec 19, 2004 12:04 am    Post subject: Columnizing html_group_widget output ( radios / checkboxes ) Reply with quote

I have used the changes I have made to html_group_widget to columnize radio buttons or checkboxes I dynamically generate from a database.

Very much thanks to mohrt for writing his split_array plugin.

As an example of the usage, I have this array in Smarty:
Quote:
answers => Array (3)
values => Array (3)
0 => Red
1 => Yellow
2 => Pinkish Orange
outputs => Array (3)
0 => Red
1 => Yellow
2 => Pinkish Orange
checked => Array (3)
0 => 1
1 => 0
2 => 1


I then use the following template code to columnize the data:
Code:
{html_group_widget assign=html_group name=thefield values=$answers.values type=checkbox selected=$answers.checked separator='<br />' output=$answers.outputs withlabels=true}
<table border="0" cellspacing="0" cellpadding="0">
{split_array var=$html_group num=2 assign=group_cols}
   <tr>
      {section name=outer loop=$group_cols}
         <td valign="top">
            {section name=inner loop=$group_cols[outer]}
               {$group_cols[outer][inner]}
            {/section}
         </td>
      {/section}
   </tr>
</table>


The result of which is the following HTML:
Code:
<table border="0" cellspacing="0" cellpadding="0">
   <tr>
      <td valign="top">
         <input type="checkbox" name="field_4[]" value="Red" checked="checked" 0=""  /><label for="labelfield_4[]Red">Red</label><br />   
         <input type="checkbox" name="field_4[]" value="Yellow" 0=""  /><label for="labelfield_4[]Yellow">Yellow</label><br />
      </td>
      <td valign="top">
         <input type="checkbox" name="field_4[]" value="Pinkish Orange" checked="checked" 0=""  /><label for="labelfield_4[]Pinkish Orange">Pinkish Orange</label><br />
      </td>
   </tr>
</table>
Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Plugins All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP