Jighance

jiggie.fun Mods

Run the Javascript code in your browser's developer console (F12) or click the bookmarklet after a room has loaded.

Color enhancement

Adds ◐ gamma and 🌢 saturation controls to the UI for bringing out hidden detail in really dull puzzles.

Hidden detail revealed

Right-click

Right-click the controls to reset to normal.

Changelog

  • 2025-05-22: Fix Scores becoming offset and causing scrollbars. Use browser-native slider snapping. Adjusted gamma slider curve to ramp up sooner.
  • 2025-04-20: Use a parabolic function for easier fine adjustments.

As a Bookmarklet

javascript:{const e="gamma-slide";document.getElementById(e)?.remove();const o=document.createElement("div");const a=document.querySelector("#room-content");Object.assign(o,{id:e,innerHTML:'<div class="flex flex-col gap-1" style="position: absolute"><style>.colorfilter img[alt="preview"], .colorfilter canvas {filter: url(#gammafilter);} #gamma-slide>div {width: fit-content;pointer-events:auto} #gamma-slide{flex-basis: 100%;pointer-events:none;}</style><svg height="0" width="0" style="position: absolute;"><filter id="gammafilter"><feComponentTransfer><feFuncR type="gamma"/><feFuncG type="gamma"/><feFuncB type="gamma"/></feComponentTransfer><feColorMatrix type="saturate" values="1"/></filter></svg><div title="Gamma" class="hover:bg-accent transition-colors bg-background border border-input rounded-full flex items-center px-2 h-8 select-none"><svg class="svelte-fa-base" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="M6 0A6 6 0 1 1 5.99 0ZM6 1A1 1 0 0 1 6 11Z" fill="currentcolor" fill-rule="evenodd"/></svg><input type="range" min="-5" max="20" step="any" value="0" list="gamma-snap" class="w-32 mx-1"><datalist id="gamma-snap"><option value="0"></option></datalist></div><div title="Saturation" class="hover:bg-accent transition-colors bg-background border border-input rounded-full flex items-center px-2 h-8 select-none"><svg class="svelte-fa-base" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg"><path d="m60 0c10 53 24 54 34 75 9.4 20-4.7 45-34 45zm0 0c-10 53-24 54-34 75-9.4 20 4.7 45 34 45z" fill="currentcolor"/></svg><input type="range" min="0" max="30" step="any" value="0" class="w-32 mx-1"></div></div>'});const[s,l]=o.querySelectorAll("input");const i=o.querySelectorAll("[type='gamma']");const r=o.querySelector("feColorMatrix");const[,c,m]=o.querySelectorAll("div");const d=(e,t=3)=>Math.E**(Math.abs(e)**t*Math.LN2)-1;let n=1,t=1;const u=e=>{s.value=n=+e;for(const t of i){t.setAttribute("exponent",1+(n<0?-d(n/s.min):d(n/s.max,3)*s.max))}p()};s.addEventListener("input",e=>u(e.target.value));c.addEventListener("contextmenu",e=>{u(0);e.preventDefault()});document.querySelector("#room-menu").parentElement.appendChild(o);const p=()=>{a.classList.toggle("colorfilter",n!=0||t!=0)};const v=e=>{l.value=t=+e;r.setAttribute("values",1+d(t/l.max,3)*l.max);p()};l.addEventListener("input",e=>v(e.target.value));m.addEventListener("contextmenu",e=>{v(0);e.preventDefault()})}

Paste into the URL field of a new browser bookmark.

Bookmarklet in Chrome

Javascript

{
  const id = "gamma-slide";
  document.getElementById(id)?.remove();
  const div = document.createElement("div");
  const room = document.querySelector("#room-content");
  Object.assign(div, {
    id,
    innerHTML: '<div class="flex flex-col gap-1" style="position: absolute"><style>.colorfilter img[alt="preview"], .colorfilter canvas {filter: url(#gammafilter);} #gamma-slide>div {width: fit-content;pointer-events:auto} #gamma-slide{flex-basis: 100%;pointer-events:none;}</style><svg height="0" width="0" style="position: absolute;"><filter id="gammafilter"><feComponentTransfer><feFuncR type="gamma"/><feFuncG type="gamma"/><feFuncB type="gamma"/></feComponentTransfer><feColorMatrix type="saturate" values="1"/></filter></svg><div title="Gamma" class="hover:bg-accent transition-colors bg-background border border-input rounded-full flex items-center px-2 h-8 select-none"><svg class="svelte-fa-base" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg"><path d="M6 0A6 6 0 1 1 5.99 0ZM6 1A1 1 0 0 1 6 11Z" fill="currentcolor" fill-rule="evenodd"/></svg><input type="range" min="-5" max="20" step="any" value="0" list="gamma-snap" class="w-32 mx-1"><datalist id="gamma-snap"><option value="0"></option></datalist></div><div title="Saturation" class="hover:bg-accent transition-colors bg-background border border-input rounded-full flex items-center px-2 h-8 select-none"><svg class="svelte-fa-base" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg"><path d="m60 0c10 53 24 54 34 75 9.4 20-4.7 45-34 45zm0 0c-10 53-24 54-34 75-9.4 20 4.7 45 34 45z" fill="currentcolor"/></svg><input type="range" min="0" max="30" step="any" value="0" class="w-32 mx-1"></div></div>'
  });

  const [slider, satslider] = div.querySelectorAll("input");
  const funcs = div.querySelectorAll("[type='gamma']");
  const sat = div.querySelector("feColorMatrix");
  const [, gdiv, sdiv] = div.querySelectorAll("div");
  const parabola = (x, p = 3) => Math.E ** (Math.abs(x) ** p * Math.LN2) - 1;
  let g = 1, s = 1;
  const setGamma = (v) => {
    slider.value = g = +v;
    for (const func of funcs) {
      func.setAttribute("exponent", 1 + (g < 0 ? -parabola(g / slider.min) : parabola(g / slider.max, 3) * slider.max));
    }
    checkEnabled();
  };
  slider.addEventListener("input", e => setGamma(e.target.value));
  gdiv.addEventListener("contextmenu", e => { setGamma(0); e.preventDefault(); });
  document.querySelector("#room-menu").parentElement.appendChild(div);
  const checkEnabled = () => {
    room.classList.toggle("colorfilter", g != 0 || s != 0);
  };

  const setSaturation = v => {
    satslider.value = s = +v;
    sat.setAttribute("values", 1 + parabola(s / satslider.max, 3) * satslider.max);
    checkEnabled();
  };
  satslider.addEventListener("input", e => setSaturation(e.target.value));
  sdiv.addEventListener("contextmenu", e => { setSaturation(0); e.preventDefault(); });
}

Paste into the browser's developer console (F12)

 


Autokicker (old, probably broken)

Run as the host or mod (/mod username) after creating or rejoining a room.
A detailed user list is printed to the console whenever someone joins the room for easier regex edits.

Javascript

bannedregex kicks anyone with a name matching the regular expression.
bannedcolor kicks anyone with a matching color value. Color codes can be copied from the dev console output after any user joins.
#97ff41 is unused, change it to #97ff40 to kick on lime-green.

var bannedregex=/\(・へ・\)|\(。>﹏<。\)|\(`・ω・´\)|KILL YOURSELF|^\s+$/i,bannedcolor="#97ff41";function listen(e){function t(){let t=this.currentTarget instanceof WebSocket;if(!t)return o.call(this);let r=o.call(this);return Object.defineProperty(this,"data",{value:r}),e({data:r,socket:this.currentTarget,event:this}),r}if(e=e||console.log,void 0!==MessageEvent.prototype.hooked)return;let r=Object.getOwnPropertyDescriptor(MessageEvent.prototype,"data");const o=r.get;r.get=t,Object.defineProperty(MessageEvent.prototype,"data",r),MessageEvent.prototype.hooked=!0}function readusers(e){function t(e,t){{const r=e=>`#${e.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(e=>parseInt(e,10).toString(16).padStart(2,"0")).join("")}`;document.querySelectorAll('.user-button[title="Admin actions"]').forEach(o=>{o.parentElement.querySelector(".user-name").textContent===t&&r(o.parentElement.querySelector(".user-color").style.backgroundColor)===e&&(o.click(),document.querySelector(".dropdown-menu-user> .dropdown-item").click())})}}let r=e.data;if("string"==typeof r){let e=JSON.parse(r);if("users"===e.type){if(e.users.length>numUsers){console.log(`Userlist changed. Searching for color ${bannedcolor} or regex ${bannedregex}.\nID\tCOLOR\tNAME\n${e.users.map(e=>`${e.id}\t${e.color}\t"${e.name}"`).join("\n")}`);for(let r=0;r<e.users.length;r++){let o=e.users[r];(o.name.match(bannedregex)||o.color==bannedcolor)&&(console.log(`Kicking #${o.id} by ${o.color==bannedcolor?"color":"name"}!`),setTimeout(t,0,o.color,o.name))}}numUsers=e.users.length}}}listen(readusers);var numUsers=1;

Paste into the browser's developer console (F12)

As a Bookmarklet

javascript:var bannedregex=/\(・へ・\)|\(。>﹏<。\)|\(`・ω・´\)|KILL YOURSELF|^\s+$/i,bannedcolor="#97ff41";function listen(e){function t(){let t=this.currentTarget instanceof WebSocket;if(!t)return o.call(this);let r=o.call(this);return Object.defineProperty(this,"data",{value:r}),e({data:r,socket:this.currentTarget,event:this}),r}if(e=e||console.log,void 0!==MessageEvent.prototype.hooked)return;let r=Object.getOwnPropertyDescriptor(MessageEvent.prototype,"data");const o=r.get;r.get=t,Object.defineProperty(MessageEvent.prototype,"data",r),MessageEvent.prototype.hooked=!0}function readusers(e){function t(e,t){{const r=e=>`#${e.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/).slice(1).map(e=>parseInt(e,10).toString(16).padStart(2,"0")).join("")}`;document.querySelectorAll('.user-button[title="Admin actions"]').forEach(o=>{o.parentElement.querySelector(".user-name").textContent===t&&r(o.parentElement.querySelector(".user-color").style.backgroundColor)===e&&(o.click(),document.querySelector(".dropdown-menu-user> .dropdown-item").click())})}}let r=e.data;if("string"==typeof r){let e=JSON.parse(r);if("users"===e.type){if(e.users.length>numUsers){console.log(`Userlist changed. Searching for color ${bannedcolor} or regex ${bannedregex}.\nID\tCOLOR\tNAME\n${e.users.map(e=>`${e.id}\t${e.color}\t"${e.name}"`).join("\n")}`);for(let r=0;r<e.users.length;r++){let o=e.users[r];(o.name.match(bannedregex)||o.color==bannedcolor)&&(console.log(`Kicking #${o.id} by ${o.color==bannedcolor?"color":"name"}!`),setTimeout(t,0,o.color,o.name))}}numUsers=e.users.length}}}listen(readusers);var numUsers=1;

Paste into the URL field of a new browser bookmark.

Edit

Pub: 13 Sep 2025 19:11 UTC

Edit: 13 Sep 2025 19:34 UTC

Views: 1153

Auto Theme: Dark