Last active
April 14, 2025 15:51
-
-
Save DarrenSem/0d9da09fc5a7b95abcc0df95d65b02c7 to your computer and use it in GitHub Desktop.
width.js - Bookmarklet for OpenAI playground to fix maxWidth of "Configure" panel (due to latest layout update); add as browser Favorite then click to toggle visibility
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// width.js - Bookmarklet for OpenAI playground to fix maxWidth of "Configure" panel (due to latest layout update); add as browser Favorite then click to toggle visibility | |
// https://gist.github.com/DarrenSem/0d9da09fc5a7b95abcc0df95d65b02c7 | |
// 05Apr2025 234pm: will now FIRST close "Configure" if already opened as slide-in panel version (could have BOTH versions visible!) | |
// 2016 char javascript:void function(){const a=null,b="innerText",c=(b,c=1)=>{let d=b;for(;c--&&(d=d?.parentElement););return d||a},d=(a,b)=>a.test(b??""),e=()=>{const a=document.querySelectorAll("button > span > span + span.sr-only"),c=Array.from(a).filter((a,c)=>{const e=a[b],f=d(/Configure/,e);return console.log({isTextConfigure:f,text:e,el:a,i:c}),f});return console.log({collConfigureButtons:c,collButtonSpans:a,selButtonSpans:"button > span > span + span.sr-only"}),c},f=e=>{let f,g,h=a;const i=c(e,1),j=i.querySelectorAll("button");for(f of j)if(g=f.dataset,console.log({dataset:g,elButton:f}),!d(/\S/,f[b])&&"secondary"==g?.color&&"md"==g?.size&&"md"==g?.gutterSize){h=f;break}return console.log({elCloseButton:h,collButtons:j,elGrandParent:i,elParent:e}),h},g=500,h=a=>{const b=a[0],d=c(b,10);return d?console.log({configureDiv:d}):console.log({elConfigureFirst:b,collConfigureButtons:a}),d},i=location,j=()=>i.W,k=a=>{i.W=a};(async()=>new Promise(a=>{let b,h=e(),i=0;for(b of h){const a=c(b,11),e=a?.className,g=!d(/flex/,e)&&!d(/h-full/,e);console.log({classText:e,isSlider:g,elParentDiv:a,elConfigure:b}),g&&++i&&f(a)?.click?.()}return console.log({sliderCount:i,collConfigureButtonsOriginal:h,MS_BEFORE_CLOSING_CONFIGURATION_SLIDER:g}),setTimeout(()=>a(e()),i&&g)}))().then(b=>{const c=h(b);if(!c)return;const d=getComputedStyle(c).maxWidth;console.log({computedMaxWidth:d});const e=d=="0px",f=c.style;e?(console.log("\nisShrunk="+e+"; [restore previous value]; computedMaxWidth via getComputedStyle() WAS "+0+"px; used getMaxWidth() to GET stored MAXWIDTH via getMaxWidth() which was "+j()+" (before we expand it back)"),f.removeProperty("max-width"),f.removeProperty("width"),k(a)):(k("none"==d?"":d),console.log("\nisShrunk="+e+"; [store current value]; computedMaxWidth via getComputedStyle() was ["+d+"] aka NOT "+0+"px; used setMaxWidth() to store MAXWIDTH so it has now been SET to "+j()+" (before shrinking it)"),f.setProperty("max-width","0px","important"),f.setProperty("width","0px","important"))})}(); | |
// 05Apr2025 1145am: logic rewrite so it now is always able to getDivToResize() - by locating "Configure" button (and then moving "up" 10 levels) | |
// 1226 char javascript:void function(){const a=(a,b=1)=>{let c=a;for(;b--&&(c=c?.parentElement););return c||null},b=()=>{const b=Array.from(document.querySelectorAll("button > span > span + span.sr-only")),c=b.filter((a,b)=>{const c=a.innerText,d="Configure"==c;return console.log({isTextConfigure:d,text:c,i:b,el:a}),d}),d=c[0],e=a(d,10);return e?console.log({configureDiv:e}):console.log({elConfigureFirst:d,collConfigure:c,collButtonSpans:b}),e},c=location,d=()=>c.W,e=a=>{c.W=a};(()=>{const a=b();if(!a)return;const c=getComputedStyle(a).maxWidth;console.log({computedMaxWidth:c});const f=c=="0px",g=a.style;f?(console.log("\nisSmol="+f+"; [restore previous value]; computedMaxWidth via getComputedStyle() WAS "+0+"px; used getMaxWidth() to GET stored MAXWIDTH via getMaxWidth() which was "+d()+" (so we can expand it back)"),g.removeProperty("max-width"),g.removeProperty("width"),e(null)):(e("none"===c?"":c),console.log("\nisSmol="+f+"; [store current value]; computedMaxWidth via getComputedStyle() was ["+c+"] aka NOT "+0+"px; used setMaxWidth() to store MAXWIDTH so it has now been SET to "+d()+" (before shrinking it)"),g.maxWidth=0,g.setProperty("max-width","0px","important"),g.setProperty("width","0px","important"))})()}(); | |
const NULL = null; | |
const TEXT_PROP = "innerText"; | |
// get PARENT element (# levels above startingElement) | |
const above = (startingElement, levels = 1) => { | |
let el = startingElement; | |
while (levels-- && (el = el?.parentElement)); | |
return el || NULL; | |
}; | |
const testRegEx = (pattern, str) => { | |
return pattern.test(str ?? ""); | |
}; | |
const getConfigureButtons = () => { | |
const selButtonSpans = "button > span > span + span.sr-only"; | |
const collButtonSpans = document.querySelectorAll(selButtonSpans); | |
const collConfigureButtons = Array.from(collButtonSpans) | |
.filter( (el, i) => { | |
const text = el[TEXT_PROP]; | |
const isTextConfigure = testRegEx(/Configure/, text); | |
console.log({ isTextConfigure, text, el, i }); | |
return isTextConfigure; | |
} ); | |
console.log({ collConfigureButtons, collButtonSpans, selButtonSpans }); | |
return collConfigureButtons; | |
}; | |
const getCloseButton = (elParent) => { | |
let elCloseButton = NULL; | |
let elButton; | |
let dataset; | |
const elGrandParent = above(elParent, 1); | |
const collButtons = elGrandParent.querySelectorAll("button"); | |
for (elButton of collButtons) { | |
dataset = elButton.dataset; | |
console.log({ dataset, elButton }); | |
if ( | |
!testRegEx(/\S/, elButton[TEXT_PROP]) | |
&& dataset?.color == "secondary" | |
&& dataset?.size == "md" | |
&& dataset?.gutterSize == "md" | |
) { | |
elCloseButton = elButton; | |
break; | |
}; | |
}; | |
console.log({ elCloseButton, collButtons, elGrandParent, elParent }); | |
return elCloseButton; | |
}; | |
const MS_BEFORE_CLOSING_CONFIGURATION_SLIDER = 500; | |
const closeConfigureSlider = async () => | |
{ | |
// close "Configure" if already opened as slide-in panel version | |
// NOTE: this is required because it is possible to have BOTH versions visible at the same time! | |
// 1. check if any of the "Configure" buttons are located inside the slide-in panel version | |
// 2. early exit if not, otherwise wait for completion of auto-clicking the "🡢|" button to close it (slide-out) | |
return new Promise( resolve => { | |
let elConfigure; | |
let collConfigureButtonsOriginal = getConfigureButtons(); | |
let sliderCount = 0; | |
for (elConfigure of collConfigureButtonsOriginal) { | |
// get the "Configure" button's PARENT element (11 levels above us), to identify if the "slide-in" version | |
// (based on elParentDiv's classText NOT containing "flex h-full", and then the label-less button's unique color + size + gutterSize) | |
const elParentDiv = above(elConfigure, 11); | |
const classText = elParentDiv?.className; | |
const isSlider = !testRegEx(/flex/, classText) && !testRegEx(/h-full/, classText); | |
console.log({ classText, isSlider, elParentDiv, elConfigure }); | |
if (isSlider && ++sliderCount) { | |
getCloseButton(elParentDiv)?.click?.(); | |
}; | |
}; | |
console.log({ sliderCount, collConfigureButtonsOriginal, MS_BEFORE_CLOSING_CONFIGURATION_SLIDER }); | |
return setTimeout( | |
() => resolve( getConfigureButtons() ), | |
sliderCount && MS_BEFORE_CLOSING_CONFIGURATION_SLIDER | |
); | |
} ); | |
}; | |
const getDivToResize = (collConfigureButtons) => { | |
const elConfigureFirst = collConfigureButtons[0]; | |
// get the "Configure" button's PARENT element (10 levels above us) | |
const configureDiv = above(elConfigureFirst, 10); | |
if (!configureDiv) { | |
console.log({ elConfigureFirst, collConfigureButtons }); | |
} else { | |
console.log({ configureDiv }); | |
// RESULT = <div class="gEVJr"> (parent = <div class="flex h-full">, grandparent = <div class="uNbBQ" style="--composer-height: 124px;">) | |
}; | |
return configureDiv; | |
}; | |
// temp "storage" hack; easier to troubleshoot console.log(document.location) than console.log(globalThis) | |
const loc = location; | |
const getMaxWidth = () => { | |
return loc.W; | |
}; | |
const setMaxWidth = (value) => { | |
loc.W = value; | |
}; | |
const toggleMaxWidth = (collConfigureButtons) => { | |
const newSize = 0; | |
const configureDiv = getDivToResize(collConfigureButtons); | |
if (!configureDiv) { | |
return; | |
}; | |
const computedMaxWidth = getComputedStyle(configureDiv).maxWidth; | |
console.log({ computedMaxWidth }); | |
const isShrunk = computedMaxWidth == newSize + "px"; | |
const style = configureDiv.style; | |
if (isShrunk) { | |
// restore previous value (so we get TOGGLE effect) | |
console.log( "\n" | |
+ "isShrunk=" + isShrunk | |
+ "; [restore previous value]" | |
+ "; computedMaxWidth via getComputedStyle() WAS " + newSize + "px" | |
+ "; used getMaxWidth() to GET stored MAXWIDTH via getMaxWidth() which was " + getMaxWidth() + " (before we expand it back)" | |
); | |
// remove the inline style's max-width prop | |
style.removeProperty("max-width"); | |
// clean up the inline width prop too | |
style.removeProperty("width"); | |
setMaxWidth(NULL); | |
} else { | |
// store current value (so we get TOGGLE effect) | |
setMaxWidth(computedMaxWidth != "none" ? computedMaxWidth : ""); | |
console.log( "\n" | |
+ "isShrunk=" + isShrunk | |
+ "; [store current value]" | |
+ "; computedMaxWidth via getComputedStyle() was [" + computedMaxWidth + "] aka NOT " + newSize + "px" | |
+ "; used setMaxWidth() to store MAXWIDTH so it has now been SET to " + getMaxWidth() + " (before shrinking it)" | |
); | |
// forcefully set the max-width prop to 50px, even if !important is used | |
style.setProperty("max-width", newSize + "px", "important"); | |
// set the width prop to 50px as well, just in case | |
style.setProperty("width", newSize + "px", "important"); | |
}; | |
}; | |
// console.clear(); | |
closeConfigureSlider().then(toggleMaxWidth); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://gist.github.com/DarrenSem/4d37711fb71a484b6ed2356c60e3c94a = above.js (PARENT element, levels = #) + next.js (SIBLING element, levels = #) helper functions instead of foo.parentElement.parentElement.parentElement etc.