krz/palettes
A color palette generator with export utilities.
clone: git clone https://gitbay.org/krz/palettes.git
1function getRGB() {
2 var r = Math.floor(Math.random() * 255);
3 var g = Math.floor(Math.random() * 255);
4 var b = Math.floor(Math.random() * 255);
5 return [r, g, b];
6}
7
8function getHex(rgb) {
9 var hex = "";
10 rgb.forEach(function (val) {
11 var hexPartial = Number(val).toString(16);
12 if (hexPartial.length < 2) {
13 hexPartial = "0" + hexPartial;
14 }
15 hex = hex + hexPartial;
16 });
17 return hex;
18}
19
20function getCMYK(rgb) {
21 var finalK = 0;
22
23 var r = rgb[0];
24 var g = rgb[1];
25 var b = rgb[2];
26
27 if (r === 0 && g === 0 && b === 0) {
28 finalK = 1;
29 return [0, 0, 0, 1];
30 }
31
32 var finalC = 1 - r / 255;
33 var finalM = 1 - g / 255;
34 var finalY = 1 - b / 255;
35
36 var minCMY = Math.min(finalC, Math.min(finalM, finalY));
37 finalC = Math.trunc(((finalC - minCMY) / (1 - minCMY)) * 100);
38 finalM = Math.trunc(((finalM - minCMY) / (1 - minCMY)) * 100);
39 finalY = Math.trunc(((finalY - minCMY) / (1 - minCMY)) * 100);
40 finalK = Math.trunc(minCMY * 100);
41
42 return finalC + "," + finalM + "," + finalY + "," + finalK;
43}
44
45function getContrast(rgb) {
46 return (299 * rgb[0] + 587 * rgb[1] + 114 * rgb[2]) / 1000;
47}
48
49function generate(elements) {
50 elements.each(function (index, column) {
51 let rgb = getRGB();
52 $(column).find(".color-rgb").text(`(${rgb})`);
53 $(column)
54 .find(".color-hex")
55 .text("#" + getHex(rgb));
56 $(column)
57 .find(".color-cmyk")
58 .text(`(${getCMYK(rgb)})`);
59 $(column).css("background-color", `rgb(${rgb})`);
60 if (getContrast(rgb) < 123) {
61 $(column).addClass("text-white");
62 } else {
63 $(column).removeClass("text-white");
64 }
65 });
66}
67
68function regenerate() {
69 generate($(".color-column[data-locked='false']"));
70}
71
72function copy(type, text) {
73 var $tempTextField = $("<input>");
74 $("body").append($tempTextField);
75 switch (type) {
76 case "rgb":
77 $tempTextField.val("rgb" + text).select();
78 break;
79 case "hex":
80 $tempTextField.val(text).select();
81 break;
82 case "cmyk":
83 $tempTextField.val("cmyk" + text).select();
84 break;
85 }
86 document.execCommand("copy");
87 $tempTextField.remove();
88}
89
90function showToast(type, text) {
91 var alert =
92 "<div class='toast-alert alert alert-" +
93 type +
94 "' role='alert'>" +
95 text +
96 "</div>";
97 $(".container-fluid").append(alert);
98 $(".toast-alert").animate(
99 {
100 opacity: 0,
101 },
102 2000,
103 function () {
104 $(this).remove();
105 }
106 );
107}
108
109function init() {
110 regenerate();
111
112 $(".color-value").click(function (e) {
113 var text = $(e.target).text();
114 copy($(e.target).data("format"), text);
115 showToast("success", "Color code copied to clipboard.");
116 });
117
118 $(".color-column-lock").click(function (e) {
119 var icon = $(e.target);
120 var column = $(e.target).parent().parent();
121 var status = column.attr("data-locked");
122 if (status === "true") {
123 column.attr("data-locked", "false");
124 } else {
125 column.attr("data-locked", "true");
126 }
127 icon.toggleClass(["fa-lock-open", "fa-lock"]);
128 });
129
130 $(".color-column-regenerate").click(function (e) {
131 generate($(e.target).parent().parent());
132 });
133
134 $("#submitNewColor").click(function (e) {
135 setNewColor(getNewColor(e));
136 });
137
138 loadAllPalettes();
139}
140
141function setNewColor(values) {
142 var column = $(".color-column:eq(" + (parseInt(values[1]) - 1) + ")");
143 var rgb = JSON.parse("[" + values[0] + "]");
144 $(column).find(".color-rgb").text(`(${rgb})`);
145 $(column)
146 .find(".color-hex")
147 .text("#" + getHex(rgb));
148 $(column)
149 .find(".color-cmyk")
150 .text(`(${getCMYK(rgb)})`);
151 $(column).css("background-color", `rgb(${rgb})`);
152 if (getContrast(rgb) < 123) {
153 $(column).addClass("text-white");
154 } else {
155 $(column).removeClass("text-white");
156 }
157}
158
159function getNewColor(e) {
160 var string = $(e.target).closest(".modal-content").find("input").val();
161 var newString = string.replace("(", "").replace(")", "").replace("rgb", "");
162 var column = $(e.target)
163 .closest(".modal-content")
164 .find("select option:selected")
165 .text();
166 return [newString, column];
167}
168
169function switchTheme() {
170 $("body").toggleClass("custom-bg");
171 $(".fa-moon").toggleClass("d-none");
172 $(".fa-sun").toggleClass("d-none");
173 $(".color-column-labels").toggleClass("text-white");
174}
175
176function storePalette(keysObject, paletteName) {
177 // Query object of all rgb colors and store text values in new object
178 var rgbDOMObject = $(".color-rgb");
179 var rgbStorageObject = {
180 0: $(rgbDOMObject[0]).text().replace("(", "").replace(")", ""),
181 1: $(rgbDOMObject[1]).text().replace("(", "").replace(")", ""),
182 2: $(rgbDOMObject[2]).text().replace("(", "").replace(")", ""),
183 3: $(rgbDOMObject[3]).text().replace("(", "").replace(")", ""),
184 4: $(rgbDOMObject[4]).text().replace("(", "").replace(")", ""),
185 };
186 // Generate random key, ensure it doesn't exist already, then save the key in storage
187 var randomKey = generateRandomKey();
188 if (keysObject === null) {
189 var newKeysObject = {};
190 newKeysObject[paletteName] = randomKey;
191 } else {
192 var newKeysObject = keysObject;
193 newKeysObject[paletteName] = randomKey;
194 }
195 localStorage.setItem("paletteKeys", JSON.stringify(newKeysObject));
196 // Save color palette object
197 localStorage.setItem(randomKey, JSON.stringify(rgbStorageObject));
198
199 return randomKey;
200}
201
202function savePalette() {
203 // Get palette names object and user input of new palette name
204 var keysObject = JSON.parse(localStorage.getItem("paletteKeys"));
205 var paletteName = $("#inputPaletteName").val();
206 var nameCheck = false;
207 // Check palette name exists
208 if (keysObject !== null && paletteName in keysObject) {
209 nameCheck = true;
210 }
211 if (typeof Storage !== "undefined") {
212 // If the input name is null or empty, show an error alert
213 if (
214 paletteName === null ||
215 paletteName == "undefined" ||
216 paletteName == ""
217 ) {
218 alert("Error: You must enter a valid name for this palette.");
219 } else if (keysObject != null && nameCheck === true) {
220 // If the name exists, ask user to confirm
221 var userConfirmation = confirm(
222 "Palette name exists. Do you want to overwrite this palette?"
223 );
224 // If the user confirms, save the palette
225 if (userConfirmation) {
226 var randomKey = storePalette(keysObject, paletteName);
227 $("#savedPalettesBody").append(
228 "<button class='btn btn-outline-secondary my-2 w-100' onclick='loadPalette(" +
229 randomKey +
230 ")'>" +
231 paletteName +
232 "</button>"
233 );
234 showToast("success", "Color palette saved.");
235 }
236 } else {
237 // If the name doesn't exist, save palette
238 var randomKey = storePalette(keysObject, paletteName);
239 $("#savedPalettesBody").append(
240 "<div id='" +
241 randomKey +
242 "' class='my-2 d-flex'><div class='btn-group w-100' role='group' aria-label='Saved palette'><button class='btn btn-secondary w-100' onclick='loadPalette(" +
243 randomKey +
244 ")'>" +
245 paletteName +
246 "</button><button class='btn btn-danger' onclick='deletePalette(" +
247 randomKey +
248 ")'><i class='far fa-trash-alt'></i></button></div></div>"
249 );
250 showToast("success", "Color palette saved.");
251 }
252 } else {
253 alert(
254 "Sorry, your browser does not support Web Storage. Please ugrade your browser and try again."
255 );
256 }
257}
258
259function loadAllPalettes() {
260 if (typeof Storage !== "undefined") {
261 var fetchedData = localStorage.getItem("paletteKeys");
262 if (fetchedData === null) {
263 console.log("Warning: No palettes exist.");
264 } else {
265 $.each(JSON.parse(fetchedData), function (key, value) {
266 var palette = localStorage.getItem(key);
267 $("#savedPalettesBody").append(
268 "<div id='" +
269 value +
270 "' class='my-2 d-flex'><div class='btn-group w-100' role='group' aria-label='Saved palette'><button class='btn btn-secondary w-100' onclick='loadPalette(" +
271 value +
272 ")'>" +
273 key +
274 "</button><button class='btn btn-danger' onclick='deletePalette(" +
275 value +
276 ")'><i class='far fa-trash-alt'></i></button></div></div>"
277 );
278 $("#editColorModal").modal("hide");
279 });
280 showToast("success", "Color palettes loaded.");
281 }
282 } else {
283 alert(
284 "Sorry, your browser does not support Web Storage. Please ugrade your browser and try again."
285 );
286 }
287}
288
289function loadPalette(requestedKey) {
290 var fetchedData = localStorage.getItem("paletteKeys");
291 $.each(JSON.parse(fetchedData), function (key, value) {
292 var newValue = parseInt(value, 10);
293 if (requestedKey === newValue) {
294 var palette = localStorage.getItem(value);
295 $.each(JSON.parse(palette), function (subKey, subValue) {
296 var col = parseInt(subKey, 10) + 1;
297 setNewColor([subValue, col]);
298 });
299 }
300 $("#editColorModal").modal("hide");
301 });
302}
303
304function deleteAllPalettes() {
305 var confirmation = confirm("Are you sure you want to delete all palettes?");
306 if (confirmation) {
307 $("#savedPalettesBody button").remove();
308 localStorage.clear();
309 }
310}
311
312function deletePalette(id) {
313 var confirmation = confirm("Are you sure you want to delete this palette?");
314 if (confirmation) {
315 // Get name of palette by the id
316 var keysObject = JSON.parse(localStorage.getItem("paletteKeys"));
317 var name = getKeyByValue(keysObject, id);
318 // Remove the button
319 $("#" + id).remove();
320 // Remove local storage item
321 localStorage.removeItem(id);
322 // Remove item from paletteKeys
323 delete keysObject[name];
324 // Set new paletteKeys object
325 var newKeysObject = keysObject;
326 localStorage.setItem("paletteKeys", JSON.stringify(newKeysObject));
327 }
328}
329
330function generateRandomKey() {
331 // Generate random key
332 var randomKey = Math.floor(Math.random() * 9007199254740992 + 1);
333 // Check if random key exists (up to 100 times)
334 for (var i = 0; i < 100; i++) {
335 // If the key exists, generate a new key
336 if (checkKey(randomKey) === true) {
337 randomKey = Math.floor(Math.random() * 9007199254740992 + 1);
338 }
339 // If the key does not exist, break the loop and return the key
340 else {
341 break;
342 }
343 }
344 return randomKey;
345}
346
347function checkKey(key) {
348 // Fetch paletteKeys object
349 var keysObject = localStorage.getItem("paletteKeys");
350 // If object is null, it doesn't exist yet
351 if (keysObject !== null) {
352 // If object exists, parse it and check to see if the key exists
353 var tempObject = JSON.parse(keysObject);
354 if (tempObject.hasOwnProperty(key.toString())) {
355 return true;
356 } else {
357 return false;
358 }
359 }
360}
361
362function saveImage() {
363 // Remove previous image
364 $("#saveImageModal img").remove();
365 // Hide toolbar so it doesn't appear in screenshot
366 $(".color-column-toolbar").hide();
367 // Set background color of canvas based on body
368 var bgColor = $("body").hasClass("custom-bg") ? "#000000" : "#FFFFFF";
369 // Get canvas and launch modal
370 html2canvas(document.getElementsByClassName("container-fluid")[0], {
371 backgroundColor: bgColor,
372 }).then(function (canvas) {
373 $(".color-column-toolbar").show();
374 var img = canvas.toDataURL("image/png");
375 $("#saveImageModal").modal("show");
376 $("#saveImageModal .modal-body").append(
377 '<img id="palette-image" class="img-fluid" src="' + img + '"/>'
378 );
379 });
380}
381
382function getKeyByValue(object, value) {
383 for (var i = 0; i < Object.keys(object).length; i++) {
384 var key = Object.keys(object)[i];
385 var fetchedValue = object[key];
386 if (value === fetchedValue) {
387 return key;
388 }
389 }
390}