Skip to content

Commit 3df0e65

Browse files
committed
Added click-draggability to chatgpt.alert() ↞ [auto-sync from https://github.com/KudoAI/chatgpt.js]
1 parent 7ba1e5e commit 3df0e65

File tree

1 file changed

+46
-17
lines changed

1 file changed

+46
-17
lines changed

starters/chrome/extension/lib/chatgpt.js

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,52 @@ const chatgpt = {
6464
// [ title/msg = strings, btns = [named functions], checkbox = named function, width (px) = int ] = optional
6565
// * Spaces are inserted into button labels by parsing function names in camel/kebab/snake case
6666

67+
// Init env context
6768
const scheme = chatgpt.isDarkMode() ? 'dark' : 'light',
6869
isMobile = chatgpt.browser.isMobile();
6970

71+
// Define event handlers
72+
const clickHandler = event => { // explicitly defined to support removal post-dismissal
73+
if (event.target == event.currentTarget || event.target.closest('[class*="-close-btn]')) dismissAlert() }
74+
const keyHandler = event => { // to dismiss active alert
75+
if (/^(?: |Space|Enter|Return|Esc)/.test(event.key) || [32, 13, 27].includes(event.keyCode)) {
76+
for (const alertId of alertQueue) { // look to handle only if triggering alert is active
77+
const alert = document.getElementById(alertId)
78+
if (alert && alert.style.display !== 'none') { // active alert found
79+
if (event.key.includes('Esc') || event.keyCode == 27) // esc pressed
80+
dismissAlert() // dismiss alert & do nothing
81+
else if (/^(?: |Space|Enter|Return)/.test(event.key) || [32, 13].includes(event.keyCode)) {
82+
const mainButton = alert.querySelector('.modal-buttons').lastChild // look for main button
83+
if (mainButton) { mainButton.click() ; event.preventDefault() } // click if found
84+
} return
85+
}}}}
86+
const dragHandlers = {
87+
mousedown(event) { // find modal, attach listeners, init XY offsets
88+
if (event.button != 0) return // prevent non-left-click drag
89+
if (getComputedStyle(event.target).cursor == 'pointer') return // prevent drag on interactive elems
90+
chatgpt.draggableElem = event.currentTarget
91+
chatgpt.draggableElem.style.cursor = 'grabbing'
92+
event.preventDefault(); // prevent sub-elems like icons being draggable
93+
['mousemove', 'mouseup'].forEach(event => document.addEventListener(event, dragHandlers[event]))
94+
const draggableElemRect = chatgpt.draggableElem.getBoundingClientRect()
95+
dragHandlers.offsetX = event.clientX - draggableElemRect.left +21
96+
dragHandlers.offsetY = event.clientY - draggableElemRect.top +12
97+
},
98+
mousemove(event) { // drag modal
99+
if (chatgpt.draggableElem) {
100+
const newX = event.clientX - dragHandlers.offsetX,
101+
newY = event.clientY - dragHandlers.offsetY
102+
Object.assign(chatgpt.draggableElem.style, { left: `${newX}px`, top: `${newY}px` })
103+
}
104+
},
105+
mouseup() { // remove listeners, reset chatgpt.draggableElem
106+
chatgpt.draggableElem.style.cursor = 'inherit';
107+
['mousemove', 'mouseup'].forEach(event =>
108+
document.removeEventListener(event, dragHandlers[event]))
109+
chatgpt.draggableElem = null
110+
}
111+
}
112+
70113
// Create modal parent/children elements
71114
const modalContainer = document.createElement('div');
72115
modalContainer.id = Math.floor(chatgpt.randomFloat() * 1000000) + Date.now();
@@ -96,6 +139,7 @@ const chatgpt = {
96139

97140
// Alert styles
98141
+ '.chatgpt-modal > div {'
142+
+ 'position: absolute ;' // to be click-draggable
99143
+ 'opacity: 0 ;' // to fade-in
100144
+ `border: 1px solid ${ scheme == 'dark' ? 'white' : '#b5b5b5' };`
101145
+ `color: ${ scheme == 'dark' ? 'white' : 'black' };`
@@ -231,26 +275,11 @@ const chatgpt = {
231275
}, 100) // delay for transition fx
232276
}
233277

234-
// Define click/key handlers
235-
const clickHandler = event => { // explicitly defined to support removal post-dismissal
236-
if (event.target == event.currentTarget || event.target.closest('[class*="-close-btn]')) dismissAlert(); };
237-
const keyHandler = event => { // to dismiss active alert
238-
if (/^(?: |Space|Enter|Return|Esc)/.test(event.key) || [32, 13, 27].includes(event.keyCode)) {
239-
for (const alertId of alertQueue) { // look to handle only if triggering alert is active
240-
const alert = document.getElementById(alertId);
241-
if (alert && alert.style.display !== 'none') { // active alert found
242-
if (event.key.includes('Esc') || event.keyCode == 27) // esc pressed
243-
dismissAlert(); // dismiss alert & do nothing
244-
else if ([' ', 'Spacebar', 'Enter', 'Return'].includes(event.key) || [32, 13].includes(event.keyCode)) { // space/enter pressed
245-
const mainButton = alert.querySelector('.modal-buttons').lastChild; // look for main button
246-
if (mainButton) { mainButton.click(); event.preventDefault(); } // click if found
247-
} return;
248-
}}}};
249-
250-
// Add listeners to dismiss alert
278+
// Add listeners
251279
const dismissElems = [modalContainer, closeBtn, closeSVG, dismissBtn];
252280
dismissElems.forEach(elem => elem.onclick = clickHandler);
253281
document.addEventListener('keydown', keyHandler);
282+
modal.onmousedown = dragHandlers.mousedown // enable click-dragging
254283

255284
// Define alert dismisser
256285
const dismissAlert = () => {

0 commit comments

Comments
 (0)