I'm trying to write a bookmarklet that deletes all the merged and closed branches on a Github project. The idea is that it would get the delete buttons for all the branches that are either merged or closed and trigger a click()
on them. This is what I have written:
javascript:document.querySelectorAll('span[title="Status: Merged"], span[title="Status: Closed"]').forEach(node => node.parentNode.parentNode.querySelector('.js-branch-delete-button').click())
If I run this on the branches page, it only deletes the first branch, rather than all, even though the following returns all the node ids:
document.querySelectorAll('span[title="Status: Merged"], span[title="Status: Closed"]').forEach(node => console.log(node.parentNode.parentNode.querySelector('.js-branch-delete-button').id))
Any idea why this is happening? I'm not a frontend developer so fair chances it might be something very simple but I've tried all I could think of without any luck and it only deletes the first branch rather than all of them.
It seems that when you click one delete button, it disables all other delete buttons until the deleting process is finished, so we can use MutationObserver
to wait until the currently selected delete button is not disabled, then click it. You can use this modified bookmarklet:
javascript:(async function(){
function waitTillNotDisabled(elm) {
return new Promise(resolve => {
if (!elm.disabled) {
return resolve();
}
const observer = new MutationObserver(mutations => {
if (!elm.disabled) {
resolve();
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
const deleteButtons = document.querySelectorAll('span[title="Status: Merged"], span[title="Status: Closed"]');
for (let i=0;i<deleteButtons.length;i++) {
const deleteButton = deleteButtons[i].parentNode.parentNode.querySelector('.js-branch-delete-button');
await waitTillNotDisabled(deleteButton);
deleteButton.click();
}
})();