// ==UserScript==
// @name F95 Template Maker
// @namespace https://f95zone.to
// @version 1.0
// @description Creates a template for F95Zone
// @match https://*.f95zone.to/*
// @grant GM_setClipboard
// @author Ryahn
// @require https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js
// @resource CHOICES_CSS https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css
// @grant GM_addStyle
// @grant GM_getResourceText
// ==/UserScript==
(function() {
'use strict';
const tags = {
technical: [
'3D Game', '3DCG', '2D Game',
'2DCG', 'AI CG', 'Animated',
'Censored', 'Character Creation',
'Kinetic Novel', 'Japanese Game',
'Male Porn', 'Male Protagonist',
'Mobile Game', 'Female Protagonist',
'Futa/Trans Protagonist', 'Multiple Protagonists',
'Multiple Endings', 'Real Porn', 'Text Based',
'Virtual Reality', 'Voiced'
],
sexual: [
'Anal Sex',
'Ahegao',
'Bdsm',
'Bestiality',
'Big Ass',
'Big Tits',
'Blackmail',
'Bukkake',
'Cheating',
'Corruption',
'Creampie',
'Dilf',
'Drugs',
'Exhibitionism',
'Female domination',
'Footjob',
'Furry',
'Futa/Trans',
'Gay',
'Group sex',
'Groping',
'Handjob',
'Harem',
'Humiliation',
'Incest',
'Internal view',
'Interracial',
'Lactation',
'Lesbian',
'Loli',
'Male Domination',
'Masturbation',
'Milf',
'Multiple Penetration',
'Necrophilia',
'Netorare',
'Oral Sex',
'Pregnancy',
'Prostitution',
'Rape',
'Scat',
'Sex Toys',
'Sexual Harassment',
'Shota',
'Sissification',
'Slave',
'Sleep Sex',
'Spanking',
'Stripping',
'Swinging',
'Tentacles',
'Teasing',
'Titfuck',
'Transformation',
'Trap',
'Urination',
'Vaginal sex',
'Virgin',
'Vore',
'Voyeurism'
],
nosex: [
'Adventure',
'Combat',
'Cosplay',
'Dating Sim',
'Dystopian setting',
'Fantasy',
'Graphic violence',
'Horror',
'Humor',
'Management',
'Mind control',
'Monster',
'Monster Girl',
'No Sexual Content',
'Paranormal',
'Parody',
'Platformer',
'Point & Click',
'Possession',
'PoV',
'Puzzle',
'Religion',
'Romance',
'Rpg',
'Sandbox',
'School setting',
'Sci-fi',
'Shooter',
'Side-scroller',
'Simulator',
'Strategy',
'Superpowers',
'Trainer',
'Turn based combat',
'Twins'
],
other: [
'Asset-addon',
'Asset-ai-shoujo',
'Asset-animal',
'Asset-animation',
'Asset-audio',
'Asset-bundle',
'Asset-character',
'Asset-clothing',
'Asset-daz-gen1',
'Asset-daz-gen2',
'Asset-daz-gen3',
'Asset-daz-gen8',
'Asset-daz-gen81',
'Asset-daz-gen9',
'Asset-daz-m4',
'Asset-daz-v4',
'Asset-environment',
'Asset-expression',
'Asset-female',
'Asset-hair',
'Asset-hdri',
'Asset-honey-select',
'Asset-honey-select2',
'Asset-koikatu',
'Asset-light',
'Asset-male',
'Asset-morph',
'Asset-nonbinary',
'Asset-playclub',
'Asset-plugin',
'Asset-pose',
'Asset-prop',
'Asset-scene',
'Asset-script',
'Asset-shader',
'Asset-texture',
'Asset-utility',
'Asset-vehicle'
]
};
const operatingSystem = [
'Win', 'Linux', 'Mac', 'Android', 'iOS', 'All'
];
const language = [
'English', 'Japanese', 'Chinese', 'Korean', 'Russian', 'Spanish', 'French', 'German', 'Italian', 'Portuguese', 'Turkish', 'Polish', 'Romanian', 'Dutch', 'Other'
];
// Create and append the button immediately instead of waiting for DOMContentLoaded
const button = document.createElement("button");
button.textContent = "Template Maker";
button.style.position = "fixed";
button.style.top = "135px"; // Match ruleselect.js positioning
button.style.right = "10px";
button.style.zIndex = "9999"; // Match ruleselect.js z-index
button.style.padding = "10px";
button.style.backgroundColor = "#1e66a5";
button.style.color = "#fff";
button.style.border = "none";
button.style.borderRadius = "5px"; // Match ruleselect.js border-radius
button.style.cursor = "pointer";
// Add button to page immediately
document.body.appendChild(button);
let isPopupOpen = false;
let popup, overlay;
// Add click handler
button.addEventListener("click", () => {
if (isPopupOpen) {
closePopup();
} else {
createPopup();
}
});
// Popup function
function createPopup() {
overlay = document.createElement("div");
overlay.style.position = 'fixed';
overlay.style.top = '0';
overlay.style.left = '0';
overlay.style.width = '100vw';
overlay.style.height = '100vh';
overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
overlay.style.zIndex = '9998';
popup = document.createElement("div");
popup.style.position = "fixed";
popup.style.top = "20%";
popup.style.left = "50%";
popup.style.transform = "translate(-50%, -20%)";
popup.style.padding = "20px";
popup.style.backgroundColor = "#333";
popup.style.border = "1px solid #555";
popup.style.borderRadius = "8px";
popup.style.zIndex = "10000";
popup.style.width = "100%";
popup.style.color = "#fff";
popup.style.boxShadow = "0px 4px 8px rgba(0, 0, 0, 0.2)";
// Create form container first
const formContainer = document.createElement("div");
formContainer.id = "templateForm";
// Update form container styling
formContainer.style.display = "flex";
formContainer.style.flexDirection = "column";
formContainer.style.gap = "20px";
formContainer.style.width = "100%";
// Create formContent container
const formContent = document.createElement("div");
formContent.className = "form-content";
formContent.style.display = "grid";
formContent.style.gridTemplateColumns = "repeat(12, 1fr)";
formContent.style.gap = "15px";
formContent.style.padding = "20px";
formContent.style.backgroundColor = "#242629";
formContent.style.borderRadius = "8px";
formContent.style.border = "1px solid #343638";
formContent.style.maxHeight = "80vh";
formContent.style.overflowY = "auto";
// Update section styling
const sectionStyle = {
marginBottom: "30px",
gridColumn: "span 12",
display: "grid",
gap: "15px",
backgroundColor: "#242629",
padding: "20px",
borderRadius: "8px",
border: "1px solid #343638"
};
// Create sections container
const generalSection = document.createElement("div");
Object.assign(generalSection.style, sectionStyle);
// General Info Header
const generalInfoHeader = document.createElement("h4");
createHeaderStyle(generalInfoHeader, "General Info");
const generalInfoDesc = document.createElement("p");
createDescStyle(generalInfoDesc, "The important stuff");
// Add elements to general section
generalSection.appendChild(generalInfoHeader);
generalSection.appendChild(generalInfoDesc);
// Overview Field
const overviewCol = document.createElement("div");
overviewCol.className = "col-xl-12";
overviewCol.style.display = "flex";
overviewCol.style.flexDirection = "column";
overviewCol.style.gap = "10px";
const overviewLabel = document.createElement("label");
overviewLabel.className = "form-label";
overviewLabel.htmlFor = "overview";
overviewLabel.textContent = "Overview";
overviewLabel.style.color = "#fff";
overviewLabel.style.marginBottom = "0";
const overviewInput = document.createElement("textarea");
overviewInput.className = "form-control";
overviewInput.id = "overview";
overviewInput.name = "overview";
overviewInput.rows = "3";
overviewInput.placeholder = "Enter game overview";
overviewInput.style.backgroundColor = "#242629";
overviewInput.style.color = "#fff";
overviewInput.style.border = "1px solid #343638";
overviewInput.style.borderRadius = "4px";
overviewInput.style.padding = "8px 12px";
overviewInput.style.marginTop = "0";
overviewCol.appendChild(overviewLabel);
overviewCol.appendChild(overviewInput);
// Thread Updated Date
const threadUpdatedCol = document.createElement("div");
threadUpdatedCol.className = "col-xl-4";
threadUpdatedCol.id = "thread_updatedShow";
const threadUpdatedGroup = document.createElement("div");
threadUpdatedGroup.className = "mb-3";
const threadUpdatedLabel = document.createElement("label");
threadUpdatedLabel.className = "form-label";
threadUpdatedLabel.htmlFor = "thread_updated";
threadUpdatedLabel.textContent = "Thread Updated";
threadUpdatedLabel.style.color = "#fff";
const threadUpdatedInput = document.createElement("input");
threadUpdatedInput.type = "text";
threadUpdatedInput.className = "form-control";
threadUpdatedInput.id = "thread_updated";
threadUpdatedInput.name = "thread_updated";
threadUpdatedInput.placeholder = "yyyy-mm-dd";
threadUpdatedInput.style.backgroundColor = "#444";
threadUpdatedInput.style.color = "#fff";
threadUpdatedInput.style.border = "1px solid #555";
threadUpdatedGroup.appendChild(threadUpdatedLabel);
threadUpdatedGroup.appendChild(threadUpdatedInput);
threadUpdatedCol.appendChild(threadUpdatedGroup);
// Release Date
const releaseDateCol = document.createElement("div");
releaseDateCol.className = "col-xl-4";
releaseDateCol.id = "releaseDateShow";
const releaseDateGroup = document.createElement("div");
releaseDateGroup.className = "mb-3";
const releaseDateLabel = document.createElement("label");
releaseDateLabel.className = "form-label";
releaseDateLabel.textContent = "Release Date";
releaseDateLabel.style.color = "#fff";
const releaseDateInput = document.createElement("input");
releaseDateInput.type = "text";
releaseDateInput.className = "form-control";
releaseDateInput.id = "release_date";
releaseDateInput.name = "release_date";
releaseDateInput.placeholder = "yyyy-mm-dd";
releaseDateInput.style.backgroundColor = "#444";
releaseDateInput.style.color = "#fff";
releaseDateInput.style.border = "1px solid #555";
releaseDateGroup.appendChild(releaseDateLabel);
releaseDateGroup.appendChild(releaseDateInput);
releaseDateCol.appendChild(releaseDateGroup);
// Censorship Dropdown
const censorshipCol = document.createElement("div");
censorshipCol.className = "col-xl-4";
censorshipCol.id = "censorsipShow";
const censorshipGroup = document.createElement("div");
censorshipGroup.className = "mb-3";
const censorshipLabel = document.createElement("label");
censorshipLabel.className = "form-label";
censorshipLabel.textContent = "Censorship";
censorshipLabel.style.color = "#fff";
const censorshipSelect = document.createElement("select");
censorshipSelect.className = "form-select";
censorshipSelect.id = "censorsip";
censorshipSelect.name = "censorship";
censorshipSelect.style.backgroundColor = "#242629";
censorshipSelect.style.color = "#fff";
censorshipSelect.style.border = "1px solid #343638";
censorshipSelect.style.width = "100%";
censorshipSelect.style.padding = "8px 12px";
censorshipSelect.style.borderRadius = "4px";
const censorshipOptions = [
{value: "", text: ""},
{value: "1", text: "Yes - Mosaics"},
{value: "2", text: "Yes - Patch w/ Mosaics"},
{value: "3", text: "Yes - Patch w/o Mosaics"},
{value: "4", text: "No"},
{value: "5", text: "No Sexual Content"}
];
censorshipOptions.forEach(option => {
const optionElement = document.createElement("option");
optionElement.value = option.value;
optionElement.textContent = option.text;
censorshipSelect.appendChild(optionElement);
});
censorshipGroup.appendChild(censorshipLabel);
censorshipGroup.appendChild(censorshipSelect);
censorshipCol.appendChild(censorshipGroup);
// Genre Multiselect
const genreCol = document.createElement("div");
genreCol.className = "col-xl-4";
genreCol.id = "genreShow";
const genreGroup = document.createElement("div");
genreGroup.className = "mb-3";
const genreLabel = document.createElement("label");
genreLabel.className = "form-label";
genreLabel.textContent = "Genre";
genreLabel.style.color = "#fff";
const genreSelect = document.createElement("select");
genreSelect.className = "form-select";
genreSelect.id = "genre";
genreSelect.name = "genre[]";
genreSelect.multiple = true;
// Add options from tags object
Object.entries(tags).forEach(([category, items]) => {
const group = document.createElement("optgroup");
group.label = category.charAt(0).toUpperCase() + category.slice(1);
items.forEach(item => {
const option = document.createElement("option");
option.value = item;
option.textContent = item;
group.appendChild(option);
});
genreSelect.appendChild(group);
});
genreGroup.appendChild(genreLabel);
genreGroup.appendChild(genreSelect);
genreCol.appendChild(genreGroup);
// Initialize Choices.js
new Choices(genreSelect, {
removeItemButton: true,
searchEnabled: true,
searchPlaceholderValue: "Search genres...",
placeholder: true,
placeholderValue: "Select genres",
classNames: {
containerOuter: 'choices',
containerInner: 'choices__inner',
input: 'choices__input',
inputCloned: 'choices__input--cloned',
list: 'choices__list',
listItems: 'choices__list--multiple',
listSingle: 'choices__list--single',
listDropdown: 'choices__list--dropdown',
item: 'choices__item',
itemSelectable: 'choices__item--selectable',
itemDisabled: 'choices__item--disabled',
itemChoice: 'choices__item--choice',
placeholder: 'choices__placeholder',
group: 'choices__group',
groupHeading: 'choices__heading',
button: 'choices__button',
}
});
// Game Name Field
const gameNameCol = document.createElement("div");
gameNameCol.className = "col-xl-12";
const gameNameGroup = document.createElement("div");
gameNameGroup.className = "form-group mb-3";
const gameNameLabel = document.createElement("label");
gameNameLabel.className = "form-label";
gameNameLabel.htmlFor = "game_name";
gameNameLabel.textContent = "Game Name";
gameNameLabel.style.color = "#fff";
const gameNameInput = document.createElement("input");
gameNameInput.type = "text";
gameNameInput.className = "form-control";
gameNameInput.id = "game_name";
gameNameInput.name = "game_name";
gameNameInput.style.backgroundColor = "#444";
gameNameInput.style.color = "#fff";
gameNameInput.style.border = "1px solid #555";
gameNameGroup.appendChild(gameNameLabel);
gameNameGroup.appendChild(gameNameInput);
gameNameCol.appendChild(gameNameGroup);
// Developer Name Field
const devCol = document.createElement("div");
devCol.className = "col-xl-6";
const devGroup = document.createElement("div");
devGroup.className = "form-group mb-3";
const devLabel = document.createElement("label");
devLabel.className = "form-label";
devLabel.htmlFor = "devName";
devLabel.textContent = "Developer Name";
devLabel.style.color = "#fff";
const devInput = document.createElement("input");
devInput.type = "text";
devInput.className = "form-control";
devInput.id = "devName";
devInput.name = "devName";
devInput.style.backgroundColor = "#444";
devInput.style.color = "#fff";
devInput.style.border = "1px solid #555";
devGroup.appendChild(devLabel);
devGroup.appendChild(devInput);
devCol.appendChild(devGroup);
// Version Field
const versionCol = document.createElement("div");
versionCol.className = "col-xl-6";
versionCol.id = "versionShow";
const versionGroup = document.createElement("div");
versionGroup.className = "form-group mb-3";
const versionLabel = document.createElement("label");
versionLabel.className = "form-label";
versionLabel.htmlFor = "version";
versionLabel.textContent = "Version";
versionLabel.style.color = "#fff";
const versionInput = document.createElement("input");
versionInput.type = "text";
versionInput.className = "form-control";
versionInput.id = "version";
versionInput.name = "version";
versionInput.style.backgroundColor = "#444";
versionInput.style.color = "#fff";
versionInput.style.border = "1px solid #555";
versionGroup.appendChild(versionLabel);
versionGroup.appendChild(versionInput);
versionCol.appendChild(versionGroup);
// Dev Links Field
const devLinksCol = document.createElement("div");
devLinksCol.className = "col-xl-6";
const devLinksGroup = document.createElement("div");
devLinksGroup.className = "form-group mb-3";
const devLinksLabel = document.createElement("label");
devLinksLabel.className = "form-label";
devLinksLabel.htmlFor = "devLinks";
devLinksLabel.textContent = "Dev Links";
devLinksLabel.style.color = "#fff";
const devLinksInput = document.createElement("input");
devLinksInput.type = "text";
devLinksInput.className = "form-control";
devLinksInput.id = "devLinks";
devLinksInput.name = "devLinks";
devLinksInput.style.backgroundColor = "#444";
devLinksInput.style.color = "#fff";
devLinksInput.style.border = "1px solid #555";
const devLinksHelp = document.createElement("small");
devLinksHelp.className = "form-text text-muted";
devLinksHelp.innerHTML = 'Format: SiteName|url,Sitename|url';
devLinksGroup.appendChild(devLinksLabel);
devLinksGroup.appendChild(devLinksInput);
devLinksGroup.appendChild(devLinksHelp);
devLinksCol.appendChild(devLinksGroup);
// Translator Field
const translatorCol = document.createElement("div");
translatorCol.className = "col-xl-6";
const translatorGroup = document.createElement("div");
translatorGroup.className = "form-group mb-3";
const translatorLabel = document.createElement("label");
translatorLabel.className = "form-label";
translatorLabel.htmlFor = "translator";
translatorLabel.textContent = "Translator";
translatorLabel.style.color = "#fff";
const translatorInput = document.createElement("input");
translatorInput.type = "text";
translatorInput.className = "form-control";
translatorInput.id = "translator";
translatorInput.name = "translator";
translatorInput.style.backgroundColor = "#444";
translatorInput.style.color = "#fff";
translatorInput.style.border = "1px solid #555";
const translatorHelp = document.createElement("small");
translatorHelp.className = "form-text text-muted";
translatorHelp.innerHTML = 'Name of translator';
translatorGroup.appendChild(translatorLabel);
translatorGroup.appendChild(translatorInput);
translatorGroup.appendChild(translatorHelp);
translatorCol.appendChild(translatorGroup);
// Translator Links Field
const translatorLinksCol = document.createElement("div");
translatorLinksCol.className = "col-xl-6";
const translatorLinksGroup = document.createElement("div");
translatorLinksGroup.className = "form-group mb-3";
const translatorLinksLabel = document.createElement("label");
translatorLinksLabel.className = "form-label";
translatorLinksLabel.htmlFor = "translatorLinks";
translatorLinksLabel.textContent = "Translator Links";
translatorLinksLabel.style.color = "#fff";
const translatorLinksInput = document.createElement("input");
translatorLinksInput.type = "text";
translatorLinksInput.className = "form-control";
translatorLinksInput.id = "translatorLinks";
translatorLinksInput.name = "translatorLinks";
translatorLinksInput.style.backgroundColor = "#444";
translatorLinksInput.style.color = "#fff";
translatorLinksInput.style.border = "1px solid #555";
const translatorLinksHelp = document.createElement("small");
translatorLinksHelp.className = "form-text text-muted";
translatorLinksHelp.innerHTML = 'Format: SiteName|url,Sitename|url';
translatorLinksGroup.appendChild(translatorLinksLabel);
translatorLinksGroup.appendChild(translatorLinksInput);
translatorLinksGroup.appendChild(translatorLinksHelp);
translatorLinksCol.appendChild(translatorLinksGroup);
// Store Links Field
const storeCol = document.createElement("div");
storeCol.className = "col-xl-6";
const storeGroup = document.createElement("div");
storeGroup.className = "form-group mb-3";
const storeLabel = document.createElement("label");
storeLabel.className = "form-label";
storeLabel.htmlFor = "store";
storeLabel.textContent = "Store Links";
storeLabel.style.color = "#fff";
const storeInput = document.createElement("input");
storeInput.type = "text";
storeInput.className = "form-control";
storeInput.id = "store";
storeInput.name = "store";
storeInput.style.backgroundColor = "#444";
storeInput.style.color = "#fff";
storeInput.style.border = "1px solid #555";
const storeHelp = document.createElement("small");
storeHelp.className = "form-text text-muted";
storeHelp.innerHTML = 'Format: Store Name|url,Store Name|url';
storeGroup.appendChild(storeLabel);
storeGroup.appendChild(storeInput);
storeGroup.appendChild(storeHelp);
storeCol.appendChild(storeGroup);
// After creating generalSection and adding the header elements, add all the general info fields:
generalSection.appendChild(overviewCol);
generalSection.appendChild(gameNameCol);
generalSection.appendChild(threadUpdatedCol);
generalSection.appendChild(releaseDateCol);
generalSection.appendChild(censorshipCol);
generalSection.appendChild(genreCol);
generalSection.appendChild(devCol);
generalSection.appendChild(versionCol);
generalSection.appendChild(devLinksCol);
generalSection.appendChild(translatorCol);
generalSection.appendChild(translatorLinksCol);
generalSection.appendChild(storeCol);
// Notes Section
const notesSection = document.createElement("div");
Object.assign(notesSection.style, sectionStyle);
const notesHeader = document.createElement("h4");
createHeaderStyle(notesHeader, "Notes");
const notesDesc = document.createElement("p");
createDescStyle(notesDesc, "Notes & Stuff");
notesSection.appendChild(notesHeader);
notesSection.appendChild(notesDesc);
// Installation Field
const installationCol = document.createElement("div");
installationCol.className = "col-xl-12";
installationCol.id = "installShow";
const installationGroup = document.createElement("div");
installationGroup.className = "form-group mb-3";
const installationLabel = document.createElement("label");
installationLabel.className = "form-label";
installationLabel.htmlFor = "installation";
installationLabel.textContent = "Installation";
installationLabel.style.color = "#fff";
const installationInput = document.createElement("textarea");
installationInput.className = "form-control";
installationInput.id = "installation";
installationInput.name = "installation";
installationInput.rows = "3";
installationInput.placeholder = "sam is always watching";
installationInput.style.backgroundColor = "#444";
installationInput.style.color = "#fff";
installationInput.style.border = "1px solid #555";
installationGroup.appendChild(installationLabel);
installationGroup.appendChild(installationInput);
installationCol.appendChild(installationGroup);
// Changelog Field
const changelogCol = document.createElement("div");
changelogCol.className = "col-xl-12";
changelogCol.id = "changelogShow";
const changelogGroup = document.createElement("div");
changelogGroup.className = "form-group mb-3";
const changelogLabel = document.createElement("label");
changelogLabel.className = "form-label";
changelogLabel.htmlFor = "changelog";
changelogLabel.textContent = "Changelog";
changelogLabel.style.color = "#fff";
const changelogInput = document.createElement("textarea");
changelogInput.className = "form-control";
changelogInput.id = "changelog";
changelogInput.name = "changelog";
changelogInput.rows = "3";
changelogInput.placeholder = "Alexander Krisnov is russia";
changelogInput.style.backgroundColor = "#444";
changelogInput.style.color = "#fff";
changelogInput.style.border = "1px solid #555";
changelogGroup.appendChild(changelogLabel);
changelogGroup.appendChild(changelogInput);
changelogCol.appendChild(changelogGroup);
// Dev Notes Field
const devNotesCol = document.createElement("div");
devNotesCol.className = "col-xl-12";
devNotesCol.id = "devNotesShow";
const devNotesGroup = document.createElement("div");
devNotesGroup.className = "form-group mb-3";
const devNotesLabel = document.createElement("label");
devNotesLabel.className = "form-label";
devNotesLabel.htmlFor = "devNotes";
devNotesLabel.textContent = "Dev Notes";
devNotesLabel.style.color = "#fff";
const devNotesInput = document.createElement("textarea");
devNotesInput.className = "form-control";
devNotesInput.id = "devNotes";
devNotesInput.name = "devNotes";
devNotesInput.rows = "3";
devNotesInput.placeholder = "rf46 FBI is looking for you";
devNotesInput.style.backgroundColor = "#444";
devNotesInput.style.color = "#fff";
devNotesInput.style.border = "1px solid #555";
devNotesGroup.appendChild(devNotesLabel);
devNotesGroup.appendChild(devNotesInput);
devNotesCol.appendChild(devNotesGroup);
// After creating notesSection and adding the header elements, add all the notes fields:
notesSection.appendChild(installationCol);
notesSection.appendChild(changelogCol);
notesSection.appendChild(devNotesCol);
// Make BBCode Button
const makeBBCodeButton = document.createElement("button");
makeBBCodeButton.className = "btn btn-outline-theme btn-lg d-block w-100 fw-500 mb-3";
makeBBCodeButton.id = "makeBBcode";
makeBBCodeButton.textContent = "Make";
makeBBCodeButton.style.backgroundColor = "#444";
makeBBCodeButton.style.color = "#fff";
makeBBCodeButton.style.border = "1px solid #555";
makeBBCodeButton.style.width = "100%";
makeBBCodeButton.style.padding = "10px";
makeBBCodeButton.style.marginBottom = "15px";
makeBBCodeButton.style.cursor = "pointer";
// Then add both sections and the make button to formContent:
formContent.appendChild(generalSection);
formContent.appendChild(notesSection);
formContent.appendChild(makeBBCodeButton);
// Update column spans and gaps
[overviewCol, gameNameCol].forEach(col => {
col.style.gridColumn = "span 12";
col.style.marginBottom = "15px";
});
[devCol, versionCol, devLinksCol, translatorCol, translatorLinksCol, storeCol].forEach(col => {
col.style.gridColumn = "span 6";
col.style.marginBottom = "15px";
});
[threadUpdatedCol, releaseDateCol, censorshipCol, genreCol].forEach(col => {
col.style.gridColumn = "span 3";
col.style.marginBottom = "15px";
});
[installationCol, changelogCol, devNotesCol].forEach(col => {
col.style.gridColumn = "span 12";
col.style.marginBottom = "15px";
});
// Style form groups
const formGroups = document.querySelectorAll('.form-group, .mb-3');
formGroups.forEach(group => {
group.style.display = "flex";
group.style.flexDirection = "column";
group.style.gap = "10px";
group.style.marginBottom = "15px";
group.style.width = "100%";
});
// Style labels
const labels = document.querySelectorAll('.form-label');
labels.forEach(label => {
label.style.color = "#fff";
label.style.fontSize = "14px";
label.style.fontWeight = "600";
label.style.marginBottom = "0";
label.style.display = "block";
label.style.width = "100%";
});
// Style inputs
const inputs = document.querySelectorAll('input, select, textarea');
inputs.forEach(input => {
input.style.width = "100%";
input.style.padding = "8px 12px";
input.style.backgroundColor = "#242629";
input.style.border = "1px solid #343638";
input.style.borderRadius = "4px";
input.style.color = "#fff";
input.style.fontSize = "14px";
input.style.lineHeight = "1.4";
input.style.marginTop = "0";
});
// Style help texts
const helpTexts = document.querySelectorAll('.form-text');
helpTexts.forEach(help => {
help.style.marginTop = "5px";
help.style.fontSize = "12px";
help.style.color = "#999";
help.style.width = "100%";
});
// Make sure the form container is added to popup first
popup.appendChild(formContainer);
formContainer.appendChild(formContent);
// THEN add the titles and buttons AFTER the form
// Popup title
const title = document.createElement("h3");
title.textContent = "Select Broken Rules";
title.style.width = "100%";
title.style.marginBottom = "5px";
title.style.color = "#fff";
popup.appendChild(title);
const linksTitle = document.createElement("h3");
linksTitle.textContent = "Rule Links";
linksTitle.style.width = "100%";
linksTitle.style.marginBottom = "5px";
linksTitle.style.color = "#fff";
popup.appendChild(linksTitle);
// Button container
const buttonContainer = document.createElement("div");
buttonContainer.style.display = "flex";
buttonContainer.style.justifyContent = "space-between";
buttonContainer.style.marginTop = "15px";
popup.appendChild(buttonContainer);
// Left-aligned buttons container
const leftButtonRow = document.createElement("div");
leftButtonRow.style.display = "flex";
leftButtonRow.style.gap = "10px"; // Space between buttons on the left
buttonContainer.appendChild(leftButtonRow);
// Rule buttons
const generalRules = document.createElement("button");
generalRules.textContent = "General";
generalRules.style.marginTop = "15px";
generalRules.style.padding = "8px 12px";
generalRules.style.backgroundColor = "#ba4545";
generalRules.style.color = "#fff";
generalRules.style.border = "none";
generalRules.style.borderRadius = "4px";
generalRules.style.cursor = "pointer";
generalRules.style.alignSelf = "center";
generalRules.style.height = "35px";
leftButtonRow.appendChild(generalRules);
generalRules.addEventListener("click", () => {
window.location.href = "https://f95zone.to/threads/general-rules-updated-2024-06-04.5589/";
closePopup();
});
generalRules.addEventListener("mouseover", () => {
generalRules.style.backgroundColor = "#9e3838";
});
generalRules.addEventListener("mouseout", () => {
generalRules.style.backgroundColor = "#ba4545";
});
const reviewRules = document.createElement("button");
reviewRules.textContent = "Reviews";
reviewRules.style.marginTop = "15px";
reviewRules.style.padding = "8px 12px";
reviewRules.style.backgroundColor = "#ba4545";
reviewRules.style.color = "#fff";
reviewRules.style.border = "none";
reviewRules.style.borderRadius = "4px";
reviewRules.style.cursor = "pointer";
reviewRules.style.alignSelf = "center";
reviewRules.style.height = "35px";
leftButtonRow.appendChild(reviewRules);
reviewRules.addEventListener("click", () => {
window.location.href = "https://f95zone.to/threads/review-rating-rules-updated-2024-06-04.1753/";
closePopup;
});
reviewRules.addEventListener("mouseover", () => {
reviewRules.style.backgroundColor = "#9e3838";
});
reviewRules.addEventListener("mouseout", () => {
reviewRules.style.backgroundColor = "#ba4545";
});
const gameRules = document.createElement("button");
gameRules.textContent = "Games";
gameRules.style.marginTop = "15px";
gameRules.style.padding = "8px 12px";
gameRules.style.backgroundColor = "#ba4545";
gameRules.style.color = "#fff";
gameRules.style.border = "none";
gameRules.style.borderRadius = "4px";
gameRules.style.cursor = "pointer";
gameRules.style.alignSelf = "center";
gameRules.style.height = "35px";
leftButtonRow.appendChild(gameRules);
gameRules.addEventListener("click", () => {
window.location.href = "https://f95zone.to/threads/game-uploading-rules-2024-02-29.524/";
closePopup;
});
gameRules.addEventListener("mouseover", () => {
gameRules.style.backgroundColor = "#9e3838";
});
gameRules.addEventListener("mouseout", () => {
gameRules.style.backgroundColor = "#ba4545";
});
const comicRules = document.createElement("button");
comicRules.textContent = "Comics/Stills";
comicRules.style.marginTop = "15px";
comicRules.style.padding = "8px 12px";
comicRules.style.backgroundColor = "#ba4545";
comicRules.style.color = "#fff";
comicRules.style.border = "none";
comicRules.style.borderRadius = "4px";
comicRules.style.cursor = "pointer";
comicRules.style.alignSelf = "center";
comicRules.style.height = "35px";
leftButtonRow.appendChild(comicRules);
comicRules.addEventListener("click", () => {
window.location.href = "https://f95zone.to/threads/comics-stills-uploading-rules-2021-01-22.2922/";
closePopup;
});
comicRules.addEventListener("mouseover", () => {
comicRules.style.backgroundColor = "#9e3838";
});
comicRules.addEventListener("mouseout", () => {
comicRules.style.backgroundColor = "#ba4545";
});
const animRules = document.createElement("button");
animRules.textContent = "Animations";
animRules.style.marginTop = "15px";
animRules.style.padding = "8px 12px";
animRules.style.backgroundColor = "#ba4545";
animRules.style.color = "#fff";
animRules.style.border = "none";
animRules.style.borderRadius = "4px";
animRules.style.cursor = "pointer";
animRules.style.alignSelf = "center";
animRules.style.height = "35px";
leftButtonRow.appendChild(animRules);
animRules.addEventListener("click", () => {
window.location.href = "https://f95zone.to/threads/animations-loops-uploading-rules-2020-01-22.72085/";
closePopup;
});
animRules.addEventListener("mouseover", () => {
animRules.style.backgroundColor = "#9e3838";
});
animRules.addEventListener("mouseout", () => {
animRules.style.backgroundColor = "#ba4545";
});
const assetRules = document.createElement("button");
assetRules.textContent = "Assets";
assetRules.style.marginTop = "15px";
assetRules.style.padding = "8px 12px";
assetRules.style.backgroundColor = "#ba4545";
assetRules.style.color = "#fff";
assetRules.style.border = "none";
assetRules.style.borderRadius = "4px";
assetRules.style.cursor = "pointer";
assetRules.style.alignSelf = "center";
assetRules.style.height = "35px";
leftButtonRow.appendChild(assetRules);
assetRules.addEventListener("click", () => {
window.location.href = "https://f95zone.to/threads/asset-uploading-rules-instructions-2024-01-28.23506/";
closePopup;
});
assetRules.addEventListener("mouseover", () => {
assetRules.style.backgroundColor = "#9e3838";
});
assetRules.addEventListener("mouseout", () => {
assetRules.style.backgroundColor = "#ba4545";
});
// Submit button
const submitButton = document.createElement("button");
submitButton.textContent = "Submit"
submitButton.style.marginTop = "15px";
submitButton.style.padding = "8px 12px";
submitButton.style.backgroundColor = "#ba4545";
submitButton.style.color = "#fff";
submitButton.style.border = "none";
submitButton.style.borderRadius = "4px";
submitButton.style.cursor = "pointer";
submitButton.style.alignSelf = "center";
submitButton.style.height = "35px";
buttonContainer.appendChild(submitButton);
submitButton.addEventListener("mouseover", () => {
submitButton.style.backgroundColor = "#9e3838";
});
submitButton.addEventListener("mouseout", () => {
submitButton.style.backgroundColor = "#ba4545";
});
submitButton.addEventListener("click", () => {
closePopup();
});
// Modify the makeBBCodeButton click event handler
makeBBCodeButton.addEventListener("click", () => {
// Get all form values
const overview = document.getElementById("overview").value;
const threadUpdated = document.getElementById("thread_updated").value;
const releaseDate = document.getElementById("release_date").value;
const gameName = document.getElementById("game_name").value;
const devName = document.getElementById("devName").value;
const devLinks = document.getElementById("devLinks").value;
const translator = document.getElementById("translator").value;
const translatorLinks = document.getElementById("translatorLinks").value;
const version = document.getElementById("version").value;
const censorship = document.getElementById("censorsip");
const censorshipText = censorship.options[censorship.selectedIndex].text;
const store = document.getElementById("store").value;
const installation = document.getElementById("installation").value;
const changelog = document.getElementById("changelog").value;
const devNotes = document.getElementById("devNotes").value;
// Get selected genres
const genreSelect = document.getElementById("genre");
const selectedGenres = Array.from(genreSelect.selectedOptions).map(option => option.value);
// Format dev links
const formattedDevLinks = devLinks.split(",").map(link => {
const [site, url] = link.split("|");
return `[URL='${url.trim()}']${site.trim()}[/URL]`;
}).join(" - ");
// Format translator links if they exist
const formattedTranslatorLinks = translatorLinks ?
translatorLinks.split(",").map(link => {
const [site, url] = link.split("|");
return `[URL='${url.trim()}']${site.trim()}[/URL]`;
}).join(" - ") : "";
// Format store links
const formattedStoreLinks = store.split(",").map(link => {
const [site, url] = link.split("|");
return `[URL='${url.trim()}']${site.trim()}[/URL]`;
}).join(" - ");
// Create BBCode
let bbcode = `[CENTER]
[B]Overview[/B]:
${overview}[/CENTER]
[B]Thread Updated[/B]: ${threadUpdated}
[B]Release Date[/B]: ${releaseDate}
[B]Developer[/B]: ${devName} ${formattedDevLinks}`;
// Add translator if provided
if (translator) {
bbcode += `\n[B]Translator[/B]: ${translator}${formattedTranslatorLinks ? ' ' + formattedTranslatorLinks : ''}`;
}
bbcode += `\n[B]Censored[/B]: ${censorshipText}
[B]Version[/B]: ${version}
[B]Genre[/B]:
[SPOILER]
${selectedGenres.join(", ")}
[/SPOILER]`;
// Add installation section if provided
if (installation) {
bbcode += `\n\n[B]Installation[/B]:
[SPOILER]
${installation}
[/SPOILER]`;
}
// Add changelog if provided
if (changelog) {
bbcode += `\n\n[B]Changelog[/B]:
[SPOILER]
${changelog}
[/SPOILER]`;
}
// Add dev notes if provided
if (devNotes) {
bbcode += `\n\n[B]Dev Notes[/B]:
[SPOILER]
${devNotes}
[/SPOILER]`;
}
// Add store links if provided
if (store) {
bbcode += `\n\n[B]Store[/B]: ${formattedStoreLinks}`;
}
// Copy to clipboard
GM_setClipboard(bbcode);
alert("BBCode has been copied to clipboard!");
});
// Prevent clicks within the popup from closing it
popup.addEventListener("click", (event) => event.stopPropagation());
// Event to close popup when clicking outside of it
overlay.addEventListener("click", closePopup);
document.body.appendChild(overlay);
document.body.appendChild(popup);
isPopupOpen = true;
}
// Function to close the popup
function closePopup() {
if (isPopupOpen) {
document.body.removeChild(overlay);
document.body.removeChild(popup);
isPopupOpen = false;
}
}
// Update the header styling for both General Info and Notes sections
function createHeaderStyle(element, text) {
element.textContent = text;
element.style.color = "#fff";
element.style.marginBottom = "10px";
element.style.gridColumn = "span 12";
element.style.backgroundColor = "#1e66a5";
element.style.padding = "10px";
element.style.borderRadius = "4px";
element.style.width = "100%";
element.style.display = "block";
element.style.fontWeight = "600";
element.style.fontSize = "16px";
}
// Update the description styling
function createDescStyle(element, text) {
element.textContent = text;
element.style.color = "#fff";
element.style.marginBottom = "20px";
element.style.gridColumn = "span 12";
element.style.backgroundColor = "#1e66a5";
element.style.padding = "10px";
element.style.borderRadius = "4px";
element.style.width = "100%";
element.style.display = "block";
element.style.fontSize = "14px";
}
// Add Choices.js CSS
GM_addStyle(GM_getResourceText('CHOICES_CSS'));
// Add custom styling for Choices.js to match the theme
GM_addStyle(`
.choices {
margin-bottom: 0;
}
.choices__inner {
background-color: #242629 !important;
border: 1px solid #343638;
color: #fff;
min-height: 38px;
padding: 6px 8px;
}
.choices__input {
background-color: #242629 !important;
color: #fff !important;
}
.choices__list--dropdown {
background-color: #242629 !important;
border: 1px solid #343638;
color: #fff;
}
.choices__list--dropdown .choices__item {
color: #fff !important;
padding: 8px;
background-color: #242629 !important;
}
.choices__list--dropdown .choices__item--selectable {
background-color: #242629 !important;
}
.choices__list--dropdown .choices__item--selectable.is-highlighted {
background-color: #1e66a5 !important;
}
.choices__list--multiple .choices__item {
background-color: #1e66a5 !important;
border: 1px solid #1e66a5;
color: #fff;
}
.choices[data-type*="select-multiple"] .choices__button {
border-left: 1px solid #fff;
background-image: url("data:image/svg+xml,%3Csvg width='21' height='21' viewBox='0 0 21 21' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23ffffff' fill-rule='evenodd'%3E%3Cpath d='M2.592.044l18.364 18.364-2.548 2.548L.044 2.592z'/%3E%3Cpath d='M0 18.364L18.364 0l2.548 2.548L2.548 20.912z'/%3E%3C/g%3E%3C/svg%3E");
}
.choices__list--dropdown {
z-index: 10001;
}
.choices__list--dropdown .choices__item--selectable {
padding-right: 10px;
}
.choices__list--dropdown .choices__item--selectable:after {
display: none;
}
.choices__placeholder {
color: #fff;
}
.choices__input--cloned {
background-color: transparent !important;
color: #fff !important;
}
.choices__list--multiple {
display: flex;
flex-wrap: wrap;
gap: 5px;
background-color: #242629 !important;
}
.choices__list--multiple .choices__item {
margin: 0;
border-radius: 4px;
}
.choices[data-type*="select-multiple"] .choices__inner {
padding: 5px;
background-color: #242629 !important;
}
.choices__list--dropdown .choices__list {
background-color: #242629 !important;
}
.choices__list--single {
background-color: #242629 !important;
color: #fff !important;
}
.choices__heading {
background-color: #1e66a5 !important;
color: #fff !important;
border-bottom: 1px solid #343638 !important;
}
.choices[data-type*="select-one"]:after {
border-color: #fff transparent transparent transparent !important;
}
`);
})();