您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Prevents page refresh when clicking Delete or Trash buttons on 8chan.moe moderation pages and handles deletions via AJAX
- // ==UserScript==
- // @name 8chan.moe Delete/Trash No Refresh
- // @namespace http://tampermonkey.net/
- // @version 2.1
- // @description Prevents page refresh when clicking Delete or Trash buttons on 8chan.moe moderation pages and handles deletions via AJAX
- // @author Anonymous
- // @match https://8chan.moe/*/res/*.html*
- // @match https://8chan.moe/mod.js?*
- // @grant none
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- console.log('8chan.moe Delete/Trash No Refresh script v2.1 loaded');
- // Function to handle button clicks and send AJAX request
- function handleButtonClick(event) {
- event.preventDefault(); // Prevent default button behavior
- event.stopPropagation(); // Stop event bubbling
- event.stopImmediatePropagation(); // Stop other handlers
- const button = event.target;
- console.log(`Clicked button: ${button.id} with value: ${button.value}`);
- // Try to find the form
- let form = button.closest('form');
- if (!form) {
- // Fallback: search for a form with deletion checkboxes
- form = document.querySelector('form input[name*="-"][name*="-"]:checked')?.closest('form') || document.querySelector('form');
- if (!form) {
- console.error('No form found in the document');
- alert('Error: No form found. Please report this issue.');
- return;
- }
- }
- console.log(`Form found: ${form.outerHTML}`);
- // Prevent form submission
- form.addEventListener('submit', (e) => {
- e.preventDefault();
- e.stopPropagation();
- console.log('Form submission prevented for form:', form);
- }, { capture: true, once: true });
- // Disable button to prevent multiple clicks
- button.disabled = true;
- setTimeout(() => { button.disabled = false; }, 500); // Re-enable after 500ms
- // Collect form data
- const formData = new FormData();
- formData.append('action', button.value); // Add the button's value (delete or trash)
- // Add checked post checkboxes (e.g., a-9-12)
- const checkedCheckboxes = form.querySelectorAll('input[name*="-"][name*="-"]:checked');
- if (checkedCheckboxes.length === 0) {
- console.error('No checked checkboxes found');
- alert('Error: No posts selected. Please check at least one post.');
- return;
- }
- checkedCheckboxes.forEach(checkbox => {
- formData.append(checkbox.name, 'true');
- console.log(`Added post checkbox: ${checkbox.name}=true`);
- });
- // Log form data for debugging
- for (const [key, value] of formData.entries()) {
- console.log(`FormData: ${key}=${value}`);
- }
- // Log form details
- console.log(`Form action attribute: ${form.getAttribute('action') || 'undefined'}`);
- console.log(`Form method: ${form.getAttribute('method') || 'undefined'}`);
- // Use the correct deletion endpoint
- const actionUrl = 'https://8chan.moe/contentActions.js?json=1';
- console.log(`Final action URL: ${actionUrl}`);
- // Send AJAX request
- fetch(actionUrl, {
- method: 'POST',
- body: formData, // Use multipart/form-data
- credentials: 'same-origin', // Include cookies for authentication
- headers: {
- 'Accept': 'application/json',
- 'X-Requested-With': 'XMLHttpRequest'
- // Omit Content-Type to let browser set multipart/form-data with boundary
- }
- })
- .then(response => {
- console.log(`Response status: ${response.status}, ok: ${response.ok}`);
- return response.json().catch(() => response.text()).then(data => ({ status: response.status, ok: response.ok, data }));
- })
- .then(({ status, ok, data }) => {
- if (ok) {
- console.log(`${button.value} action successful`, data);
- // Provide visual feedback for each checked post
- checkedCheckboxes.forEach(checkbox => {
- const postElement = checkbox.closest('.post') || checkbox.closest('.post-container') || checkbox.closest('article');
- if (postElement) {
- postElement.style.opacity = '0.5'; // Visual indication
- postElement.style.pointerEvents = 'none'; // Disable interactions
- }
- });
- } else {
- throw new Error(`Failed to ${button.value}: ${status} ${JSON.stringify(data)}`);
- }
- })
- .catch(error => {
- console.error('Error:', error);
- alert(`Error performing ${button.value} action: ${error.message}`);
- // Revert visual changes on failure
- checkedCheckboxes.forEach(checkbox => {
- const postElement = checkbox.closest('.post') || checkbox.closest('.post-container') || checkbox.closest('article');
- if (postElement) {
- postElement.style.opacity = '';
- postElement.style.pointerEvents = '';
- }
- });
- });
- }
- // Add event listeners to Delete and Trash buttons
- document.addEventListener('click', function(event) {
- if (event.target.matches('#deleteFormButton') || event.target.matches('#trashFormButton')) {
- console.log('Button click detected:', event.target.id);
- handleButtonClick(event);
- }
- }, { capture: true });
- // Prevent form submission for all forms with delete/trash buttons or checkboxes
- document.querySelectorAll('form').forEach(form => {
- if (form.querySelector('#deleteFormButton') || form.querySelector('#trashFormButton') || form.querySelector('input[name*="-"][name*="-"]')) {
- form.addEventListener('submit', (e) => {
- e.preventDefault();
- e.stopPropagation();
- console.log('Form submission blocked for form:', form);
- }, { capture: true });
- }
- });
- // Global submit prevention for safety
- document.addEventListener('submit', (e) => {
- if (e.target.querySelector('#deleteFormButton') || e.target.querySelector('#trashFormButton') || e.target.querySelector('input[name*="-"][name*="-"]')) {
- e.preventDefault();
- console.log('Global form submission blocked');
- }
- }, { capture: true });
- })();