mirror of
https://github.com/processwire/processwire.git
synced 2025-08-18 12:31:17 +02:00
Upgrade InputfieldRadios and InputfieldCheckboxes to support a 'optionWidth' configuration property per processwire/processwire-issues#1327
This commit is contained in:
@@ -49,6 +49,13 @@
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
|
||||
.Inputfields .InputfieldCheckboxesWidth li {
|
||||
display: inline-block;
|
||||
}
|
||||
.Inputfields .InputfieldCheckboxesWidth li label {
|
||||
white-space: initial;
|
||||
}
|
||||
|
||||
.InputfieldCheckboxes table label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
@@ -1,11 +1,15 @@
|
||||
<?php namespace ProcessWire;
|
||||
|
||||
/**
|
||||
* Class InputfieldCheckboxes
|
||||
* ProcessWire Checkboxes Inputfield
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property bool $table Whether or not to display as a table
|
||||
* @property string $thead Pipe "|" separated list of table headings. Do the same for the addOption() labels.
|
||||
* @property int|bool $optionColumns Specify 1 for inline list of options, or qty of columns to list options in.
|
||||
* @property string $optionWidth Alternative to optionColumns, specify option width like '222px', '22em', etc. or '1' for auto. 3.0.184+
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -15,20 +19,33 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
return array(
|
||||
'title' => __('Checkboxes', __FILE__), // Module Title
|
||||
'summary' => __('Multiple checkbox toggles', __FILE__), // Module Summary
|
||||
'version' => 107,
|
||||
'version' => 108,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
$this->set('table', false);
|
||||
$this->set('thead', '');
|
||||
$this->set('optionColumns', 0);
|
||||
$this->set('optionWidth', '');
|
||||
parent::init();
|
||||
$this->set('size', null); // cancel 'size' attribute used by select multiple
|
||||
}
|
||||
|
||||
/**
|
||||
* Render
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___render() {
|
||||
|
||||
$sanitizer = $this->wire()->sanitizer;
|
||||
|
||||
$this->checkDefaultValue();
|
||||
$out = '';
|
||||
@@ -37,16 +54,22 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
$inline = $columns === 1 || $columns > 10;
|
||||
$liAttr = '';
|
||||
$ulClass = '';
|
||||
$inputClass = $this->wire('sanitizer')->entities($this->attr('class'));
|
||||
$inputClass = $sanitizer->entities($this->attr('class'));
|
||||
$entityEncode = $this->getSetting('entityEncodeText') === false ? false : true;
|
||||
|
||||
$options = $this->getOptions();
|
||||
$optionWidth = $this->optionWidth ? $this->getOptionWidthCSS($this->optionWidth, $options) : '';
|
||||
|
||||
if($this->table) {
|
||||
/** @var MarkupAdminDataTable $table */
|
||||
$table = $this->modules->get("MarkupAdminDataTable");
|
||||
$table = $this->modules->get("MarkupAdminDataTable");
|
||||
$table->setEncodeEntities(false);
|
||||
$table->setSortable(false);
|
||||
$table->addClass('pw-no-select');
|
||||
if($this->thead) $table->headerRow(explode('|', htmlspecialchars($this->thead, ENT_QUOTES, 'UTF-8')));
|
||||
if($this->thead) $table->headerRow(explode('|', htmlspecialchars($this->thead, ENT_QUOTES, 'UTF-8')));
|
||||
|
||||
} else if($optionWidth) {
|
||||
$liAttr = " style='width:$optionWidth'";
|
||||
$ulClass = 'InputfieldCheckboxesWidth';
|
||||
|
||||
} else if($columns) {
|
||||
|
||||
@@ -67,12 +90,12 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
|
||||
if(!$table) $out = "<ul class='$ulClass'>";
|
||||
|
||||
foreach($this->getOptions() as $key => $value) {
|
||||
foreach($options as $key => $value) {
|
||||
$checked = '';
|
||||
|
||||
if($this->isOptionSelected($key)) $checked = " checked='checked'";
|
||||
|
||||
$id = $this->wire()->sanitizer->name($key);
|
||||
$id = $sanitizer->name($key);
|
||||
if(!strlen(trim($id, '_'))) $id = trim(base64_encode($key), '=/.');
|
||||
$id = $this->id . '_' . $id;
|
||||
|
||||
@@ -98,7 +121,6 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
$value[0] = "$input<span class='pw-no-select'>$value[0]</span></label>";
|
||||
$table->row($value);
|
||||
} else {
|
||||
//$value = str_replace(' ', ' <wbr>', $value);
|
||||
$out .= "<li$liAttr>$input<span class='pw-no-select'>$value</span></label></li>";
|
||||
}
|
||||
|
||||
@@ -111,6 +133,36 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 '';
|
||||
if(!preg_match('/^(\d+)\s*([a-z]{1,4}|%|);?$/i', $optionWidth, $matches)) return '';
|
||||
$unit = empty($matches[2]) ? 'px' : $matches[2];
|
||||
$optionWidth = $matches[1] . $unit;
|
||||
if($optionWidth === '1px') { // 1 or 1px means "calculate at runtime"
|
||||
$optionWidth = 10;
|
||||
foreach($options as $label) {
|
||||
if(strlen($label) > $optionWidth) $optionWidth = strlen($label);
|
||||
}
|
||||
if($optionWidth > 20) {
|
||||
// use without adjustment
|
||||
} else if($optionWidth > 10) {
|
||||
$optionWidth += 2;
|
||||
} else {
|
||||
$optionWidth = 10; // minimum option width
|
||||
}
|
||||
$optionWidth .= 'ch';
|
||||
}
|
||||
return $optionWidth;
|
||||
}
|
||||
|
||||
public function set($key, $value) {
|
||||
if($key == 'optionColumns') {
|
||||
$value = (int) $value;
|
||||
@@ -121,14 +173,34 @@ class InputfieldCheckboxes extends InputfieldSelectMultiple implements Inputfiel
|
||||
}
|
||||
|
||||
public function ___getConfigInputfields() {
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
$modules = $this->wire()->modules;
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
|
||||
/** @var InputfieldInteger $f */
|
||||
$f = $this->wire('modules')->get('InputfieldInteger');
|
||||
$f->label = $this->_('Columns of Checkboxes');
|
||||
$f->description = $this->_('If you want the checkboxes to display in columns (rather than stacked), enter the number of columns you want to use (up to 10). To display checkboxes side-by-side (inline) enter 1.');
|
||||
$f = $modules->get('InputfieldText');
|
||||
$f->label = $this->_('Option column width');
|
||||
$f->description =
|
||||
$this->_('Use this setting to have options display in fixed width columns that float or collapse according to viewport width.') . ' ' .
|
||||
$this->_('Enter a CSS width number and unit such as `100px` or `10em`, for example. If no unit is specified, `px` (pixels) is assumed.') . ' ' .
|
||||
$this->_('Enter the number `1` to automatically calculate an appropriate width at runtime.');
|
||||
$f->notes = $this->_('For best appearance, enter a width that can fit the longest option without word wrapping, or enter `1` to for auto width.');
|
||||
$f->attr('name', 'optionWidth');
|
||||
$f->attr('value', $this->optionWidth);
|
||||
if(!$this->optionWidth) $f->collapsed = Inputfield::collapsedYes;
|
||||
$inputfields->add($f);
|
||||
|
||||
/** @var InputfieldInteger $f */
|
||||
$f = $modules->get('InputfieldInteger');
|
||||
$f->label = $this->_('Option column quantity');
|
||||
$f->description =
|
||||
$this->_('If you want the options to display in columns, enter the number of columns you want to use (up to 10).') . ' ' .
|
||||
$this->_('To display options inline side-by-side enter the number `1`.');
|
||||
$f->notes = $this->_('Note that the “option column width” setting is preferable for responsive behavior.');
|
||||
$f->attr('name', 'optionColumns');
|
||||
$f->attr('value', (int) $this->optionColumns);
|
||||
$inputfields->add($f);
|
||||
if(!$this->optionColumns) $f->collapsed = Inputfield::collapsedYes;
|
||||
$inputfields->add($f);
|
||||
|
||||
return $inputfields;
|
||||
}
|
||||
|
||||
|
@@ -39,3 +39,8 @@
|
||||
padding-bottom: 1%;
|
||||
}
|
||||
|
||||
.Inputfields .InputfieldRadiosWidth li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -3,10 +3,11 @@
|
||||
/**
|
||||
* ProcessWire Radios Inputfield
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* 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+
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -16,26 +17,27 @@ class InputfieldRadios extends InputfieldSelect {
|
||||
return array(
|
||||
'title' => __('Radio Buttons', __FILE__), // Module Title
|
||||
'summary' => __('Radio buttons for selection of a single item', __FILE__), // Module Summary
|
||||
'version' => 105,
|
||||
'version' => 106,
|
||||
'permanent' => true,
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
public function init() {
|
||||
$this->set('optionColumns', 0);
|
||||
$this->set('optionColumns', 0);
|
||||
$this->set('optionWidth', '');
|
||||
parent::init();
|
||||
}
|
||||
|
||||
public function ___render() {
|
||||
|
||||
/** @var Sanitizer $sanitizer */
|
||||
$sanitizer = $this->wire('sanitizer');
|
||||
$sanitizer = $this->wire()->sanitizer;
|
||||
|
||||
$defaults = array(
|
||||
'wbr' => true,
|
||||
'noSelectLabels' => true,
|
||||
);
|
||||
$settings = $this->wire('config')->get('InputfieldRadios');
|
||||
|
||||
$settings = $this->wire()->config->get('InputfieldRadios');
|
||||
$settings = is_array($settings) ? array_merge($defaults, $settings) : $defaults;
|
||||
|
||||
$this->checkDefaultValue();
|
||||
@@ -43,9 +45,14 @@ class InputfieldRadios extends InputfieldSelect {
|
||||
$columns = (int) $this->optionColumns;
|
||||
if($columns === 1) $inline = true;
|
||||
$options = $this->getOptions();
|
||||
$optionWidth = $this->getOptionWidthCSS($this->optionWidth, $options);
|
||||
$liAttr = '';
|
||||
|
||||
if($columns) {
|
||||
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}%;'";
|
||||
@@ -116,17 +123,33 @@ class InputfieldRadios extends InputfieldSelect {
|
||||
}
|
||||
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 InputfieldInteger $f */
|
||||
$f = $this->wire('modules')->get('InputfieldInteger');
|
||||
$f->label = $this->_('Columns of Radio Buttons');
|
||||
$f->description = $this->_('If you want the radio buttons to display in columns (rather than stacked), enter the number of columns you want to use (up to 10). To display buttons side-by-side (inline) enter 1.');
|
||||
$f->notes = $this->_('If no number is specified here, then each radio button will display on its own line.');
|
||||
$f->attr('name', 'optionColumns');
|
||||
$f->attr('value', (int) $this->optionColumns);
|
||||
$inputfields->add($f);
|
||||
/** @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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user