1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-24 15:23:11 +02:00

Add support for PHP-defined header actions for Inputfields as requested by @Toutouwai. These work the same as those defined in JS via Inputfields.addHeaderAction() except the method can now also be called from Inputfield objects in PHP. Also added support for 'link' type actions that open a link in either the current or a modal window.

This commit is contained in:
Ryan Cramer
2024-05-24 14:42:23 -04:00
parent 049efa7c3b
commit 3c5205721b
4 changed files with 177 additions and 18 deletions

View File

@@ -3,7 +3,7 @@
/**
* ProcessWire Inputfield - base class for Inputfield modules.
*
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
* https://processwire.com
*
* An Inputfield for an actual form input field widget, and this is provided as the base class
@@ -397,6 +397,14 @@ abstract class Inputfield extends WireData implements Module {
*/
protected $editable = true;
/**
* Header icon definitions
*
* @var array
*
*/
protected $headerActions = array();
/**
* Construct the Inputfield, setting defaults for all properties
*
@@ -2081,6 +2089,60 @@ abstract class Inputfield extends WireData implements Module {
return $this->editable;
}
/**
* Add header action
*
* This adds a clickable icon to the right side of the Inputfield header.
* There are three types of actions: 'click', 'toggle' and 'link'. The 'click'
* action simply triggers your JS event whenever it is clicked. The 'toggle' action
* has an on/off state, and you can specify the JS event to trigger for each.
* This function will automatically figure out whether you want a `click`,
* `toggle` or 'link' action based on what you provide in the $settings argument.
* Below is a summary of these settings:
*
* Settings for 'click' or 'link' type actions:
*
* - `icon` (string): Name of font-awesome icon to use.
* - `tooltip` (string): Optional tooltip text to display when icon hovered.
* - `event` (string): Event name to trigger in JS when clicked ('click' actions only).
* - `href` (string): URL to open ('link' actions only).
* - `modal` (bool): Specify true to open link in modal ('link' actions only).
*
* Settings for 'toggle' (on/off) type actions:
*
* - `on` (bool): Start with the 'on' state? (default=false)
* - `onIcon` (string): Name of font-awesome icon to show for on state.
* - `onEvent` (string): JS event name to trigger when toggled on.
* - `onTooltip` (string): Tooltip text to show when on icon is hovered.
* - `offIcon` (string): Name of font-awesome icon to show for off state.
* - `offEvent` (string): JS event name to trigger when toggled off.
* - `offTooltip` (string): Tooltip text to show when off icon is hovered.
*
* Other/optional settings (applies to all types):
*
* - `name` (string): Name of this action (-_a-zA-Z0-9).
* - `overIcon` (string): Name of font-awesome icon to show when hovered.
* - `overEvent` (string): JS event name to trigger when mouse is over the icon.
* - `cursor` (string): CSS cursor name to show when mouse is over the icon.
* - `setAll` (array): Set all of the header actions in one call, replaces any existing.
* Note: to get all actions, call the method and omit the $settings argument.
*
* @param array $settings Specify array containing the appropriate settings above.
* @return array Returns all currently added actions.
* @since 3.0.240
*
*/
public function addHeaderAction(array $settings = array()) {
if(!empty($settings['setAll'])) {
if(is_array($settings['setAll'])) {
$this->headerActions = array_values($settings['setAll']);
}
} else {
$this->headerActions[] = $settings; // add new action
}
return $this->headerActions; // return all
}
/**
* debugInfo PHP 5.6+ magic method
*

View File

@@ -3,7 +3,7 @@
/**
* ProcessWire InputfieldWrapper
*
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer
* ProcessWire 3.x, Copyright 2024 by Ryan Cramer
* https://processwire.com
*
* About InputfieldWrapper
@@ -885,6 +885,10 @@ class InputfieldWrapper extends Inputfield implements \Countable, \IteratorAggre
if($toggle && strpos($toggle, 'title=') === false) {
$toggle = str_replace("class=", "title='" . $this->_('Toggle open/close') . "' class=", $toggle);
}
$headerActions = $inputfield->addHeaderAction();
if(count($headerActions)) {
$label .= $this->renderHeaderActions($inputfield, $headerActions);
}
if($skipLabel === Inputfield::skipLabelHeader || $quietMode) {
// label only shows when field is collapsed
$label = str_replace('{out}', $icon . $label . $toggle, $markup['item_label_hidden']);
@@ -992,6 +996,52 @@ class InputfieldWrapper extends Inputfield implements \Countable, \IteratorAggre
return $out;
}
/**
* Render Inputfield header actions
*
* @param Inputfield $inputfield
* @param array $actions
* @return string
* @since 3.0.240
*
*/
protected function renderHeaderActions(Inputfield $inputfield, array $actions) {
$sanitizer = $this->wire()->sanitizer;
$out = '';
$modal = false;
foreach($actions as $a) {
$icon = '';
$type = '';
if(isset($a['icon'])) {
$icon = $a['icon'];
if(isset($a['href'])) {
$type = 'link';
if(!empty($a['modal'])) $modal = true;
} else {
$type = 'click';
}
} else if(isset($a['offIcon'])) {
$type = 'toggle';
if(!isset($a['onIcon'])) $a['onIcon'] = $a['offIcon'];
} else if(isset($a['onIcon'])) {
$type = 'toggle';
$a['offIcon'] = $a['onIcon'];
}
if($type === 'toggle') $icon = $a['on'] ? $a['onIcon'] : $a['offIcon'];
if(empty($icon) || empty($type)) continue;
$a['type'] = $type;
if(strpos($icon, 'fa-') !== 0) $icon = "fa-$icon";
$data = $sanitizer->entities(json_encode($a));
$out .= "<i class='_InputfieldHeaderAction fa fa-fw $icon' data-action='$data' hidden></i>";
}
if($modal) {
/** @var JqueryUI $jQueryUI */
$jQueryUI = $this->wire()->modules->get('JqueryUI');
$jQueryUI->use('modal');
}
return $out;
}
/**
* Render the output of this Inputfield and its children, showing values only (no inputs)
*