Subversion Repositories web.active

Rev

Rev 22 | Blame | Compare with Previous | Last modification | View Log | Download

<?php namespace ProcessWire;

/**
 * ProcessWire Radios Inputfield
 * 
 * ProcessWire 3.x, Copyright 2021 by Ryan Cramer
 * https://processwire.com
 * 
 * @property int $optionColumns Number of columns to display radios in, or 0 for vertical stacked, or 1 for inline (default=0)
 * @property string $optionWidth Alternative to optionColumns, specify option width like '222px', '22em', etc. or '1' for auto. 3.0.184+
 * 
 */

class InputfieldRadios extends InputfieldSelect {

  public static function getModuleInfo() {
    return array(
      'title' => __('Radio Buttons', __FILE__), // Module Title
      'summary' => __('Radio buttons for selection of a single item', __FILE__), // Module Summary
      'version' => 106,
      'permanent' => true, 
    );
  }

  public function init() {
    $this->set('optionColumns', 0);
    $this->set('optionWidth', ''); 
    parent::init();
  }

  public function ___render() { 
  
    $sanitizer = $this->wire()->sanitizer;

    $defaults = array(
      'wbr' => false, 
      'noSelectLabels' => true,
    );
    
    $settings = $this->wire()->config->get('InputfieldRadios');
    $settings = is_array($settings) ? array_merge($defaults, $settings) : $defaults;
    
    $this->checkDefaultValue();
    $inline = false;
    $columns = (int) $this->optionColumns;
    if($columns === 1) $inline = true; 
    $options = $this->getOptions();
    $optionWidth = $this->getOptionWidthCSS($this->optionWidth, $options);
    $entityEncodeLabels = $this->getSetting('entityEncodeText') === false ? false : true;
    $liAttr = '';

    if($optionWidth) {
      $liAttr = " style='width:$optionWidth'";
      $out = "<ul class='InputfieldRadiosWidth'>"; 

    } else if($columns) {
      if(count($options) >= $columns && !$inline) {
        $liWidth = round(100 / $columns)-1;  // 1% padding-right added from stylesheet
        $liAttr = " style='width: {$liWidth}%;'";
        $ulClass = 'InputfieldRadiosColumns';
      } else {
        // don't bother setting a width, we will let them float where they want instead
        $ulClass = 'InputfieldRadiosFloated';
      }
      $out = "<ul class='$ulClass pw-clearfix ui-helper-clearfix'>";

    } else {
      $out = "<ul class='InputfieldRadiosStacked'>"; 
    }

    foreach($options as $key => $value) {
      
      $checked = '';

      $id = $sanitizer->name($key); 
      if(!strlen(trim($id, '_'))) $id = trim(base64_encode($key), '=/.');
      $id = $this->id . '_' . $id;
      $attrs = $this->getOptionAttributes($key);
      
      $inputClass = trim($this->attr('class'));
      if(isset($attrs['input.class'])) $inputClass .= ' ' . $attrs['input.class'];
      
      if($this->isOptionSelected($key)) $checked = " checked='checked'";
      $disabled = empty($attrs['disabled']) ? "" : " disabled='disabled'";
      
      unset($attrs['selected'], $attrs['checked'], $attrs['disabled'], $attrs['input.class']); 
      
      $textClass = $settings['noSelectLabels'] ? 'pw-no-select' : '';
      if($disabled) $textClass .= ' ui-state-disabled';
      
      $attrs = $this->getOptionAttributesString($attrs);
      if($attrs) $attrs = ' ' . $attrs;
      
      $label = $settings['wbr'] ? str_replace(' ', ' !wbr!', $value) : $value;
      if($entityEncodeLabels) $label = $this->entityEncode($label, Inputfield::textFormatBasic);
      if($settings['wbr']) $label = str_replace('!wbr!', '<wbr>', $label);

      $inputName = $sanitizer->entities($this->attr('name'));
      $inputValue = $sanitizer->entities($key);
      $inputClass = trim($sanitizer->entities($inputClass));

      $out .= 
        "<li$liAttr><label$attrs>" . 
        "<input$checked$disabled " . 
        "type='radio' " . 
        "name='$inputName' " . 
        "id='$id' " .
        "class='$inputClass' " . 
        "value='$inputValue' />" . 
        "<span class='$textClass'>$label</span>" . 
        "</label></li>";
    }

    $out .= "</ul>";

    return $out; 
  }

  public function set($key, $value) {
    if($key == 'optionColumns') {
      $value = (int) $value;
      if($value < 0) $value = 0;
      if($value > 10) $value = 10;
    }
    return parent::set($key, $value); 
  }
  
  /**
   * Get CSS width and unit for option width
   *
   * @param string|int $optionWidth
   * @param array $options
   * @return string
   *
   */
  public function getOptionWidthCSS($optionWidth, array &$options) {
    if(!$optionWidth) return '';
    /** @var InputfieldCheckboxes $f */
    $f = $this->wire()->modules->getModule('InputfieldCheckboxes', array('noInit' => true));
    return $f->getOptionWidthCSS($optionWidth, $options);
  }

  public function ___getConfigInputfields() {
    $inputfields = parent::___getConfigInputfields(); 
    /** @var InputfieldCheckboxes $module */
    $module = $this->wire()->modules->getModule('InputfieldCheckboxes', array('noInit' => true));
    $fs = $module->___getConfigInputfields();
    foreach(array('optionWidth', 'optionColumns') as $name) {
      $f = $fs->getChildByName($name);
      $f->val($this->getSetting($name));
      if($f->val()) $f->collapsed = Inputfield::collapsedNo;  
      $inputfields->add($f);
    }
    return $inputfields; 
  }

}