mirror of
https://github.com/processwire/processwire.git
synced 2025-08-16 03:34:33 +02:00
Numerous updates/improvements to the new InputfieldToggle module
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
.InputfieldToggleGroup {
|
||||
display: flex;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.InputfieldToggleGroup input {
|
||||
position: absolute !important;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
border: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.InputfieldToggleGroup label {
|
||||
background-color: #eee;
|
||||
color: rgba(0, 0, 0, 0.6);
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
padding: 8px 16px;
|
||||
margin-right: -1px;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.InputfieldToggleGroup label:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.InputfieldToggleGroup input:checked + label {
|
||||
background-color: #999;
|
||||
color: #fff;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.InputfieldToggleGroup label:first-of-type {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.InputfieldToggleGroup label:last-of-type {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
85
wire/modules/Inputfield/InputfieldToggle/InputfieldToggle.js
Normal file
85
wire/modules/Inputfield/InputfieldToggle/InputfieldToggle.js
Normal file
@@ -0,0 +1,85 @@
|
||||
function InputfieldToggleInit() {
|
||||
|
||||
// this becomes true when we are in a click event, used to avoid double calls to handler
|
||||
var isClick = false;
|
||||
|
||||
// event handler for labels/inputs in a .InputfieldToggleUseDeselect container
|
||||
function toggleInputEvent($input) {
|
||||
|
||||
var cls = 'InputfieldToggleChecked';
|
||||
|
||||
// allow for labels as prev sibling of input or label as parent element of input
|
||||
// var $label = $input.prev('label').length ? $input.prev('label') : $input.closest('label');
|
||||
var $prevInput = $input.closest('.Inputfield').find('input.' + cls);
|
||||
// var $prevLabel = $prevInput.prev('label').length ? $prevInput.prev('label') : $prevInput.closest('label');
|
||||
|
||||
// check of another item was clicked when an existing selection was in place
|
||||
if($prevInput.length && $prevInput.attr('id') != $input.attr('id')) {
|
||||
// remove our custom class from existing selection
|
||||
$prevInput.removeClass(cls).removeAttr('checked');
|
||||
}
|
||||
|
||||
// check if clicked input was already checked
|
||||
if($input.hasClass(cls) && $input.closest('.InputfieldToggleUseDeselect').length) {
|
||||
// if clicked input was already checked, now make it un-checked
|
||||
$input.removeAttr('checked').removeClass(cls);
|
||||
// if this de-select was the first selection in the request, it's necessary to remove
|
||||
// the checked attribute again a short while later for some reason
|
||||
setTimeout(function() { $input.removeAttr('checked') }, 100);
|
||||
} else {
|
||||
// input was just checked (and wasn't before), so add our checked class to the input
|
||||
// $input.attr('checked', 'checked').addClass(cls);
|
||||
$input.addClass(cls);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('change', '.InputfieldToggle input', function() {
|
||||
// change event for de-selectable radios
|
||||
if(isClick) return false;
|
||||
toggleInputEvent($(this));
|
||||
|
||||
}).on('click', '.InputfieldToggle label:not(.InputfieldHeader)', function() {
|
||||
// click event for de-selectable radios
|
||||
if(isClick) return false;
|
||||
var $label = $(this);
|
||||
var $input = $label.prev('input.InputfieldToggleChecked'); // toggle buttons
|
||||
if(!$input.length) $input = $label.children('input.InputfieldToggleChecked'); // radios
|
||||
if(!$input.length) return;
|
||||
isClick = true;
|
||||
toggleInputEvent($input);
|
||||
setTimeout(function() { isClick = false; }, 200);
|
||||
});
|
||||
|
||||
// button style for default toggle button group
|
||||
// inherit colors from existing inputs and buttons
|
||||
var $button = $('button.ui-button:eq(0)');
|
||||
var $input = $('.InputfieldForm input[type=text]:eq(0)');
|
||||
if($button.length && $input.length) {
|
||||
var onBgcolor, onColor, offBgcolor, offColor, borderColor, style;
|
||||
onBgcolor = $button.css('background-color');
|
||||
onColor = $button.css('color');
|
||||
offBgcolor = $input.css('background-color');
|
||||
offColor = $input.css('color');
|
||||
borderColor = $input.css('border-color');
|
||||
style =
|
||||
"<style type='text/css'>" +
|
||||
'.InputfieldToggleGroup label { ' +
|
||||
'background-color: ' + offBgcolor + '; ' +
|
||||
'color: ' + offColor + ';' +
|
||||
'border-color: ' + borderColor + ';' +
|
||||
'} ' +
|
||||
'.InputfieldToggleGroup input:checked + label { ' +
|
||||
'background-color: ' + onBgcolor + '; ' +
|
||||
'color: ' + onColor + ';' +
|
||||
'border-color: ' + onBgcolor + '; ' +
|
||||
'} ' +
|
||||
"</style>";
|
||||
|
||||
$('body').append(style);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
jQuery(document).ready(function($) {
|
||||
InputfieldToggleInit();
|
||||
});
|
1
wire/modules/Inputfield/InputfieldToggle/InputfieldToggle.min.js
vendored
Normal file
1
wire/modules/Inputfield/InputfieldToggle/InputfieldToggle.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
function InputfieldToggleInit(){var isClick=false;function toggleInputEvent($input){var cls="InputfieldToggleChecked";var $prevInput=$input.closest(".Inputfield").find("input."+cls);if($prevInput.length&&$prevInput.attr("id")!=$input.attr("id")){$prevInput.removeClass(cls).removeAttr("checked")}if($input.hasClass(cls)&&$input.closest(".InputfieldToggleUseDeselect").length){$input.removeAttr("checked").removeClass(cls);setTimeout(function(){$input.removeAttr("checked")},100)}else{$input.addClass(cls)}}$(document).on("change",".InputfieldToggle input",function(){if(isClick)return false;toggleInputEvent($(this))}).on("click",".InputfieldToggle label:not(.InputfieldHeader)",function(){if(isClick)return false;var $label=$(this);var $input=$label.prev("input.InputfieldToggleChecked");if(!$input.length)$input=$label.children("input.InputfieldToggleChecked");if(!$input.length)return;isClick=true;toggleInputEvent($input);setTimeout(function(){isClick=false},200)});var $button=$("button.ui-button:eq(0)");var $input=$(".InputfieldForm input[type=text]:eq(0)");if($button.length&&$input.length){var onBgcolor,onColor,offBgcolor,offColor,borderColor,style;onBgcolor=$button.css("background-color");onColor=$button.css("color");offBgcolor=$input.css("background-color");offColor=$input.css("color");borderColor=$input.css("border-color");style="<style type='text/css'>"+".InputfieldToggleGroup label { "+"background-color: "+offBgcolor+"; "+"color: "+offColor+";"+"border-color: "+borderColor+";"+"} "+".InputfieldToggleGroup input:checked + label { "+"background-color: "+onBgcolor+"; "+"color: "+onColor+";"+"border-color: "+onBgcolor+"; "+"} "+"</style>";$("body").append(style)}}jQuery(document).ready(function($){InputfieldToggleInit()});
|
@@ -9,17 +9,17 @@
|
||||
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property int $labelType
|
||||
* @property int $valueType
|
||||
* @property int $labelType Label type to use, see the labelType constants (default=labelTypeYes)
|
||||
* @property int $valueType Type of value for methods that ask for it (use one of the valueType constants)
|
||||
* @property string $yesLabel Custom yes/on label
|
||||
* @property string $noLabel Custom no/off label
|
||||
* @property string $otherLabel Custom label for optional other value
|
||||
* @property int|bool $useReverse
|
||||
* @property int|bool $useOther
|
||||
* @property bool|int $useVertical
|
||||
* @property int $defaultValue
|
||||
* @property int|string $defaultOption
|
||||
* @property string $inputfieldClass
|
||||
* @property string $noLabel Custom no/off label
|
||||
* @property string $otherLabel Custom label for optional other value Label to use for "other" option
|
||||
* @property int|bool $useReverse Reverse the order of the Yes/No options? (default=false)
|
||||
* @property int|bool $useOther Use the "other" option? (default=false)
|
||||
* @property bool|int $useVertical Use vertically oriented radio buttons? (default=false)
|
||||
* @property bool|int $useDeselect Allow radios or toggles to be de-selected, enabling possibility of no-selection? (default=false)
|
||||
* @property int|string $defaultOption Default selected value of 0, 1, 2 or '' (default='')
|
||||
* @property string $inputfieldClass Inputfield class to use or blank for this toggle buttons (default='')
|
||||
*
|
||||
* @method InputfieldSelect|InputfieldRadios getInputfield()
|
||||
*
|
||||
@@ -47,9 +47,6 @@ class InputfieldToggle extends Inputfield {
|
||||
const valueOther = 2;
|
||||
const valueUnknown = '';
|
||||
|
||||
// default or fallback Inputfield clasr
|
||||
const defaultInputfieldClass = 'InputfieldRadios';
|
||||
|
||||
/**
|
||||
* Array of all label types
|
||||
*
|
||||
@@ -93,6 +90,14 @@ class InputfieldToggle extends Inputfield {
|
||||
*/
|
||||
protected $allLabels = array();
|
||||
|
||||
/**
|
||||
* Manually added options of [ value => label ]
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $options = array();
|
||||
|
||||
/**
|
||||
* Construct and set default settings
|
||||
*
|
||||
@@ -106,8 +111,9 @@ class InputfieldToggle extends Inputfield {
|
||||
$this->set('useOther', 0);
|
||||
$this->set('useReverse', 0);
|
||||
$this->set('useVertical', 0);
|
||||
$this->set('useDeselect', 0);
|
||||
$this->set('defaultOption', 'none');
|
||||
$this->set('inputfieldClass', self::defaultInputfieldClass);
|
||||
$this->set('inputfieldClass', '0');
|
||||
|
||||
$this->attr('value', self::valueUnknown);
|
||||
|
||||
@@ -132,8 +138,14 @@ class InputfieldToggle extends Inputfield {
|
||||
*/
|
||||
public function isEmpty() {
|
||||
$value = $this->val();
|
||||
if($value === '') return true;
|
||||
if(is_int($value) && $value > -1) return false;
|
||||
if($value === self::valueUnknown) return true;
|
||||
if(is_int($value)) {
|
||||
if($this->hasOptions()) {
|
||||
if(isset($this->options[$value])) return false;
|
||||
} else {
|
||||
if($value > -1) return false;
|
||||
}
|
||||
}
|
||||
if($value === self::valueOther && $this->useOther) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -153,7 +165,11 @@ class InputfieldToggle extends Inputfield {
|
||||
$intValue = strlen("$value") && ctype_digit("$value") ? (int) $value : '';
|
||||
$strValue = strtolower("$value");
|
||||
|
||||
if($intValue === self::valueNo || $intValue === self::valueYes) {
|
||||
if($this->hasOptions()) {
|
||||
if($intValue !== '') $value = $intValue;
|
||||
$value = isset($this->options[$value]) ? $value : self::valueUnknown;
|
||||
|
||||
} else if($intValue === self::valueNo || $intValue === self::valueYes) {
|
||||
$value = $intValue;
|
||||
|
||||
} else if($intValue === self::valueOther) {
|
||||
@@ -203,18 +219,26 @@ class InputfieldToggle extends Inputfield {
|
||||
/**
|
||||
* Get the delegated Inputfield that will be used for rendering selectable options
|
||||
*
|
||||
* @return InputfieldRadios|InputfieldSelect
|
||||
* @return InputfieldRadios|InputfieldSelect|InputfieldToggle
|
||||
*
|
||||
*/
|
||||
public function ___getInputfield() {
|
||||
|
||||
|
||||
if($this->inputfield) return $this->inputfield;
|
||||
|
||||
$class = $this->getSetting('inputfieldClass');
|
||||
if(empty($class)) $class = self::defaultInputfieldClass;
|
||||
if(empty($class) || $class === $this->className()) {
|
||||
if($this->wire('adminTheme') == 'AdminThemeDefault') {
|
||||
// clicking toggles jumps to top of page on AdminThemeDefault for some reason
|
||||
// even if JS click events are canceled, so use radios instead
|
||||
$class = 'InputfieldRadios';
|
||||
} else {
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
$f = $this->wire('modules')->get($class);
|
||||
if(!$f) $f = $this->wire('modules')->get(self::defaultInputfieldClass);
|
||||
if(!$f || $f === $this) return $this;
|
||||
|
||||
$this->addClass($class, 'wrapClass');
|
||||
|
||||
@@ -226,22 +250,17 @@ class InputfieldToggle extends Inputfield {
|
||||
if(!$this->useVertical) {
|
||||
$f->set('optionColumns', 1);
|
||||
}
|
||||
|
||||
$labels = $this->getLabels($this->labelType);
|
||||
|
||||
if($this->useReverse) {
|
||||
$f->addOption(self::valueNo, $labels['no']);
|
||||
$f->addOption(self::valueYes, $labels['yes']);
|
||||
} else {
|
||||
$f->addOption(self::valueYes, $labels['yes']);
|
||||
$f->addOption(self::valueNo, $labels['no']);
|
||||
$val = $this->val();
|
||||
$options = $this->getOptions();
|
||||
$f->addOptions($options);
|
||||
|
||||
if(isset($options[$val]) && method_exists($f, 'addOptionAttributes')) {
|
||||
$f->addOptionAttributes($val, array('input.class' => 'InputfieldToggleChecked'));
|
||||
}
|
||||
|
||||
if($this->useOther) {
|
||||
$f->addOption(self::valueOther, $labels['other']);
|
||||
}
|
||||
$f->val($val);
|
||||
|
||||
$f->val($this->val());
|
||||
$this->inputfield = $f;
|
||||
|
||||
return $f;
|
||||
@@ -257,7 +276,10 @@ class InputfieldToggle extends Inputfield {
|
||||
*/
|
||||
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
||||
$f = $this->getInputfield();
|
||||
if($f) $f->renderReady($parent, $renderValueMode);
|
||||
if($f && $f !== $this) $f->renderReady($parent, $renderValueMode);
|
||||
if($this->useDeselect && $this->defaultOption === 'none') {
|
||||
$this->addClass('InputfieldToggleUseDeselect', 'wrapClass');
|
||||
}
|
||||
return parent::renderReady($parent, $renderValueMode);
|
||||
}
|
||||
|
||||
@@ -269,7 +291,7 @@ class InputfieldToggle extends Inputfield {
|
||||
*/
|
||||
public function ___renderValue() {
|
||||
$label = $this->getValueLabel($this->attr('value'));
|
||||
$value = $this->wire('sanitizer')->entities1($label);
|
||||
$value = $this->formatLabel($label, true);
|
||||
return $value;
|
||||
}
|
||||
|
||||
@@ -282,9 +304,9 @@ class InputfieldToggle extends Inputfield {
|
||||
public function ___render() {
|
||||
|
||||
$value = $this->val();
|
||||
|
||||
// check if we should assign a default value
|
||||
$default = $this->getSetting('defaultOption');
|
||||
|
||||
// check if we should assign a default value
|
||||
if($default && ("$value" === self::valueUnknown || !strlen("$value"))) {
|
||||
if($default === 'yes') {
|
||||
$this->val(self::valueYes);
|
||||
@@ -296,10 +318,46 @@ class InputfieldToggle extends Inputfield {
|
||||
}
|
||||
|
||||
$f = $this->getInputfield();
|
||||
if(!$f) return "Unable to load Inputfield";
|
||||
$f->val($this->val());
|
||||
|
||||
if($f && $f !== $this) {
|
||||
$f->val($this->val());
|
||||
$out = $f->render();
|
||||
} else {
|
||||
$out = $this->renderToggle();
|
||||
}
|
||||
|
||||
// hidden input to indicate presence when no selection is made (like with radios)
|
||||
$out .= "<input type='hidden' name='_{$this->name}_' value='1' />";
|
||||
|
||||
return $f->render();
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render default input toggles
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function renderToggle() {
|
||||
|
||||
$id = $this->attr('id');
|
||||
$name = $this->attr('name');
|
||||
$checkedValue = $this->val();
|
||||
$out = '';
|
||||
|
||||
foreach($this->getOptions() as $value => $label) {
|
||||
$checked = "$checkedValue" === "$value" ? "checked " : "";
|
||||
$class = $checked ? 'InputfieldToggleChecked' : '';
|
||||
$label = $this->formatLabel($label);
|
||||
$out .=
|
||||
"<input type='radio' id='{$id}_$value' name='$name' class='$class' value='$value' $checked/>" .
|
||||
"<label for='{$id}_$value'><span class='pw-no-select'>$label</span></label>";
|
||||
}
|
||||
|
||||
return
|
||||
"<div class='pw-clearfix ui-helper-clearfix'>" .
|
||||
"<div class='InputfieldToggleGroup'>$out</div>" .
|
||||
"</div>";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,12 +369,17 @@ class InputfieldToggle extends Inputfield {
|
||||
*/
|
||||
public function ___processInput(WireInputData $input) {
|
||||
|
||||
$prevValue = $this->val();
|
||||
$value = $input[$this->name];
|
||||
$intValue = strlen($value) && ctype_digit("$value") ? (int) $value : null;
|
||||
|
||||
if($value === null && $input["_{$this->name}_"] === null) {
|
||||
// input was not rendered in the submitted post, so should be ignored
|
||||
|
||||
if($value === null) {
|
||||
// selection not present in input
|
||||
|
||||
} else if($this->hasOptions()) {
|
||||
// custom options
|
||||
if(isset($this->options[$value])) $this->val($value);
|
||||
|
||||
} else if($intValue === self::valueYes || $intValue === self::valueNo) {
|
||||
// yes or no selected
|
||||
$this->val($intValue);
|
||||
@@ -325,14 +388,18 @@ class InputfieldToggle extends Inputfield {
|
||||
// other selected
|
||||
$this->val($intValue);
|
||||
|
||||
} else if($value === self::valueUnknown) {
|
||||
// no selection (not reachable when using radios)
|
||||
} else if($value === self::valueUnknown || $value === null) {
|
||||
// no selection
|
||||
$this->val(self::valueUnknown);
|
||||
|
||||
} else {
|
||||
// something we don't recognize
|
||||
}
|
||||
|
||||
|
||||
if($this->val() !== $prevValue) {
|
||||
$this->trackChange('value', $prevValue, $this->val());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -453,7 +520,7 @@ class InputfieldToggle extends Inputfield {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the label for the currently set or given value
|
||||
* Get the label for the currently set (or given) value
|
||||
*
|
||||
* @param bool|int|string|null $value Optionally provide value or omit to use currently set value attribute.
|
||||
* @param int|null $labelType Specify labelType constant or omit for selected label type.
|
||||
@@ -463,6 +530,11 @@ class InputfieldToggle extends Inputfield {
|
||||
*/
|
||||
public function getValueLabel($value = null, $labelType = null, $language = null) {
|
||||
|
||||
if($value !== null && $labelType === null && $this->hasOptions()) {
|
||||
// get custom defined option label from addOption() call (API usage only)
|
||||
if(isset($this->options[$value])) return $this->options[$value];
|
||||
}
|
||||
|
||||
$labels = $this->getLabels($labelType, $language);
|
||||
|
||||
if($value === null) $value = $this->attr('value');
|
||||
@@ -484,7 +556,7 @@ class InputfieldToggle extends Inputfield {
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getYesLabel($labelType = null, $language = null) {
|
||||
protected function getYesLabel($labelType = null, $language = null) {
|
||||
return $this->getValueLabel(self::valueYes, $labelType, $language);
|
||||
}
|
||||
|
||||
@@ -496,7 +568,7 @@ class InputfieldToggle extends Inputfield {
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getNoLabel($labelType = null, $language = null) {
|
||||
protected function getNoLabel($labelType = null, $language = null) {
|
||||
return $this->getValueLabel(self::valueNo, $labelType, $language);
|
||||
}
|
||||
|
||||
@@ -508,7 +580,7 @@ class InputfieldToggle extends Inputfield {
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getOtherLabel($labelType = null, $language = null) {
|
||||
protected function getOtherLabel($labelType = null, $language = null) {
|
||||
return $this->getValueLabel(self::valueOther, $labelType, $language);
|
||||
}
|
||||
|
||||
@@ -520,9 +592,122 @@ class InputfieldToggle extends Inputfield {
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function getUnknownLabel($labelType = null, $language = null) {
|
||||
protected function getUnknownLabel($labelType = null, $language = null) {
|
||||
return $this->getValueLabel(self::valueUnknown, $labelType, $language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format label for HTML output (entity encode, etc.)
|
||||
*
|
||||
* @param string $label
|
||||
* @param bool $allowIcon Allow icon markup to appear in label?
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function formatLabel($label, $allowIcon = true) {
|
||||
$label = $this->wire('sanitizer')->entities1($label);
|
||||
if(strpos($label, 'icon-') !== false && preg_match('/\bicon-([-_a-z0-9]+)/', $label, $matches)) {
|
||||
$name = $matches[1];
|
||||
$icon = $allowIcon ? $icon = wireIconMarkup($name, 'fw') : '';
|
||||
$label = str_replace("icon-$name", $icon, $label);
|
||||
}
|
||||
return trim($label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all selectable options as array of [ value => label ]
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function getOptions() {
|
||||
// use custom options instead if any have been set from an addOption() call
|
||||
if($this->hasOptions()) return $this->options;
|
||||
// use built in toggle options
|
||||
$options = array();
|
||||
$values = $this->useReverse ? array(self::valueNo, self::valueYes) : array(self::valueYes, self::valueNo);
|
||||
if($this->useOther) $values[] = self::valueOther;
|
||||
foreach($values as $value) {
|
||||
$options[$value] = $this->getValueLabel($value);
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a selectable option (custom API usage only, overrides built-in options)
|
||||
*
|
||||
* Note that once you use this, your options take over and Toggle's default yes/no/other
|
||||
* are no longer applicable. This is for custom API use and is not used by FieldtypeToggle.
|
||||
*
|
||||
* @param int|string $value
|
||||
* @param null|string $label
|
||||
* @return $this
|
||||
* @throws WireException if you attempt to call this method when used with FieldtypeToggle
|
||||
*
|
||||
*/
|
||||
public function addOption($value, $label = null) {
|
||||
if($this->hasFieldtype) {
|
||||
throw new WireException('The addOption() method is not available for FieldtypeToggle');
|
||||
}
|
||||
if($label === null) $label = $value;
|
||||
$this->options[$value] = $label;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all options with array of [ value => label ] (custom API usage only, overrides built-in options)
|
||||
*
|
||||
* Once you use this (with a non-empty array, your set options take over and the
|
||||
* built-in yes/no/other no longer apply. This is for custom API use and is not used
|
||||
* by FieldtypeToggle.
|
||||
*
|
||||
* The value for each option must be an integer value between -128 and 127.
|
||||
*
|
||||
* @param array $options
|
||||
* @return $this
|
||||
* @throws WireException if you attempt to call this method when used with FieldtypeToggle
|
||||
*
|
||||
*/
|
||||
public function setOptions(array $options) {
|
||||
$this->options = array();
|
||||
foreach($options as $key => $value) {
|
||||
$this->addOption($key, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Are custom options in use?
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
protected function hasOptions() {
|
||||
return !$this->hasFieldtype && count($this->options) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of config property names allowed for fieldgroup/template context
|
||||
*
|
||||
* @param Field $field
|
||||
* @return array of Inputfield names
|
||||
* @see Fieldtype::getConfigAllowContext()
|
||||
*
|
||||
*/
|
||||
public function ___getConfigAllowContext($field) {
|
||||
return array_merge(parent::___getConfigAllowContext($field), array(
|
||||
'labelType',
|
||||
'inputfieldClass',
|
||||
'yesLabel',
|
||||
'noLabel',
|
||||
'otherLabel',
|
||||
'useVertical',
|
||||
'useDeselect',
|
||||
'useOther',
|
||||
'useReverse',
|
||||
'defaultOption',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure Inputfield
|
||||
@@ -534,12 +719,20 @@ class InputfieldToggle extends Inputfield {
|
||||
|
||||
/** @var Modules $modules */
|
||||
$modules = $this->wire('modules');
|
||||
|
||||
/** @var Languages $languages */
|
||||
$languages = $this->wire('languages');
|
||||
|
||||
$inputfields = parent::___getConfigInputfields();
|
||||
|
||||
if($this->hasFieldtype) {
|
||||
/** @var InputfieldFieldset $fieldset */
|
||||
$fieldset = $modules->get('InputfieldFieldset');
|
||||
$fieldset->label = $this->_('Toggle field labels and input settings');
|
||||
$fieldset->icon = 'toggle-on';
|
||||
$inputfields->prepend($fieldset);
|
||||
} else {
|
||||
$fieldset = $inputfields;
|
||||
}
|
||||
|
||||
$removals = array('defaultValue');
|
||||
foreach($removals as $name) {
|
||||
$f = $inputfields->getChildByName($name);
|
||||
@@ -560,20 +753,22 @@ class InputfieldToggle extends Inputfield {
|
||||
}
|
||||
$f->attr('value', (int) $this->labelType);
|
||||
$f->columnWidth = 34;
|
||||
$inputfields->add($f);
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldRadios $f */
|
||||
$f = $modules->get('InputfieldRadios');
|
||||
$f->attr('name', 'inputfieldClass');
|
||||
$f->label = $this->_('Input type');
|
||||
$f->addOption('0', $this->_('Toggle buttons'));
|
||||
foreach($modules->findByPrefix('Inputfield') as $name) {
|
||||
if(!wireInstanceOf($name, 'InputfieldSelect')) continue;
|
||||
if(wireInstanceOf($name, 'InputfieldHasArrayValue')) continue;
|
||||
$f->addOption($name, str_replace('Inputfield', '', $name));
|
||||
$label = str_replace('Inputfield', '', $name);
|
||||
$f->addOption($name, $label);
|
||||
}
|
||||
$f->val($this->getSetting('inputfieldClass'));
|
||||
$f->columnWidth = 33;
|
||||
$inputfields->add($f);
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldRadios $f */
|
||||
$f = $modules->get('InputfieldRadios');
|
||||
@@ -584,7 +779,33 @@ class InputfieldToggle extends Inputfield {
|
||||
$f->val($this->useVertical ? 1 : 0);
|
||||
$f->columnWidth = 33;
|
||||
$f->showIf = 'inputfieldClass=InputfieldRadios';
|
||||
$inputfields->add($f);
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
$f = $modules->get('InputfieldCheckbox');
|
||||
$f->attr('name', 'useOther');
|
||||
$f->label = $this->_('Use a 3rd “other” option?');
|
||||
if($this->useOther) $f->attr('checked', 'checked');
|
||||
$f->columnWidth = 34;
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
$f = $modules->get('InputfieldCheckbox');
|
||||
$f->attr('name', 'useReverse');
|
||||
$f->label = $this->_('Reverse order of yes/no options?');
|
||||
if($this->useReverse) $f->attr('checked', 'checked');
|
||||
$f->columnWidth = 33;
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
$f = $modules->get('InputfieldCheckbox');
|
||||
$f->attr('name', 'useDeselect');
|
||||
$f->label = $this->_('Support click to de-select?');
|
||||
$f->showIf = "inputfieldClass=0|InputfieldRadios";
|
||||
if($this->useDeselect) $f->attr('checked', 'checked');
|
||||
$f->columnWidth = 33;
|
||||
$f->showIf = 'defaultOption=none';
|
||||
$fieldset->add($f);
|
||||
|
||||
$customStates = array(
|
||||
'yesLabel' => $this->_('Yes/On'),
|
||||
@@ -597,7 +818,7 @@ class InputfieldToggle extends Inputfield {
|
||||
$f->attr('name', $name);
|
||||
$f->label = sprintf($this->_('Label for “%s” option'), $label);
|
||||
$f->showIf = 'labelType=' . self::labelTypeCustom;
|
||||
$f->attr('value', $this->get($name));
|
||||
$f->val($this->get($name));
|
||||
$f->columnWidth = 50;
|
||||
if($languages) {
|
||||
$f->useLanguages = true;
|
||||
@@ -606,50 +827,35 @@ class InputfieldToggle extends Inputfield {
|
||||
if(!$language->isDefault()) $f->set("value$language", $langValue);
|
||||
}
|
||||
}
|
||||
$inputfields->add($f);
|
||||
$fieldset->add($f);
|
||||
}
|
||||
|
||||
/** @var InputfieldText $f */
|
||||
$f = $modules->get('InputfieldText');
|
||||
$f->attr('name', 'otherLabel');
|
||||
$f->label = sprintf($this->_('Label for 3rd option'));
|
||||
$f->label = sprintf($this->_('Label for 3rd “other” option'));
|
||||
$f->showIf = 'useOther=1';
|
||||
$f->attr('value', $this->get('otherLabel'));
|
||||
$f->columnWidth = 50;
|
||||
$f->val($this->get('otherLabel'));
|
||||
if($languages) {
|
||||
$f->useLanguages = true;
|
||||
foreach($languages as $language) {
|
||||
if(!$language->isDefault()) $f->set("value$language", $this->get("otherLabel$language"));
|
||||
}
|
||||
}
|
||||
$inputfields->add($f);
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
$f = $modules->get('InputfieldCheckbox');
|
||||
$f->attr('name', 'useOther');
|
||||
$f->label = $this->_('Show a 3rd option?');
|
||||
if($this->useOther) $f->attr('checked', 'checked');
|
||||
$f->columnWidth = 50;
|
||||
$inputfields->add($f);
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
$f = $modules->get('InputfieldCheckbox');
|
||||
$f->attr('name', 'useReverse');
|
||||
$f->label = $this->_('Reverse order of yes/no options?');
|
||||
if($this->useReverse) $f->attr('checked', 'checked');
|
||||
$inputfields->add($f);
|
||||
$fieldset->add($f);
|
||||
|
||||
/** @var InputfieldRadios $f */
|
||||
$f = $modules->get('InputfieldRadios');
|
||||
/** @var InputfieldToggle $f */
|
||||
$f = $modules->get('InputfieldToggle');
|
||||
$f->set('inputfieldClass', $this->inputfieldClass);
|
||||
$f->attr('name', 'defaultOption');
|
||||
$f->label = $this->_('Default selected option');
|
||||
$f->addOption('yes', $this->getYesLabel());
|
||||
$f->addOption('no', $this->getNoLabel());
|
||||
if($this->useOther) $f->addOption('other', $this->getOtherLabel());
|
||||
$f->addOption('none', $this->_('No selection'));
|
||||
$f->optionColumns = 1;
|
||||
$f->attr('value', $this->defaultOption);
|
||||
$inputfields->add($f);
|
||||
$f->val($this->defaultOption);
|
||||
$f->addClass('InputfieldToggle', 'wrapClass');
|
||||
$fieldset->add($f);
|
||||
|
||||
return $inputfields;
|
||||
}
|
||||
|
Reference in New Issue
Block a user