Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix and Update! #14

Merged
merged 30 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
73df154
save js current
Barny-Thorpe Feb 29, 2024
bad4f20
type
Barny-Thorpe Feb 29, 2024
89b8ba0
add field
Barny-Thorpe Mar 20, 2024
97c2e19
field
Barny-Thorpe Mar 20, 2024
caeb89c
get field
Barny-Thorpe Mar 20, 2024
d46cfc9
work through js as well
Barny-Thorpe Mar 20, 2024
8834df4
get fields to pull in
Barny-Thorpe Mar 20, 2024
dfc0bcd
cleanup field values
Barny-Thorpe Mar 20, 2024
aa0d7fe
pass the class through while its eeasier
Barny-Thorpe Mar 20, 2024
6ff5e02
phpcs
Barny-Thorpe Mar 20, 2024
18bdddc
get class
Barny-Thorpe Mar 20, 2024
4dc97e8
update js to match
Barny-Thorpe Mar 20, 2024
4662da6
revert main issue
Barny-Thorpe Mar 20, 2024
8814a9d
default to previous versions selector
Barny-Thorpe Mar 20, 2024
9820a20
phpcs
Barny-Thorpe Mar 20, 2024
c3e3a37
fallback selector
Barny-Thorpe Mar 21, 2024
5494744
change names
Barny-Thorpe Mar 21, 2024
631c234
use dataset
Barny-Thorpe Mar 21, 2024
e652b94
remove comment
Barny-Thorpe Mar 21, 2024
44cf956
types
Barny-Thorpe Mar 21, 2024
e9ab3d5
GF_Field
Barny-Thorpe Mar 26, 2024
4009e5a
remove unneccessary docs
Barny-Thorpe Mar 26, 2024
3df2a11
only query the document once
Barny-Thorpe Mar 26, 2024
56e5cfa
phpcs
Barny-Thorpe Mar 26, 2024
f868528
fix variable name
Barny-Thorpe Mar 26, 2024
581ee1d
simplify js
Barny-Thorpe Mar 28, 2024
9a22c23
id only id
Barny-Thorpe Mar 28, 2024
6c3992c
function not arrow function
Barny-Thorpe Mar 28, 2024
b17d166
phpcs
Barny-Thorpe Mar 28, 2024
bd90a07
variable names updated js
Barny-Thorpe Apr 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 74 additions & 43 deletions public/js/gf-giftaid-field-frontend.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,88 @@
function gfGiftAidOnInputChange(elem) {
if (!(elem instanceof HTMLElement)) {
return;
}
document.addEventListener('DOMContentLoaded', () => {
initGiftAid();
});

if (! elem.classList.contains('ginput_total') && ! elem.classList.contains('ginput_amount')) {
/**
* Updates the gift aid display, based on a chosen field changing.
*/
function initGiftAid() {
const gravityForm = document.querySelector('.gform_wrapper');
if (! (gravityForm instanceof HTMLElement)) {
return;
}

const parentForm = elem.closest('form');
if (!(parentForm instanceof HTMLFormElement)) {
const totalSelector = totalFieldSelector(gravityForm, '.ginput_amount');
if (!totalSelector) {
return;
}
window.gform.addAction('gform_input_change', (elem) => {
const total = getTotalAmount(elem, totalSelector);
if (! total || !total.donation || !total.giftAidTotal) {
return;
}
updateGiftAidDisplay(gravityForm, total);
}, 10);
}

const totalEl = parentForm.querySelector('.ginput_total');
if (totalEl instanceof HTMLElement) {
elem = totalEl;
/**
* Gets the selector of the total field, selected in the gift aid field settings.
* Will be in the format 'field_<form_id>_<field_id>' and will be an id so the selector will be prefixed by #.
* @param {HTMLElement} gravityForm The form element.
* @param {string} fallback fallback selector if the field is not found.
* @returns {string} The class of the total field.
*/
function totalFieldSelector(gravityForm, fallback) {
const giftAidComponent = gravityForm.querySelector('.gift-box-wrapper');
if (! (giftAidComponent instanceof HTMLElement)) {
return fallback;
}

const spanTotal = parentForm.querySelectorAll('.gform_donation_total');
if (!(spanTotal instanceof NodeList) || 0 === spanTotal.length) {
return;
const selectedPriceFieldId = giftAidComponent.dataset.selectedPriceFieldId;
if (!selectedPriceFieldId) {
return fallback;
}
return `#${selectedPriceFieldId}`;
}

const spanTotalGift = parentForm.querySelectorAll(
'.gform_donation_gifttotal',
);
if (!(spanTotalGift instanceof NodeList) || 0 === spanTotalGift.length) {
return;
/**
* Gets the total amount donated and updates the Gift Aid total.
* @param {HTMLElement} elem The element that has changed.
* @param {string} totalSelector selector of the chosen total field.
* @returns {object} The donation and gift aid total.
*/
function getTotalAmount(elem, totalSelector) {
if (! (elem instanceof HTMLInputElement) || ! elem.closest(totalSelector)) {
return '';
}
const totalValueStr = elem.value;
const totalValueFloat = parseFloat(totalValueStr);
if (! totalValueFloat) {
return '';
}
const giftAidAmount = totalValueFloat * 1.25;

const extractFloat = (str) => {
// Regular expression to match floating-point numbers
const regex = /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/g;

// Use match() to find all matching numbers in the string
const matches = str.match(regex);

// If there are matches, convert them to floats and return them; otherwise, return the original str.
return matches ? matches.map(Number) : str;
return {
donation: totalValueFloat.toFixed(2),
giftAidTotal: giftAidAmount.toFixed(2)
};
}

const val = extractFloat(elem.value);
const total = parseFloat(val).toFixed(2);
const totalGift = parseFloat(val * 1.25).toFixed(2);

Array.from(spanTotal).forEach((item) => {
item.innerHTML = total;
});

Array.from(spanTotalGift).forEach((item) => {
item.innerHTML = totalGift;
});
/**
* Updates the gift aid display.
* @param {HTMLElement} gravityForm The form element.
* @param {object} The donation and gift aid total.
* @returns {void}
*/
function updateGiftAidDisplay(gravityform, total) {
if (!total || !total.donation || !total.giftAidTotal) {
return;
}
const spanTotal = gravityform.querySelector('.gform_donation_total');
if (! (spanTotal instanceof HTMLSpanElement)) {
return;
}
const spanTotalGift = gravityform.querySelector('.gform_donation_gifttotal');
if (! (spanTotalGift instanceof HTMLSpanElement)) {
return;
}
spanTotal.innerHTML = total.donation;
spanTotalGift.innerHTML = total.giftAidTotal;
}
document.addEventListener('DOMContentLoaded', () => {
window.gform.addAction('gform_input_change', gfGiftAidOnInputChange, 10);
});
70 changes: 69 additions & 1 deletion src/GfGiftAidField.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

namespace Itineris\GfGiftaidField;

use GF_Field;
use GFAddOn;
use GFAPI;
use GFForms;

class GfGiftAidField
Expand All @@ -13,11 +15,77 @@ class GfGiftAidField

public static function run(): void
{
if (! method_exists('GFForms', 'include_addon_framework')) {
if (!method_exists('GFForms', 'include_addon_framework')) {
return;
}

GFForms::include_addon_framework();
GFAddOn::register(AddOn::class);

add_action('gform_field_standard_settings', [static::class, 'addSelectedPriceFieldSetting'], 10, 2);
}

/**
* Custom field to enable the user to choose where they would like to pull the total value from.
*/
public static function addSelectedPriceFieldSetting(int $position, int $form_id): void
{
if (25 !== $position || empty($form_id)) {
return;
}
$field_options = static::getFormFields($form_id);
if (empty($field_options)) {
return;
}
?>
<li class="selected_price_field_setting field_setting">
<label for="selected_price_field_dropdown" class="section_label">
<?php esc_html_e('Price Field', 'itineris-gf-giftaid-field'); ?>
</label>

<select
name="donation_total"
id="selected_price_field_dropdown"
onchange="SetFieldProperty('selectedPriceField', this.value);"
>
<?php foreach ($field_options as $field_id => $field_label) : ?>
<?php
if (empty($field_id) || empty($field_label)) {
continue;
}
?>

<option value="<?php echo esc_attr($field_id); ?>"><?php echo esc_html($field_label); ?></option>
<?php endforeach; ?>
</select>
</li>
<?php
}

/**
* Get all the fields in a gravity form in the format:
* ['field class' => 'field_label', ...]
*/
public static function getFormFields(int $form_id): array
{
$exists = GFAPI::form_id_exists($form_id);
if (empty($exists)) {
return [];
}

$form = GFAPI::get_form($form_id);
$fields = $form['fields'] ?? [];
if (empty($fields) || !is_array($fields)) {
return [];
}

return array_reduce($fields, function (array $carry, GF_Field $field) use ($form_id): array {
if (empty($field) || empty($field->id) || empty($field->label)) {
return $carry;
}
$class = "field_{$form_id}_{$field->id}";
$carry[$class] = $field->label;
return $carry;
}, []);
}
}
13 changes: 11 additions & 2 deletions src/GiftAidField.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

class GiftAidField extends GF_Field
{
public string $type = 'giftaid';
public string $type = 'gift_aid';

public function get_form_editor_field_title(): string
{
Expand Down Expand Up @@ -39,6 +39,7 @@ public function get_form_editor_button(): array
public function get_form_editor_field_settings(): array
{
return [
'selected_price_field_setting',
'label_setting',
'description_setting',
'rules_setting',
Expand All @@ -65,17 +66,24 @@ public function get_field_input($form, $value = '', $entry = null): string
{
$id = (int) $this->id;
$giftaidImage = plugins_url('public/img/giftaid.svg', __DIR__);
$selectedPriceField = $this->selectedPriceField ?? '.ginput_amount';

ob_start();
?>
<div class="gift-box-wrapper bg-gray-50 rounded-br-4 p-7.5">
<div
class="gift-box-wrapper bg-gray-50 rounded-br-4 p-7.5"
data-selected-price-field-id="<?php echo esc_attr($selectedPriceField); ?>"
codepuncher marked this conversation as resolved.
Show resolved Hide resolved
>

<div class="giftaid-logo mb-2">
<img src="<?php echo esc_url($giftaidImage); ?>" alt="GiftAid logo">
</div>

<div class="description text-primary font-medium text-xl mb-2">
<?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php echo wpautop(wp_kses_post($this->get_calculated_gift())); ?>
</div>

<div class="gift-box-form-wrapper my-6 pb-6 border-b border-b-gray-200">
<div class="ginput_container ginput_container_checkbox mb-6">
<div class="gfield_checkbox" id="input_<?php echo esc_attr($id); ?>">
Expand All @@ -94,6 +102,7 @@ class="gfield-choice-input"
</div>
</div>
</div>

<div class="details-description"><?php echo wp_kses_post($this->description); ?></div>
</div>
<?php
Expand Down
Loading