JavaScript: AI-generated bookmarklet, code and thoughts
I've been avoiding using AI for a while now, but this one time, I didn't have the time or the expertise available to me, so I reached for a LLM.
I needed to scrape something off a web page, but as is typical these days, the website is a JavaScript-fueled labyrinth of nested tags, odd class names, and HTML that is hard to read. In the past, I would have bashed through and did rounds upon rounds of trial and error until I got the result I wanted, but I didn't have the time this time. I also had not touched JavaScript is probably a year.
What I wanted to do was to compose some JavaScript into a bookmarklet that I can click to scrape the HTMl, compose a handy table, and put it into my system clipboard.
I had heard that Claude is good for coding, so I went on and gave it a shot. I told it what I wanted to do, fed it the entire HTML page, and iterated with it until I got to my final solution.
It turns out that I had just enough free messages to arrive at a solution!
Some notes, mostly to justify to myself that my knowledge is not redudant:
- I needed to know what I was reading. Claude wrote the bulk of the code for me, but for example, it picked up on the wrong class name and I had to correct it.
- I had to know what solution direction I wanted. I needed to tell it to give me JavaScript code in a bookmarklet. I don't know if it would have suggested that otherwise.
- I used it because I write JavaScript so infrequently these days and some of the techniques required (even small things like boomarklet syntax) is a bit out of reach
Anyway, this is the code that Claude made for me. In the real bookmarklet, all this code is all together in one line, no spaces.
javascript:(
function(){
function parseCompetitionResults(){
let csvOutput = 'Place,Name,Club,Event\r\n';
document
.querySelectorAll('.result')
.forEach( division => {
const eventElement = division.querySelector('h2');
const event = eventElement ? eventElement.textContent.trim().replace(/\s*<!---->\s*$/,'') : 'Unknown Event';
division
.querySelectorAll('.clearfix')
.forEach( row => {
const placeElement = row.querySelector('.place');
const place = placeElement ? placeElement.textContent.trim() : '';
const nameElement = row.querySelector('.name a')||row.querySelector('.name div');
const name = nameElement ? nameElement.textContent.trim().replace(/\s*\n.*$/,'').replace(/,/g,'') : '';
const clubElement = row.querySelector('.club');
const club = clubElement ? clubElement.textContent.trim().replace(/,/g,'') : '';
if(place&&name&&club){csvOutput+ = `${place},${name},${club},${event}\r\n`}
} )
} );
const tempTextArea = document.createElement('textarea');
tempTextArea.value = csvOutput;
document.body.appendChild(tempTextArea);
tempTextArea.select();
try{
if(navigator.clipboard){
navigator.clipboard.writeText(csvOutput).then(() => {alert('Competition results copied to clipboard!')}).catch(err => {document.execCommand('copy');
alert('Competition results copied to clipboard!')})
} else {
document.execCommand('copy');
alert('Competition results copied to clipboard!')
};
}
catch (err) {
alert('Failed to copy results to clipboard');
}
finally{
document.body.removeChild(tempTextArea)
}
}
parseCompetitionResults()
}
)();