Skip to content

Instantly share code, notes, and snippets.

@artginzburg
Last active April 5, 2022 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save artginzburg/791ea42fb687bc7ca0144e7cc4a1f925 to your computer and use it in GitHub Desktop.
Save artginzburg/791ea42fb687bc7ca0144e7cc4a1f925 to your computer and use it in GitHub Desktop.
A drop-in patch for Firefox "dragend" and other DragEvent events.
/* eslint-disable func-names, no-underscore-dangle, no-useless-escape, no-mixed-operators */
/**
* A drop-in patch for Firefox "dragend" and other {@link DragEvent} events.
* @author Codesmith <https://bugzilla.mozilla.org/show_bug.cgi?id=505521#c87>
* @see {@link https://bugzilla.mozilla.org/show_bug.cgi?id=505521 Bugzilla: Bug #505521}
*
* @version 0.1.0
* @link https://gist.github.com/artginzburg/791ea42fb687bc7ca0144e7cc4a1f925
* @example React.useEffect(firefoxDragEventPatch, []);
*/
export function firefoxDragEventPatch() {
if (
/Firefox\/\d+[\d\.]*/.test(navigator.userAgent) &&
typeof window.DragEvent === 'function' &&
typeof window.addEventListener === 'function'
) {
(function () {
// patch for Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=505521
let cx;
let cy;
let px;
let py;
let ox;
let oy;
let sx;
let sy;
let lx;
let ly;
function update(e) {
cx = e.clientX;
cy = e.clientY;
px = e.pageX;
py = e.pageY;
ox = e.offsetX;
oy = e.offsetY;
sx = e.screenX;
sy = e.screenY;
lx = e.layerX;
ly = e.layerY;
}
function assign(e) {
e._ffix_cx = cx;
e._ffix_cy = cy;
e._ffix_px = px;
e._ffix_py = py;
e._ffix_ox = ox;
e._ffix_oy = oy;
e._ffix_sx = sx;
e._ffix_sy = sy;
e._ffix_lx = lx;
e._ffix_ly = ly;
}
window.addEventListener('mousemove', update, true);
window.addEventListener('dragover', update, true);
// bug #505521 identifies these three listeners as problematic:
// (although tests show 'dragstart' seems to work now, keep to be compatible)
window.addEventListener('dragstart', assign, true);
window.addEventListener('drag', assign, true);
window.addEventListener('dragend', assign, true);
const me = Object.getOwnPropertyDescriptors(window.MouseEvent.prototype);
const ue = Object.getOwnPropertyDescriptors(window.UIEvent.prototype);
function getter(prop, repl) {
return function () {
return (
(me[prop] && me[prop].get.call(this)) || Number(this[repl]) || 0
);
};
}
function layerGetter(prop, repl) {
return function () {
return this.type === 'dragover' && ue[prop]
? ue[prop].get.call(this)
: Number(this[repl]) || 0;
};
}
const descriptorClientX = Object.getOwnPropertyDescriptor(
window.DragEvent.prototype,
'clientX',
);
if (!descriptorClientX || descriptorClientX.configurable) {
Object.defineProperties(window.DragEvent.prototype, {
clientX: { get: getter('clientX', '_ffix_cx') },
clientY: { get: getter('clientY', '_ffix_cy') },
pageX: { get: getter('pageX', '_ffix_px') },
pageY: { get: getter('pageY', '_ffix_py') },
offsetX: { get: getter('offsetX', '_ffix_ox') },
offsetY: { get: getter('offsetY', '_ffix_oy') },
screenX: { get: getter('screenX', '_ffix_sx') },
screenY: { get: getter('screenY', '_ffix_sy') },
x: { get: getter('x', '_ffix_cx') },
y: { get: getter('y', '_ffix_cy') },
layerX: { get: layerGetter('layerX', '_ffix_lx') },
layerY: { get: layerGetter('layerY', '_ffix_ly') },
});
}
})();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment