- // ==UserScript==
- // @name Color Picker
- // @namespace https://greasyfork.org/users/281093
- // @match https://sketchful.io/*
- // @grant none
- // @version 0.5
- // @author Bell
- // @description Color picker for Sketchful
- // @run-at document-end
- // jshint esversion: 6
- // ==/UserScript==
-
- let defaultPalettes = [
- [
- "#ffffff","#d3d1d2","#f70f0f","#ff7200","#fce700","#02cb00","#01fe94","#05b0ff","#221ecd","#a300bd","#cc7fad","#fdad88","#9e5425",
- "#514f54","#a9a7a8","#ae0b00","#c84706","#ec9e06","#007612","#049d6f","#00579d","#0f0b96","#6e0083","#a65673","#e38a5e","#5e320d",
- "#000000","#827c80","#57060c","#8b2500","#9e6600","#003f00","#00766a","#003b75","#0e0151","#3c0350","#73314d","#d1754e","#421e06"
- ],
-
- [
- "#3a3a3c","#8e8e93","#f8f9fa","#ffadad","#ffd6a5","#fdffb6","#caffbf","#9bf6ff","#a0c4ff","#bdb2ff","#ffc6ff","#fdad88","#9e5425",
- "#2c2c2e","#636366","#e0e0e0","#ff7070","#f3a220","#f9e079","#049d6f","#92ddea","#6dafe0","#ab87ff","#ff87ab","#e38a5e","#5e320d",
- "#1c1c1e","#48484a","#c2c2c2","#f54d4d","#dc8700","#f0c808","#00766a","#219bc3","#548bbc","#715aff","#ff5d8f","#d1754e","#421e06"
- ],
-
- [
- "#081c15","#1b4332","#2d6a4f","#40916c","#52b788","#74c69d","#95d5b2","#b7e4c7","#d8f3dc","#000000","#faf9f9","#ffd6ba","#fec89a",
- "#774936","#8a5a44","#9d6b53","#b07d62","#c38e70","#cd9777","#d69f7e","#deab90","#e6b8a2","#edc4b3","#ffb5a7","#fcd5ce","#f8edeb",
- "#cb997e","#eddcd2","#fff1e6","#f0efeb","#ddbea9","#a5a58d","#b7b7a4","#6d6875","#b5838d","#e5989b","#ffb4a2","#ffcdb2","#f9dcc4"
- ],
-
- [
- "#10002b","#240046","#3c096c","#5a189a","#7b2cbf","#9d4edd","#c77dff","#e0aaff","#efcefa","#d4b2d8","#a88fac","#826c7f","#5d4e60",
- "#7c6f93","#886f93","#a967ad","#ad6789","#db81ad","#ff6c91","#ff736c","#ff9e46","#faa275","#ff8c61","#ce6a85","#985277","#5c374c",
- "#721b65","#b80d57","#f8615a","#ffd868","#bb596b","#f96d80","#ff9a76","#ffc4a3","#00e0ff","#74f9ff","#a6fff2","#e8ffe8","#ffffff"
- ],
-
- [
- "#007f5f","#2b9348","#55a630","#80b918","#aacc00","#bfd200","#d4d700","#dddf00","#eeef20","#ffff3f","#03045e","#0077b6","#00b4d8",
- "#ff4800","#ff5400","#ff6000","#ff6d00","#ff7900","#ff8500","#ff9100","#ff9e00","#ffaa00","#ffb600","#90e0ef","#caf0f8","#000000",
- "#143642","#263c41","#38413f","#4a473e","#5c4d3c","#6f523b","#815839","#935e38","#a56336","#b76935","#000000","#ffffff","#ffffff"
- ]
- ];
- let palettes = JSON.parse(localStorage.getItem('palettes')) || defaultPalettes;
- let paletteIndex = parseInt(localStorage.getItem("paletteIndex")) || 0;
- let lockedPalettes = JSON.parse(localStorage.getItem('lockedPalettes')) || [0];
- let activeColor = {
- node: null,
- index: null
- };
-
- const canvas = document.querySelector("#canvas");
- const ctx = canvas.getContext("2d");
- const gameTools = document.querySelector("#gameTools");
- const chatBox = document.querySelector("#gameChat");
- const colorButtons = document.querySelectorAll(".gameToolsColor");
- const colorsDiv = document.querySelector("#gameToolsColors");
- const colorButton = document.querySelector("#gameToolsColors > div:nth-child(1) > div:nth-child(1)");
-
- const colorPickerWrapper = document.createElement("div");
- const colorInput = document.createElement("input");
- const colorPicker = document.createElement("input");
- const inputStyle = `margin: 5px 0; height: 20px; width: 35%; text-align: center; border: none;font-weight: 800; border-radius: 5px; background-color: #CBCBCB;`;
- const wrapperStyle = `position: absolute; margin: 5px 35%; height: 20px; width: 37px; border-radius: 5px;`;
-
- (function init() {
- addPicker();
- updatePageStyle();
- addObservers();
- addListeners();
- changePalette(paletteIndex);
- })();
-
- function addPicker() {
- colorPicker.type = "color";
- colorPicker.setAttribute("style", "opacity: 0; width: 37px; cursor: pointer;");
- colorPicker.oninput = updatePicker;
-
- colorPickerWrapper.setAttribute("style", wrapperStyle);
- colorPickerWrapper.style.backgroundColor = colorPicker.value;
- colorPickerWrapper.appendChild(colorPicker);
- gameTools.appendChild(colorPickerWrapper);
-
- colorInput.oninput = updateInput;
- colorInput.addEventListener("click", selectInputText, false);
- colorInput.setAttribute("style", inputStyle);
- colorInput.setAttribute("spellcheck", "false");
- colorInput.value = colorPicker.value;
- gameTools.appendChild(colorInput);
- addButtons();
- }
-
- function addObservers() {
- const heightObserver = new MutationObserver(adjustChatSize);
- const config = {
- attributes: true,
- childList: false,
- subtree: false
- };
- heightObserver.observe(gameTools, config);
- heightObserver.observe(chatBox, config);
- }
-
- function addListeners() {
- canvas.addEventListener('pointerdown', pickCanvasColor, false);
- colorsDiv.addEventListener("click", editColor, false);
- let saveBtn = document.querySelector("#savePalette");
- saveBtn.addEventListener("dragenter", highlight, false);
- saveBtn.addEventListener("dragleave", unhighlight, false);
- saveBtn.addEventListener("drop", handleDrop, false);
- saveBtn.addEventListener("dragover", e => { e.preventDefault(); }, false);
- }
-
- function updatePageStyle() {
- document.querySelector("#gameToolsSlider").style.top = "77px";
- gameTools.style.height = "200px";
- }
-
- function toggleLock() {
- let lockBtn = document.querySelector("#lockButton");
- if (lockBtn.getAttribute("state") === "unlocked") {
- lockPalette(lockBtn);
- } else {
- unlockPalette(lockBtn);
- }
- updateLock();
- }
-
- function lockPalette(lockBtn) {
- lockedPalettes.push(paletteIndex);
- localStorage.setItem("lockedPalettes", JSON.stringify(lockedPalettes));
- }
-
- function unlockPalette(lockBtn) {
- let index = lockedPalettes.indexOf(paletteIndex);
- if (index < 0) return;
- lockedPalettes.splice(index, 1);
- localStorage.setItem("lockedPalettes", JSON.stringify(lockedPalettes));
- }
-
- function updateLock() {
- let lockBtn = document.querySelector("#lockButton");
- if (isPaletteLocked()) {
- lockBtn.classList.remove("fa-unlock-alt");
- lockBtn.classList.add("fa-lock");
- lockBtn.setAttribute("state", "locked");
- } else {
- lockBtn.classList.add("fa-unlock-alt");
- lockBtn.classList.remove("fa-lock");
- lockBtn.setAttribute("state", "unlocked");
- }
- resetActiveColor();
- }
-
- function addButtons() {
- let prevPaletteBtn = document.createElement("button");
- let saveColorBtn = document.createElement("button");
- let nextPaletteBtn = document.createElement("button");
- let lockBtn = document.createElement("button");
-
- addButton(prevPaletteBtn, "arrow-left", "5px 5px 5px 45px;");
- addButton(saveColorBtn, "save", "5px 5px 5px 75px;", "savePalette");
- addButton(nextPaletteBtn, "arrow-right", "5px 5px 5px 105px;");
- addButton(lockBtn, "unlock-alt", "5px 5px 5px 135px;", "lockButton");
- lockBtn.setAttribute("state", "unlocked");
-
- prevPaletteBtn.addEventListener("click", prevPalette, false);
- saveColorBtn.addEventListener("click", saveColor, false);
- nextPaletteBtn.addEventListener("click", nextPalette, false);
- lockBtn.addEventListener("click", toggleLock, false);
- }
-
- function nextPalette() {
- paletteIndex < (palettes.length - 1) && paletteIndex++;
- localStorage.setItem("paletteIndex", paletteIndex);
- changePalette();
- }
-
- function prevPalette() {
- paletteIndex > 0 && paletteIndex--;
- localStorage.setItem("paletteIndex", paletteIndex);
- changePalette();
- }
-
- function saveColor(e) {
- if (e.shiftKey) {
- downloadPalettes();
- return;
- }
- let currentPalette = palettes[paletteIndex];
- if (activeColor.index) {
- currentPalette[activeColor.index] = colorPicker.value;
- } else {
- while (currentPalette.length >= 39 || isPaletteLocked()) {
- paletteIndex++;
- if (paletteIndex === palettes.length) {
- palettes.push([]);
- }
- currentPalette = palettes[paletteIndex];
- }
- currentPalette.push(colorPicker.value);
- }
- changePalette();
- savePalettes();
- }
-
- function savePalettes() {
- localStorage.setItem("palettes", JSON.stringify(palettes));
- }
-
- function downloadPalettes() {
- let formattedPaletteData = JSON.stringify(palettes).replace(/\]\,/g, "],\n\n");
- download("palettes.txt", formattedPaletteData);
- }
-
- function download(filename, text) {
- let pom = document.createElement('a');
- pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
- pom.setAttribute('download', filename);
-
- if (document.createEvent) {
- let event = document.createEvent('MouseEvents');
- event.initEvent('click', true, true);
- pom.dispatchEvent(event);
- }
- else {
- pom.click();
- }
- }
-
- function isPaletteLocked() {
- return lockedPalettes.includes(paletteIndex);
- }
-
- function editColor(event) {
- if (isPaletteLocked() || !event.target.classList.contains("gameToolsColor")) return;
- event.preventDefault();
- let color = {
- node: event.target,
- index: Array.prototype.indexOf.call(colorButtons, event.target)
- };
- if (event.altKey) {
- if (color.index >= 0 && paletteIndex >= 0) {
- let palette = palettes[paletteIndex];
- palette.splice(color.index, 1);
- if (isPaletteEmpty(palette)) {
- palettes.splice(paletteIndex, 1);
- paletteIndex--;
- }
- changePalette();
- savePalettes();
- }
- } else if (event.shiftKey) {
- setActiveColor(color);
- }
- }
-
- function changePalette() {
- if (paletteIndex < 0 || paletteIndex >= palettes.length) {
- paletteIndex = 0;
- localStorage.setItem("paletteIndex", paletteIndex);
- }
- colorButtons.forEach((button, idx) => {
- let color = palettes[paletteIndex][idx] || "#fff";
- button.style.backgroundColor = color;
- });
- resetActiveColor();
- updateLock();
- }
-
- function isPaletteEmpty(palette) {
- if (!palette) return true;
- let empty = true;
- for (let color of palette) {
- if (color) {
- empty = false;
- break;
- }
- }
- return empty;
- }
-
- function setActiveColor(color) {
- resetActiveColor();
- activeColor = color;
- console.log(activeColor);
- activeColor.node.style.border = "solid 2px red";
- }
-
- function resetActiveColor() {
- if (activeColor.node) {
- activeColor.node.style.border = "";
- activeColor = {
- node: null,
- index: null
- };
- }
- }
-
- function addButton(button, icon, pos, id = "") {
- let buttonStyle = `margin: ${pos}; position: absolute; height: 20px; border: none; background-color: #CBCBCB; border-radius: 5px;`;
- button.setAttribute("style", buttonStyle);
- button.setAttribute("class", `fas fa-${icon}`);
- button.id = id;
- gameTools.appendChild(button);
- }
-
- function updatePicker(event) {
- let color = event.target.value;
- colorPickerWrapper.style.backgroundColor = color;
- colorInput.value = color;
- setColor(color);
- }
-
- function updateInput(event) {
- let color = event.target.value;
- colorPickerWrapper.style.backgroundColor = color;
- colorPicker.value = color;
- setColor(color);
- }
-
- function setColor(color) {
- let prevColor = colorButton.style.backgroundColor;
- colorButton.style.backgroundColor = color;
- colorButton.dispatchEvent(new Event("pointerdown"));
- colorButton.style.backgroundColor = prevColor;
- }
-
- function selectInputText() {
- colorInput.select();
- }
-
- function pickCanvasColor(event) {
- if (!event.altKey) return;
- event.stopImmediatePropagation();
- let pos = getPos(event);
- let [r, g, b, a] = ctx.getImageData(pos.x, pos.y, 1, 1).data;
- let color = `rgb(${r}, ${g}, ${b})`;
- setColor(color);
- }
-
- function getPos(event) {
- let canvasRect = canvas.getBoundingClientRect();
- let canvasScale = canvas.width / canvasRect.width;
- return {
- x: (event.clientX - canvasRect.left) * canvasScale,
- y: (event.clientY - canvasRect.top) * canvasScale
- };
- }
-
- function handleDrop(e) {
- e.preventDefault();
- colorsDiv.style.filter = "";
- let file = e.dataTransfer.files[0];
- console.log(file);
- if (file) {
- let reader = new FileReader();
- reader.readAsText(file);
- reader.onload = (e) => {
- loadPalettes(JSON.parse(e.target.result));
- };
- }
- }
-
- function loadPalettes(loadedPalettes) {
- downloadPalettes();
- palettes = loadedPalettes;
- paletteIndex = 0;
- lockedPalettes = [];
- resetActiveColor();
- updateLock();
- changePalette();
- savePalettes();
- }
-
- function highlight(e) {
- e.preventDefault();
- colorsDiv.style.filter = "brightness(0.8)";
- }
-
- function unhighlight(e) {
- console.log("leave");
- e.preventDefault();
- colorsDiv.style.filter = "";
- }
-
- function isDrawing() {
- return document.querySelector("#gameTools").style.display !== "none";
- }
-
- function adjustChatSize() {
- chatBox.style.height = isDrawing() ? "calc(100% - 200px)" : "calc(100% - 180px)";
- }