Redbubble Delete Cart Items

Automation for deleting items from the Redbubble cart

  1. // ==UserScript==
  2. // @name Redbubble Delete Cart Items
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.5
  5. // @description Automation for deleting items from the Redbubble cart
  6. // @author YAD
  7. // @match https://www.redbubble.com/cart
  8. // @license MIT
  9. // @grant none
  10. // @icon https://www.redbubble.com/boom/public/favicons/favicon.ico
  11. // @run-at document-end
  12.  
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. const controlPanel = document.createElement('div');
  19. controlPanel.style.position = 'fixed';
  20. controlPanel.style.backgroundColor = '#ff596f';
  21. controlPanel.style.border = '1px solid #ccc';
  22. controlPanel.style.borderRadius = '8px';
  23. controlPanel.style.padding = '10px';
  24. controlPanel.style.boxShadow = '0 2px 10px rgba(0,0,0,0.1)';
  25. controlPanel.style.zIndex = 1000;
  26. controlPanel.style.cursor = 'move';
  27. controlPanel.style.transition = 'transform 0.2s';
  28.  
  29. const deleteCountDisplay = document.createElement('div');
  30. deleteCountDisplay.id = 'delete-count';
  31. deleteCountDisplay.style.fontSize = '16px';
  32. deleteCountDisplay.style.marginBottom = '10px';
  33. deleteCountDisplay.innerHTML = 'Items Deleted: <span id="count">0</span>';
  34.  
  35. const inputContainer = document.createElement('div');
  36. inputContainer.style.marginBottom = '10px';
  37.  
  38. const itemCountInput = document.createElement('input');
  39. itemCountInput.type = 'number';
  40. itemCountInput.id = 'item-count';
  41. itemCountInput.placeholder = 'Number of items to delete';
  42. itemCountInput.style.marginRight = '10px';
  43. itemCountInput.style.width = '150px';
  44.  
  45. const deleteAllCheckbox = document.createElement('input');
  46. deleteAllCheckbox.type = 'checkbox';
  47. deleteAllCheckbox.id = 'delete-all';
  48. deleteAllCheckbox.style.marginRight = '5px';
  49.  
  50. const deleteAllLabel = document.createElement('label');
  51. deleteAllLabel.setAttribute('for', 'delete-all');
  52. deleteAllLabel.textContent = 'Delete All';
  53.  
  54. inputContainer.appendChild(itemCountInput);
  55. inputContainer.appendChild(deleteAllCheckbox);
  56. inputContainer.appendChild(deleteAllLabel);
  57.  
  58. const controlButton = document.createElement('button');
  59. controlButton.id = 'control-button';
  60. controlButton.style.backgroundColor = '#e91e63';
  61. controlButton.style.color = '#fff';
  62. controlButton.style.border = 'none';
  63. controlButton.style.borderRadius = '4px';
  64. controlButton.style.padding = '5px 10px';
  65. controlButton.style.cursor = 'pointer';
  66. controlButton.textContent = 'Start';
  67.  
  68. controlPanel.appendChild(deleteCountDisplay);
  69. controlPanel.appendChild(inputContainer);
  70. controlPanel.appendChild(controlButton);
  71.  
  72. document.body.appendChild(controlPanel);
  73.  
  74. const savedPosition = JSON.parse(localStorage.getItem('controlPanelPosition'));
  75. if (savedPosition) {
  76. controlPanel.style.top = savedPosition.top || '10px';
  77. controlPanel.style.left = savedPosition.left || '10px';
  78. } else {
  79. controlPanel.style.top = '50%';
  80. controlPanel.style.left = 'calc(100% - 220px)';
  81. controlPanel.style.transform = 'translateY(-50%)';
  82. }
  83.  
  84. function savePosition() {
  85. localStorage.setItem('controlPanelPosition', JSON.stringify({
  86. top: controlPanel.style.top,
  87. left: controlPanel.style.left
  88. }));
  89. }
  90.  
  91. let isDragging = false;
  92. let offsetX, offsetY;
  93. let isDraggingDisabled = false;
  94.  
  95. controlPanel.addEventListener('mousedown', (e) => {
  96. if (isDraggingDisabled) return;
  97. isDragging = true;
  98. offsetX = e.clientX - controlPanel.getBoundingClientRect().left;
  99. offsetY = e.clientY - controlPanel.getBoundingClientRect().top;
  100. controlPanel.style.cursor = 'grabbing';
  101. });
  102.  
  103. document.addEventListener('mousemove', (e) => {
  104. if (isDragging) {
  105. controlPanel.style.top = `${e.clientY - offsetY}px`;
  106. controlPanel.style.left = `${e.clientX - offsetX}px`;
  107. savePosition();
  108. }
  109. });
  110.  
  111. document.addEventListener('mouseup', () => {
  112. isDragging = false;
  113. controlPanel.style.cursor = 'move';
  114. });
  115.  
  116. let isPaused = false;
  117.  
  118. function deleteItems() {
  119. const deleteButtons = document.querySelectorAll('button[aria-label="Show remove confirmation button"]');
  120. const confirmButtons = document.querySelectorAll('button.LineItem_removeConfirmBtn__CZE_0');
  121. const totalButtons = deleteButtons.length;
  122.  
  123. if (totalButtons === 0) {
  124. alert('No items found to delete.');
  125. return;
  126. }
  127.  
  128. let deleteCount = 0;
  129. let maxDeleteCount = parseInt(itemCountInput.value) || totalButtons;
  130.  
  131. if (deleteAllCheckbox.checked) {
  132. maxDeleteCount = totalButtons;
  133. }
  134.  
  135. function deleteNext() {
  136. if (isPaused) return;
  137. if (deleteCount >= maxDeleteCount || deleteCount >= totalButtons) {
  138. controlButton.textContent = 'Start';
  139. isDraggingDisabled = false;
  140. return;
  141. }
  142.  
  143. const deleteButton = deleteButtons[deleteCount];
  144. if (!deleteButton) {
  145. console.error('Delete button not found for index:', deleteCount);
  146. return;
  147. }
  148. deleteButton.click();
  149.  
  150. setTimeout(() => {
  151. const confirmButton = confirmButtons[deleteCount];
  152. if (confirmButton) {
  153. confirmButton.click();
  154. deleteCount++;
  155. document.getElementById('count').textContent = deleteCount;
  156. deleteNext();
  157. } else {
  158. console.error('Confirm button not found for index:', deleteCount);
  159. }
  160. }, 100);
  161. }
  162.  
  163. deleteNext();
  164. }
  165.  
  166. controlButton.addEventListener('click', () => {
  167. if (controlButton.textContent === 'Start') {
  168. isPaused = false;
  169. isDraggingDisabled = true;
  170. controlButton.textContent = 'Pause';
  171. deleteItems();
  172. } else if (controlButton.textContent === 'Pause') {
  173. isPaused = !isPaused;
  174. controlButton.textContent = isPaused ? 'Resume' : 'Pause';
  175. } else if (controlButton.textContent === 'Resume') {
  176. isPaused = false;
  177. controlButton.textContent = 'Pause';
  178. deleteItems();
  179. }
  180. });
  181.  
  182. document.addEventListener('mouseup', () => {
  183. if (controlButton.textContent === 'Resume') {
  184. isDraggingDisabled = false;
  185. }
  186. });
  187.  
  188. })();