Custom Coloris Palette

Modifies Coloris color pickers in Kanka to offer the user’s selection of preset colors.

  1. // ==UserScript==
  2. // @name Custom Coloris Palette
  3. // @namespace http://tampermonkey.net/
  4. // @version 4
  5. // @description Modifies Coloris color pickers in Kanka to offer the user’s selection of preset colors.
  6. // @author Salvatos
  7. // @match https://app.kanka.io/*relations*
  8. // @match https://app.kanka.io/*entity_events*
  9. // @match https://app.kanka.io/*map_markers*
  10. // @match https://app.kanka.io/*presets*
  11. // @match https://app.kanka.io/*calendars*
  12. // @match https://app.kanka.io/*families/*/tree*
  13. // @match https://app.kanka.io/*theme-builder
  14. // @icon https://www.google.com/s2/favicons?domain=kanka.io
  15. // @grant none
  16. // @run-at document-end
  17. // ==/UserScript==
  18.  
  19. /*** INSTRUCTIONS
  20. Add your color values in any valid format to the "customColors" setting below.
  21. - Values are enclosed in quotation marks and separated by commas (line breaks are optional).
  22. - All standard web color formats are accepted: named, hexadecimal, RGB(A), HSL, etc.
  23.  
  24. Example:
  25. var customColorsExample = [
  26. 'navy',
  27. '#07b',
  28. '#123321',
  29. '#00b4d880',
  30. 'rgb(244,162,97)',
  31. 'rgba(0,119,182,0.8)',
  32. 'hsl(0, 100%, 50%)',
  33. ];
  34.  
  35. Remember you can also define a palette on each campaign; details on GreasyFork.
  36. ***/
  37.  
  38. var customColors = [
  39. ];
  40.  
  41. // Prepare to check for supported themes in the campaign
  42. var rootFlags = getComputedStyle(document.documentElement);
  43.  
  44. /* Campaign-specific swatches */
  45. if (rootFlags.getPropertyValue('--coloris-presets')) {
  46. let campaignSwatches = rootFlags.getPropertyValue('--coloris-presets').split(" ");
  47. // Merge browser and campaign arrays, removing duplicates
  48. customColors = customColors.concat(campaignSwatches.filter((item) => customColors.indexOf(item) < 0));
  49. }
  50.  
  51. /* Build swatches */
  52. var swatches = `<div>`;
  53. for (let i = 0; i < customColors.length; i++) {
  54. swatches += `<button type="button" id="clr-swatch-${i}" aria-labelledby="clr-swatch-label clr-swatch-${i}" style="color: ${customColors[i]};">${customColors[i]}</button>`;
  55. }
  56. swatches += `</div>`;
  57.  
  58. /* Select the element to watch for the appearance of a color picker based on the current page */
  59. /* Use the closest parent to input.spectrum that exists at page load to keep MutationObserver lean */
  60.  
  61. // Buld relations edit modal
  62. if (window.location.href.indexOf("relations") != -1 && window.location.href.indexOf("entities") == -1) {
  63. document.targetNode = document.getElementById("bulk-edit");
  64. }
  65. // Map marker edit page
  66. else if (window.location.href.indexOf("map_markers") != -1) {
  67. document.targetNode = document.getElementById("map-marker-form");
  68. }
  69. // Map marker preset edit page
  70. else if (window.location.href.indexOf("presets") != -1) {
  71. document.targetNode = document.querySelector("section.content .grid");
  72. }
  73. // Family tree relation edit modal
  74. else if (window.location.href.indexOf("tree") != -1) {
  75. document.targetNode = document.getElementById("family-tree");
  76. }
  77. // Theme Builder
  78. // Form is created at page load, so no need to observe mutations
  79. else if (window.location.href.indexOf("theme-builder") != -1) {
  80. // Just add the swatches once, but allow a second for Coloris to initialize
  81. setTimeout(() => {
  82. document.getElementById("clr-swatches").insertAdjacentHTML("beforeend", swatches);
  83. }, "1000");
  84.  
  85. }
  86. // Default (entity relations and reminders, calendar reminders, theme builder, etc.)
  87. else {
  88. document.targetNode = document.getElementById("primary-dialog");
  89. }
  90.  
  91. // Start observing the page for the appearance of a "Spectrum" input, except for the Theme Builder
  92. if (document.targetNode) {
  93. let observer = new MutationObserver(function(mutations) {
  94. if (document.querySelector(':is(.spectrum, .picker)')) {
  95. // If swatches have not already been added, append them to the existing container
  96. if (document.getElementById("clr-swatches").children.length < 1) {
  97. document.getElementById("clr-swatches").insertAdjacentHTML("beforeend", swatches);
  98. }
  99. // Keep the observer running in case the modal is closed and reopened
  100. }
  101. });
  102.  
  103. observer.observe(document.targetNode, {attributes: false, childList: true, characterData: false, subtree:true});
  104. }