Bootcamp page: CTAs say 'Buy for 790 USD' and post the basket natively

The three CTAs (hero, mid-page, §7) were <a class="btn-buy"> that only worked
through JavaScript. They are now native <form method="post" target="_blank">
elements posting basket=[{"product_id":12,"qty":1}] + clear=1 to
https://20.odoo4projects.com/shop/post_basket, so the buy works with JavaScript
disabled; the button keeps the brass styling and the same size classes.

static/buy.js no longer builds a form on click. It is now pure progressive
enhancement: a capture-phase submit listener appends the utm_source/medium/
campaign hidden inputs from the cookies and lets the native submit proceed.

One page-scoped declaration keeps the button height at 55px: a <button> takes
line-height:normal from the UA font shorthand where the <a>s inherited the body
line-height (measured 49.19px vs 54.78px without it).
This commit is contained in:
oliver committed 2026-10-24 22:26:40 +00:00
1 parent f0c6284bda
commit 24e542f4ab
2 files changed
+40 -45

No files matched your search

+22 -3
View File
@@ -137,6 +137,13 @@
text-align: center; text-align: center;
margin-top: 0.5rem; margin-top: 0.5rem;
} }
/* The three CTAs are native basket <form>s with a <button> (they were <a>s).
A <button> takes `line-height: normal` from the UA font shorthand while
the <a>s inherited the body line-height, which would make the button
5.6px shorter. Match the anchors' height: one declaration, no new look. */
form[action$="/shop/post_basket"] .btn {
line-height: inherit;
}
/* Grids — auto-fit so no breakpoint is needed */ /* Grids — auto-fit so no breakpoint is needed */
.bc-list { .bc-list {
@@ -527,7 +534,11 @@
<span class="hero-stat"><i aria-hidden="true">&#10003;</i> One year of Odoo Community Edition included</span> <span class="hero-stat"><i aria-hidden="true">&#10003;</i> One year of Odoo Community Edition included</span>
</div> </div>
<div class="hero-actions"> <div class="hero-actions">
<a href="javascript:void(0)" class="btn btn-brass btn-lg btn-buy" data-id="12">Reserve your seat</a> <form method="post" action="https://20.odoo4projects.com/shop/post_basket" target="_blank">
<input type="hidden" name="basket" value='[{"product_id":12,"qty":1}]' />
<input type="hidden" name="clear" value="1" />
<button type="submit" class="btn btn-brass btn-lg">Buy for 790 USD</button>
</form>
</div> </div>
</div> </div>
</section> </section>
@@ -546,7 +557,11 @@
</p> </p>
<p class="bc-subline">Three months. Ten hours of teaching. One system that runs your company.</p> <p class="bc-subline">Three months. Ten hours of teaching. One system that runs your company.</p>
<div class="bc-action"> <div class="bc-action">
<a href="javascript:void(0)" class="btn btn-brass btn-lg btn-buy" data-id="12">Reserve your seat</a> <form method="post" action="https://20.odoo4projects.com/shop/post_basket" target="_blank">
<input type="hidden" name="basket" value='[{"product_id":12,"qty":1}]' />
<input type="hidden" name="clear" value="1" />
<button type="submit" class="btn btn-brass btn-lg">Buy for 790 USD</button>
</form>
</div> </div>
</div> </div>
</section> </section>
@@ -715,7 +730,11 @@
alumni community and the expert review. alumni community and the expert review.
</p> </p>
<div class="bc-action"> <div class="bc-action">
<a href="javascript:void(0)" class="btn btn-brass btn-lg btn-buy" data-id="12">Reserve your seat</a> <form method="post" action="https://20.odoo4projects.com/shop/post_basket" target="_blank">
<input type="hidden" name="basket" value='[{"product_id":12,"qty":1}]' />
<input type="hidden" name="clear" value="1" />
<button type="submit" class="btn btn-brass btn-lg">Buy for 790 USD</button>
</form>
</div> </div>
<ul class="bc-related"> <ul class="bc-related">
<li><a href="/support.html#contact">Questions before you book? Talk to us first</a></li> <li><a href="/support.html#contact">Questions before you book? Talk to us first</a></li>
+18 -42
View File
@@ -1,10 +1,14 @@
/* buy.js — page-local checkout helper. /* buy.js — page-local checkout helper (progressive enhancement).
* *
* Mirrors `script.js` `buyNow()` — the main page's checkout path. * The checkout itself is a native <form method="post" target="_blank"> that posts
* basket=[{"product_id":12,"qty":1}] + clear=1 to
* https://20.odoo4projects.com/shop/post_basket. With JavaScript off it still works.
*
* This file only adds attribution: on submit it appends the utm_* hidden inputs
* from the cookies, then lets the native submit proceed (it never preventDefault).
*
* The UTM helpers mirror `script.js` `buyNow()` — the main page's checkout path.
* If that changes, change this too. * If that changes, change this too.
*
* Loaded by pages that do not load `script.js` (e.g. the bootcamp page).
* Binds `.btn-buy` elements: <a class="btn-buy" data-id="12">…</a>.
*/ */
(function () { (function () {
'use strict'; 'use strict';
@@ -29,7 +33,7 @@
var stored = getStoredUTM(); var stored = getStoredUTM();
var keys = ['source', 'medium', 'campaign']; var keys = ['source', 'medium', 'campaign'];
for (var i = 0; i < keys.length; i++) { for (var i = 0; i < keys.length; i++) {
if (stored[keys[i]]) { if (stored[keys[i]] && !form.elements['utm_' + keys[i]]) {
var input = document.createElement('input'); var input = document.createElement('input');
input.type = 'hidden'; input.type = 'hidden';
input.name = 'utm_' + keys[i]; input.name = 'utm_' + keys[i];
@@ -39,41 +43,13 @@
} }
} }
/* ---- Buy Now — POST basket via form, opens checkout in new tab ---- */ /* ---- Progressive enhancement: add UTM inputs to the native basket form ----
window.buyNow = function (productId) { Capture phase, so the inputs are in the form before the browser serialises it.
var form = document.createElement('form'); No preventDefault — the native POST proceeds untouched. */
form.method = 'POST'; document.addEventListener('submit', function (e) {
form.action = 'https://20.odoo4projects.com/shop/post_basket'; var form = e.target;
form.target = '_blank'; if (!form || form.tagName !== 'FORM') return;
form.style.display = 'none'; if (!form.querySelector('input[name="basket"]')) return;
var basket = document.createElement('input');
basket.type = 'hidden';
basket.name = 'basket';
basket.value = JSON.stringify([{ product_id: productId, qty: 1 }]);
form.appendChild(basket);
var clear = document.createElement('input');
clear.type = 'hidden';
clear.name = 'clear';
clear.value = '1';
form.appendChild(clear);
appendToForm(form); appendToForm(form);
}, true);
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
};
/* ---- Bind .btn-buy (delegated: same contract as script.js) ---- */
document.addEventListener('click', function (e) {
var btn = e.target.closest ? e.target.closest('.btn-buy') : null;
if (!btn) return;
var id = btn.getAttribute('data-id');
if (id) {
e.preventDefault();
window.buyNow(parseInt(id, 10));
}
});
})(); })();