344 lines
10 KiB
Text
344 lines
10 KiB
Text
<?php namespace ProcessWire;
|
|
|
|
/**
|
|
* An Inputfield for handling "submit" buttons
|
|
*
|
|
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
|
|
* https://processwire.com
|
|
* License: MPL 2.0
|
|
*
|
|
* @property bool $header Whether or not button will also appear in header (default=false).
|
|
* @property bool $secondary Whether or not button is secondary (default=false).
|
|
* @property bool $small Whether or not button should be small, where supported (default=false).
|
|
* @property string $dropdownInputName Name of input to receive selected dropdown value (default='_action_value') #pw-internal
|
|
* @property bool $dropdownSubmit Selected dropdown value becomes submit value? (default=true) #pw-internal
|
|
* @property bool $dropdownRequired Require dropdown selection, when true, click submit without selection opens dropdown @since 3.0.180 #pw-internal
|
|
* @property string $html Button inner HTML label (default='') @since 3.0.134
|
|
* @property string $text Button inner TEXT label, if $html not provided. (default='') @since 3.0.134
|
|
* @property string $value Button value attribute and inner TEXT label, if $text it provided (default='Submit')
|
|
* @property string $textClass Class applied to span for inner html/text, omitted if blank (default='ui-button-text') @since 3.0.134
|
|
* @property-read string|false $submitValue Value that was submitted if clicked (default=false) @since 3.0.134
|
|
*
|
|
*/
|
|
class InputfieldSubmit extends Inputfield {
|
|
|
|
public static function getModuleInfo() {
|
|
return array(
|
|
'title' => 'Submit', // Module Title
|
|
'summary' => __('Form submit button', __FILE__), // Module Summary
|
|
'version' => 103,
|
|
'permanent' => true,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Names of submit buttons created
|
|
*
|
|
* @var array
|
|
*
|
|
*/
|
|
protected static $submitNames = array();
|
|
|
|
/**
|
|
* Additional dropdown actions added to the button
|
|
*
|
|
* @var array
|
|
*
|
|
*/
|
|
protected $dropdownItems = array();
|
|
|
|
/**
|
|
* Init
|
|
*
|
|
*/
|
|
public function init() {
|
|
parent::init();
|
|
$this->attr('type', 'submit');
|
|
$this->attr('name', 'submit');
|
|
$this->attr('value', $this->_('Submit')); // Standard submit button label
|
|
$this->set('submitValue', false); // becomes string after processInput
|
|
$this->attr('class', 'ui-button ui-widget ui-state-default ui-corner-all');
|
|
$this->set('textClass', 'ui-button-text');
|
|
$this->skipLabel = Inputfield::skipLabelBlank;
|
|
$this->set('small', false);
|
|
$this->set('html', '');
|
|
$this->set('text', '');
|
|
|
|
// name of 'hidden' input that will receive the clicked dropdown item value
|
|
$this->set('dropdownInputName', '_action_value');
|
|
|
|
// Selected dropdown value becomes submit value? If set to false, then only the
|
|
// dropdownInputName above will contain the selected value
|
|
$this->set('dropdownSubmit', true);
|
|
|
|
// dropdown selection required? (when true, clicking submit without dropdown selection opens dropdown)
|
|
$this->set('dropdownRequired', false);
|
|
}
|
|
|
|
public function set($key, $value) {
|
|
if($key == 'header') {
|
|
$this->showInHeader($value);
|
|
} else if($key == 'secondary') {
|
|
$this->setSecondary($value);
|
|
}
|
|
return parent::set($key, $value);
|
|
}
|
|
|
|
public function get($key) {
|
|
if($key == 'header') return $this->hasClass('pw-head-button');
|
|
if($key == 'secondary') return $this->hasClass('ui-priority-secondary');
|
|
return parent::get($key);
|
|
}
|
|
|
|
public function setAttribute($key, $value) {
|
|
if($key === 'name') self::$submitNames[$value] = $value;
|
|
return parent::setAttribute($key, $value);
|
|
}
|
|
|
|
/**
|
|
* Show another copy of this button in the header?
|
|
*
|
|
* @param bool $show True=yes, false=no (default=true)
|
|
* @return $this
|
|
*
|
|
*/
|
|
public function showInHeader($show = true) {
|
|
if($show) {
|
|
$this->addClass('pw-head-button');
|
|
} else {
|
|
$this->removeClass('pw-head-button');
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Make this button secondary? (slightly faded)
|
|
*
|
|
* Note: by default, buttons are not secondary
|
|
*
|
|
* @param bool $secondary Default=true
|
|
* @return $this
|
|
*
|
|
*/
|
|
public function setSecondary($secondary = true) {
|
|
if($secondary) {
|
|
$this->addClass('ui-priority-secondary');
|
|
} else {
|
|
$this->removeClass('ui-priority-secondary');
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Make this button small?
|
|
*
|
|
* By default, buttons are regular size. This makes them small.
|
|
* Supported only for non-dropdown, non-header buttons.
|
|
*
|
|
* @param bool $small Default=true
|
|
* @return $this
|
|
*
|
|
*/
|
|
public function setSmall($small = true) {
|
|
$this->set('small', $small ? true : false);
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Render ready
|
|
*
|
|
* @param Inputfield|InputfieldWrapper|null The parent InputfieldWrapper that is rendering it, or null if no parent.
|
|
* @param bool $renderValueMode Specify true only if this is for `Inputfield::renderValue()` rather than `Inputfield::render()`.
|
|
* @return bool True if assets were just added, false if already added.
|
|
*
|
|
*/
|
|
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
|
$class = $this->attr('class');
|
|
if(strpos($class, 'head_button_clone') !== false) {
|
|
// if legacy class name used, convert to updated pw- class name to accomodate 3rd party usages
|
|
$class = str_replace('head_button_clone', 'pw-head-button', $class);
|
|
$this->attr('class', $class);
|
|
}
|
|
if($this->getSetting('small')) {
|
|
$this->addClass('InputfieldSubmitSmall', 'wrapClass');
|
|
}
|
|
return parent::renderReady($parent, $renderValueMode);
|
|
}
|
|
|
|
/**
|
|
* Render the button
|
|
*
|
|
* @return string
|
|
*
|
|
*/
|
|
public function ___render() {
|
|
$sanitizer = $this->wire()->sanitizer;
|
|
$attrs = $this->getAttributesString();
|
|
$icon = $this->icon ? $sanitizer->name($this->icon) : '';
|
|
$icon = $icon ? wireIconMarkup($icon) . ' ' : '';
|
|
$buttonText = $this->getSetting('html'); // option for non-encoded button text
|
|
if(empty($buttonText)) {
|
|
$buttonText = $this->getSetting('text');
|
|
if(empty($buttonText)) $buttonText = $this->attr('value');
|
|
$buttonText = $this->entityEncode($buttonText);
|
|
}
|
|
$buttonText = $icon . $buttonText;
|
|
$textClass = $sanitizer->entities($this->getSetting('textClass'));
|
|
if(!empty($textClass)) $buttonText = "<span class='$textClass'>$buttonText</span>";
|
|
$out = "<button $attrs>$buttonText</button>";
|
|
if($this->getSetting('small')) $out = "<small>$out</small>";
|
|
if(count($this->dropdownItems)) $out .= $this->renderDropdown();
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Render the dropdown to accompany the button
|
|
*
|
|
* @return string
|
|
*
|
|
*/
|
|
protected function renderDropdown() {
|
|
|
|
if($this->wire('input')->get('modal')) return '';
|
|
|
|
$config = $this->wire()->config;
|
|
$file = $config->debug ? 'dropdown.js' : 'dropdown.min.js';
|
|
$config->scripts->add($config->urls->InputfieldSubmit . $file);
|
|
$numValues = 0;
|
|
$dropdownID = $this->attr('id') . '_dropdown';
|
|
$out = "<ul id='$dropdownID' class='pw-button-dropdown' data-my='left top' data-at='left bottom+1'>";
|
|
|
|
foreach($this->dropdownItems as $item) {
|
|
|
|
// entity encode all the labels in the dropdown
|
|
foreach($item as $k => $v) {
|
|
if($k == 'type') continue;
|
|
$item[$k] = htmlentities($v, ENT_QUOTES, "UTF-8");
|
|
}
|
|
|
|
if($item['type'] == 'link') {
|
|
// direct link
|
|
$out .= "<li><a href='$item[value]'>";
|
|
} else {
|
|
// populate hidden input with value before submit
|
|
$out .= "<li><a data-pw-dropdown-value='$item[value]' href='#'>";
|
|
$numValues++;
|
|
}
|
|
// icon to accompany label
|
|
if($item['icon']) $out .= "<i class='fa fa-fw fa-$item[icon]'></i>";
|
|
|
|
// label and finish item
|
|
$out .= "$item[label]</a></li>";
|
|
}
|
|
|
|
$out .= "</ul>";
|
|
|
|
if($numValues) {
|
|
// there are values that can be populated to a hidden input
|
|
$inputID = $dropdownID . '_value';
|
|
$attr = "type='hidden' name='{$this->dropdownInputName}' id='$inputID' value='' ";
|
|
// copy the submitted dropdown value to the submit button value?
|
|
if($this->dropdownSubmit) $attr .= "data-pw-dropdown-submit='1' ";
|
|
// render the output
|
|
$out = "<input $attr />" . str_replace("<ul ", "<ul data-pw-dropdown-input='#$inputID' ", $out);
|
|
}
|
|
|
|
$required = $this->dropdownRequired ? 'true' : 'false';
|
|
// script to initialize this dropdown immediately
|
|
$out .= "<script" . ">InputfieldSubmitDropdown.init('#{$this->id}', null, $required);</script>";
|
|
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* Process input
|
|
*
|
|
* @param WireInputData $input
|
|
* @return $this
|
|
*
|
|
*/
|
|
public function ___processInput(WireInputData $input) {
|
|
|
|
$this->submitValue = '';
|
|
$name = $this->attr('name');
|
|
$value = $input->$name;
|
|
|
|
if($value === $this->attr('value')) {
|
|
$this->submitValue = $value;
|
|
return $this;
|
|
}
|
|
|
|
if(!count($this->dropdownItems)) return $this;
|
|
|
|
if(!$this->dropdownSubmit) {
|
|
$name = $this->dropdownInputName;
|
|
$value = $input->$name;
|
|
}
|
|
|
|
if($value === null) return $this;
|
|
|
|
foreach($this->dropdownItems as $item) {
|
|
if($value !== $item['value']) continue;
|
|
$this->submitValue = $item['value'];
|
|
break;
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Add a dropdown item to this button
|
|
*
|
|
* @param string $type Either 'link' or 'value'
|
|
* @param string|int $value
|
|
* @param string $label
|
|
* @param string $icon
|
|
*
|
|
*/
|
|
protected function addActionItem($type, $value, $label, $icon) {
|
|
if(!$icon) $icon = 'angle-double-right';
|
|
$this->dropdownItems[] = array(
|
|
'type' => $type,
|
|
'value' => $value,
|
|
'label' => $label,
|
|
'icon' => $icon,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add a dropdown action item that populates a new 'value' for the submit button
|
|
*
|
|
* This also populates the value to $_POST['_action_value']
|
|
*
|
|
* @param string $value Value to populate to hidden input when dropdown item is selected/clicked.
|
|
* @param string $label Text label to accompany the item
|
|
* @param string $icon Icon name (optional)
|
|
*
|
|
*/
|
|
public function addActionValue($value, $label, $icon = '') {
|
|
$this->addActionItem('value', $value, $label, $icon);
|
|
}
|
|
|
|
/**
|
|
* Add a dropdown action item that links to a URL
|
|
*
|
|
* @param string $url URL to link to
|
|
* @param string $label Text label to accompany the item
|
|
* @param string $icon Icon name (optional)
|
|
*
|
|
*/
|
|
public function addActionLink($url, $label, $icon = '') {
|
|
$this->addActionItem('link', $url, $label, $icon);
|
|
}
|
|
|
|
/**
|
|
* #pw-internal
|
|
*
|
|
* @return array()
|
|
*
|
|
*/
|
|
static public function getSubmitNames() {
|
|
return self::$submitNames;
|
|
}
|
|
|
|
}
|