element that surrounds checkbox (default=[]) @since 3.0.141 * @property int $autocheck When set to 1, setting value attribute to non-blank/non-zero automatically triggers checked. * * */ class InputfieldCheckbox extends Inputfield { public static function getModuleInfo() { return array( 'title' => __('Checkbox', __FILE__), // Module Title 'summary' => __('Single checkbox toggle', __FILE__), // Module Summary 'version' => 106, 'permanent' => true, ); } /** * Default checked value * */ const checkedValueDefault = 1; /** * Default unchecked value * */ const uncheckedValueDefault = ''; /** * True if the $checkedValue set manually (and should be used as a label), false if it was inherited from $value attribute * */ protected $checkedValueIsLabel = false; /** * Construct and set default settings * */ public function __construct() { $this->set('checkedValue', self::checkedValueDefault); $this->checkedValueIsLabel = false; // cancel line above $this->set('uncheckedValue', self::uncheckedValueDefault); // when autocheck set to 1, setting the value attribute to non-zero automatically triggered checked=checked attribute $this->set('autocheck', 0); // alternate label for checkbox (both do the same thing but for different config context) $this->set('label2', ''); // typically specified by API $this->set('checkboxOnly', false); // render checkbox only, without showing label text $this->set('checkboxLabel', ''); // typically specified by interactive config $this->set('labelAttrs', array()); // Optional attributes for "; return $out; } /** * Render value only * * @return string * */ public function ___renderValue() { $value = $this->val(); if($value != self::uncheckedValueDefault && $value != $this->uncheckedValue) { $value = $this->wire()->sanitizer->entities($this->checkedValue); $value = $value === "1" ? $this->_('Checked') : $value; $value = wireIconMarkup('check-square-o') . " $value"; } else { $value = $this->wire()->sanitizer->entities($this->uncheckedValue); $value = empty($value) ? $this->_('Not checked') : $value; $value = wireIconMarkup('square-o') . " $value"; } return $value; } /** * Set attribute * * @param array|string $key * @param array|int|string $value * @return Inputfield|InputfieldCheckbox * */ public function setAttribute($key, $value) { if($key === 'value' && $value && "$value" !== "$this->uncheckedValue") { if("$value" !== (string) self::checkedValueDefault) { $this->checkedValue = $value; $this->checkedValueIsLabel = false; } // autocheck mode: when non-zero 'value' set, then 'checked=checked' is assumed if($this->autocheck || $this->getSetting('formBuilder')) $this->attr('checked', 'checked'); } return parent::setAttribute($key, $value); } /** * Set property * * @param string $key * @param mixed $value * @return InputfieldCheckbox|Inputfield * */ public function set($key, $value) { if($key === 'checkedValue' && $value != self::checkedValueDefault) { $this->checkedValueIsLabel = true; } return parent::set($key, $value); } /** * Get or set current checkbox boolean attribute state * * ~~~~~ * // the following two lines are equivalent to GET checkbox state * $checked = $f->checked(); * $checked = !empty($f->attr('checked')); * * // the following two lines are equivalent to SET checkbox state * $f->checked(true); * $f->attr('checked', 'checked'); * ~~~~~ * * @param bool|null Specify boolean to set checkbox state * @return bool * @since 3.0.133 * */ public function checked($checked = null) { if($checked !== null) { if($checked) { $this->attr('checked', 'checked'); $checked = true; } else { $this->removeAttr('checked'); $checked = false; } } else { $checked = $this->attr('checked'); $checked = empty($checked) ? false : true; } return $checked; } /** * Is checkbox currently checked? * * #pw-internal * * @return bool * */ public function isChecked() { return $this->checked(); } /** * Is empty (checkbox not checked)? * * @return bool * */ public function isEmpty() { return !$this->checked(); } /** * Process input * * @param WireInputData $input * @return $this * */ public function ___processInput(WireInputData $input) { $value = $input[$this->name]; $checked = $this->isChecked(); if(!empty($value)) { if(!$checked) $this->trackChange('value', $this->uncheckedValue, $this->checkedValue); parent::attr('checked', 'checked'); parent::attr('value', $this->checkedValue); } else { if($checked) $this->trackChange('value', $this->checkedValue, $this->uncheckedValue); parent::attr('checked', ''); parent::attr('value', $this->uncheckedValue); } return $this; } /** * Configure checkbox field * * @return InputfieldWrapper * */ public function ___getConfigInputfields() { $inputfields = parent::___getConfigInputfields(); $languages = $this->wire()->languages; /** @var InputfieldText $f */ $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'checkboxLabel'); $f->label = $this->_('Checkbox label'); $f->description = $this->_('If you want to have separate field and checkbox labels, specify the label that will appear next to the checkbox here.'); $f->notes = $this->_('If not specified, the field label will be used instead.'); $f->attr('value', $this->getSetting('checkboxLabel')); $f->icon = 'check-square'; $f->collapsed = Inputfield::collapsedBlank; if($languages) { $f->useLanguages = true; foreach($languages as $language) { if(!$language->isDefault()) $f->set("value$language", $this->getSetting("checkboxLabel$language")); } } $inputfields->add($f); // if working with fieldtype, no additional settings are applicable if($this->hasFieldtype) return $inputfields; $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'checkedValue'); $f->attr('value', $this->checkedValue); $f->label = $this->_('Checked Value'); $f->collapsed = $this->checkedValue == self::checkedValueDefault ? Inputfield::collapsedYes : Inputfield::collapsedNo; $f->description = $this->_('When populated with something other than "1", this will appear as a label directly next to the checkbox.'); $f->required = true; $inputfields->add($f); $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'uncheckedValue'); $f->attr('value', "$this->uncheckedValue"); $f->label = $this->_('Unchecked Value'); $f->collapsed = $this->uncheckedValue == self::uncheckedValueDefault ? Inputfield::collapsedYes : Inputfield::collapsedNo; $f->description = $this->_('This only appears in result entries, not in the form itself. You should leave this blank unless you want it to hold a specific value.'); $inputfields->add($f); return $inputfields; } }