Text
Only Copyable Shopping Baskets
I’ve been ordering a large number of things from ThePiHut lately, and the university procurement system needs quite a few details of each order line so they can actually make the purchase.
Unfortunately, ThePiHut’s website does not include an ‘export basket’ or other equivalent mechanism that I can use to send all these details to our procurement folks… so in the usual fasion of a developer faced with a code-based problem, I wrote a code-based solution.
I wrote a GreaseMonkey / TamperMonkey script that only runs on the basket page of ThePiHut, and pulls all the details of each item in your basket, dropping them all into a single text box with all the information a procurement department could want.
This simple script I’ve posted on Github as a Gist, which both systems can use as an install and update source (although I do consider this ‘complete’ so probably won’t change it much now). Or you can copy the frozen copy of this gist from the code box below this post.
Hopefully this won’t be needed forever as the folks at ThePiHut could easily add identical functionality into the website itself, but for now, it saves me a ton of time, and it might save you some too.
// ==UserScript==
// @name ThePiHut Text Basket
// @namespace https://johnvidler.co.uk/
// @website https://johnvidler.co.uk/
// @source https://gist.github.com/JohnVidler/e57b0009391e8582ae5cf2431372d85a
// @version 2025-11-26
// @description Creates a simple copy/pasteable shopping cart to send to procurement departments for ThePiHut.com
// @author John Vidler
// @match https://thepihut.com/cart
// @icon https://www.google.com/s2/favicons?sz=64&domain=thepihut.com
// @grant none
// @require https://code.jquery.com/jquery-3.7.1.min.js
// ==/UserScript==
// USAGE: Install Tampermonkey or Greasemonkey into your browser, create a new script and drop this file's contents into it. That's it!
// When you next visit the basket page on ThePiHut you'll have an extra box under the cart total with a text-only copy of the current cart.
(function () {
'use strict';
let _copyableBOM = "";
function copyToClipboard(){
navigator.clipboard.writeText(_copyableBOM);
alert( "Copied basket to clipboard" );
}
function addButton(text, onclick, cssObj) {
cssObj = cssObj || {position: 'absolute', bottom: '7%', left:'4%', 'z-index': 3}
let button = document.createElement('button'), btnStyle = button.style
document.body.appendChild(button)
button.innerHTML = text
button.onclick = onclick
Object.keys(cssObj).forEach(key => btnStyle[key] = cssObj[key])
return button
}
function buildBOM(){
const $ = window.jQuery;
console.log("jQuery version:", $.fn.jquery);
const lines = $('.line-item');
const parts = [];
let total = 0;
for( var i=0; i<lines.length; i++ ) {
const line = lines.get(i);
const fPrice = parseFloat($(line).find('span.price--convertible').attr('data-base-amount'));
parts.push({
vendor: $(line).find('a.line-item-meta__vendor').text(),
title: $(line).find('a.line-item-meta__title').text(),
quantity: $(line).find('input.quantity-selector__input').val(),
link: "https://thepihut.com" + $(line).find('a.line-item-meta__title').attr("href"),
price: fPrice
});
total += fPrice;
}
let formattedOutput = parts.map( v => [
`(${v.quantity}x) ${v.title}`,
`\t - ${v.link}`,
`\t - Vendor: ${v.vendor}`,
`\t - £${v.price.toFixed(2)} Total (£${(v.price/v.quantity).toFixed(2)} each)`,
].join('\n') ).join("\n\n");
formattedOutput += `\n\nTotal without shipping: £${total.toFixed(2)}\n`
_copyableBOM = formattedOutput;
const newHTML = [
`<div class="cart-upsells" style='margin-top: 3rem;'>`,
`<div class="o-container">`,
`<h3 style='text-align:center;'><strong>Text-Only Basket</strong></h3>`,
"<p>Copy & Paste this to send to your procurement department, notes document, or anywhere else you might need a text-only copy of this basket.</p>",
`<p><textarea style='width:100%; height:20rem; resize:none;' wrap=false>${formattedOutput}</textarea></p>`,
"<p style='text-align: center; color: gray;'>A tiny utility by <a href='https://johnvidler.co.uk/' target='_blank'>John Vidler</a>. No association with ThePiHut implied</p>",
`</div>`,
`</div>`
];
//$('div.cart__content').append( newHTML.join('') );
$('safe-sticky.cart__aside-inner').append( newHTML.join('') );
}
// Delay slightly to allow for any lazy loading and/or net delays
setTimeout( () => buildBOM(), 100 );
})();