Skip to content

Commit b0fb9f3

Browse files
committed
Merge remote-tracking branch 'origin/AC-15304' into spartans_pr_10112025
2 parents e19fad5 + 76dfe5f commit b0fb9f3

File tree

2 files changed

+125
-15
lines changed

2 files changed

+125
-15
lines changed

app/code/Magento/Checkout/view/frontend/templates/cart/form.phtml

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
?>
1111
<?php $mergedCells = ($this->helper(Magento\Tax\Helper\Data::class)->displayCartBothPrices() ? 2 : 1); ?>
1212
<?= $block->getChildHtml('form_before') ?>
13-
<form action="<?= $block->escapeUrl($block->getUrl('checkout/cart/updatePost')) ?>"
13+
<form action="<?= $escaper->escapeUrl($block->getUrl('checkout/cart/updatePost')) ?>"
1414
method="post"
1515
id="form-validate"
1616
data-mage-init='{"Magento_Checkout/js/action/update-shopping-cart":
17-
{"validationURL" : "<?= $block->escapeUrl($block->getUrl('checkout/cart/updateItemQty')) ?>",
18-
"updateCartActionContainer": "#update_cart_action_container"}
17+
{"validationURL" : "<?= $escaper->escapeUrl($block->getUrl('checkout/cart/updateItemQty')) ?>",
18+
"updateCartActionContainer": "#update_cart_action_container"},
19+
"Magento_Checkout/js/cart/ensure-subtotal-sync": {}
1920
}'
2021
class="form form-cart">
2122
<?= $block->getBlockHtml('formkey') ?>
@@ -29,13 +30,13 @@
2930
class="cart items data table"
3031
data-mage-init='{"shoppingCart":{"emptyCartButton": ".action.clear",
3132
"updateCartActionContainer": "#update_cart_action_container"}}'>
32-
<caption class="table-caption"><?= $block->escapeHtml(__('Shopping Cart Items')) ?></caption>
33+
<caption class="table-caption"><?= $escaper->escapeHtml(__('Shopping Cart Items')) ?></caption>
3334
<thead>
3435
<tr>
35-
<th class="col item" scope="col"><span><?= $block->escapeHtml(__('Item')) ?></span></th>
36-
<th class="col price" scope="col"><span><?= $block->escapeHtml(__('Price')) ?></span></th>
37-
<th class="col qty" scope="col"><span><?= $block->escapeHtml(__('Qty')) ?></span></th>
38-
<th class="col subtotal" scope="col"><span><?= $block->escapeHtml(__('Subtotal')) ?></span></th>
36+
<th class="col item" scope="col"><span><?= $escaper->escapeHtml(__('Item')) ?></span></th>
37+
<th class="col price" scope="col"><span><?= $escaper->escapeHtml(__('Price')) ?></span></th>
38+
<th class="col qty" scope="col"><span><?= $escaper->escapeHtml(__('Qty')) ?></span></th>
39+
<th class="col subtotal" scope="col"><span><?= $escaper->escapeHtml(__('Subtotal')) ?></span></th>
3940
</tr>
4041
</thead>
4142
<?php foreach ($block->getItems() as $_item): ?>
@@ -51,28 +52,28 @@
5152
<div class="cart main actions">
5253
<?php if ($block->getContinueShoppingUrl()): ?>
5354
<a class="action continue"
54-
href="<?= $block->escapeUrl($block->getContinueShoppingUrl()) ?>"
55-
title="<?= $block->escapeHtml(__('Continue Shopping')) ?>">
56-
<span><?= $block->escapeHtml(__('Continue Shopping')) ?></span>
55+
href="<?= $escaper->escapeUrl($block->getContinueShoppingUrl()) ?>"
56+
title="<?= $escaper->escapeHtml(__('Continue Shopping')) ?>">
57+
<span><?= $escaper->escapeHtml(__('Continue Shopping')) ?></span>
5758
</a>
5859
<?php endif; ?>
5960
<?php if ($block->getViewModel()->isClearShoppingCartEnabled()): ?>
6061
<button type="button"
6162
name="update_cart_action"
6263
data-cart-empty=""
6364
value="empty_cart"
64-
title="<?= $block->escapeHtml(__('Clear Shopping Cart')) ?>"
65+
title="<?= $escaper->escapeHtml(__('Clear Shopping Cart')) ?>"
6566
class="action clear" id="empty_cart_button">
66-
<span><?= $block->escapeHtml(__('Clear Shopping Cart')) ?></span>
67+
<span><?= $escaper->escapeHtml(__('Clear Shopping Cart')) ?></span>
6768
</button>
6869
<?php endif ?>
6970
<button type="submit"
7071
name="update_cart_action"
7172
data-cart-item-update=""
7273
value="update_qty"
73-
title="<?= $block->escapeHtml(__('Update Shopping Cart')) ?>"
74+
title="<?= $escaper->escapeHtml(__('Update Shopping Cart')) ?>"
7475
class="action update">
75-
<span><?= $block->escapeHtml(__('Update Shopping Cart')) ?></span>
76+
<span><?= $escaper->escapeHtml(__('Update Shopping Cart')) ?></span>
7677
</button>
7778
<input type="hidden" value="" id="update_cart_action_container" data-cart-item-update=""/>
7879
</div>
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/**
2+
* Copyright 2025 Adobe
3+
* All Rights Reserved.
4+
*/
5+
6+
define([
7+
'jquery',
8+
'mage/translate'
9+
], function ($) {
10+
'use strict';
11+
12+
/**
13+
* Compare central cart subtotal with summary subtotal and click Update once if mismatched.
14+
*/
15+
return function initEnsureSubtotalSync(config, element)
16+
{
17+
const $root = $(element || document);
18+
let clicked = false;
19+
20+
function parsePrice(text)
21+
{
22+
if (!text) {
23+
return NaN;
24+
}
25+
26+
// Remove non-numeric except . , - then normalize
27+
let cleaned = ('' + text).replace(/[^0-9,.-]/g, '');
28+
29+
// If both , and . exist, assume , is thousands
30+
if (cleaned.indexOf(',') > -1 && cleaned.indexOf('.') > -1) {
31+
cleaned = cleaned.replace(/,/g, '');
32+
} else if (cleaned.indexOf(',') > -1 && cleaned.indexOf('.') === -1) {
33+
// European format: swap , to .
34+
cleaned = cleaned.replace(/,/g, '.');
35+
}
36+
37+
const n = parseFloat(cleaned);
38+
39+
return isNaN(n) ? NaN : Math.round(n * 100) / 100;
40+
}
41+
42+
function getCentralSubtotal()
43+
{
44+
// Sum of row totals on the table
45+
let sum = 0;
46+
47+
$root.find('#shopping-cart-table .col.subtotal .cart-price').each(function () {
48+
const text = $(this).text(), val = parsePrice(text);
49+
50+
if (!isNaN(val)) {
51+
sum += val;
52+
}
53+
});
54+
55+
return Math.round(sum * 100) / 100;
56+
}
57+
58+
function getSummarySubtotal()
59+
{
60+
// Summary subtotal in cart totals knockout template
61+
const text = $('#cart-totals .totals.sub .amount .price').first().text();
62+
63+
return parsePrice(text);
64+
}
65+
66+
function trySync()
67+
{
68+
if (clicked) {
69+
return;
70+
}
71+
72+
const central = getCentralSubtotal(), summary = getSummarySubtotal();
73+
74+
if (!isNaN(central) && !isNaN(summary) && central !== summary) {
75+
const $updateBtn = $root.find('.cart.main.actions button.action.update');
76+
77+
if ($updateBtn.length) {
78+
clicked = true;
79+
$updateBtn.trigger('click');
80+
}
81+
}
82+
}
83+
84+
// Initial attempt after DOM ready and after a short delay to allow KO to render totals
85+
$(function () {
86+
trySync();
87+
setTimeout(trySync, 300);
88+
89+
// Observe changes in totals area to re-check once
90+
const totals = document.getElementById('cart-totals');
91+
92+
if (totals && typeof MutationObserver !== 'undefined') {
93+
const obs = new MutationObserver(function () {
94+
trySync();
95+
96+
if (clicked) {
97+
obs.disconnect();
98+
}
99+
});
100+
101+
obs.observe(totals, {
102+
childList: true,
103+
subtree: true,
104+
characterData: true
105+
});
106+
}
107+
});
108+
};
109+
});

0 commit comments

Comments
 (0)