dropdown.js callback is not a function on repeat focus
-
Bug:
dropdown.js—load_tlib()throws “callback is not a function” on repeat focus/hoverAffected asset:
https://cdn.gtranslate.net/widgets/latest/dropdown.js(the “dropdown” widget variant; other variants may share the same helper — worth checkingfloat.js/dwf.js/globe.jstoo).Root cause
load_tlib(callback)is defined as a general-purpose helper that lazy-injectslib.min.jsand then runs a callback once it’s loaded:function load_tlib(callback){
if(!window.gt_translate_script){
window.gt_translate_script = document.createElement('script');
gt_translate_script.src = 'https://cdn.gtranslate.net/widgets/latest/lib.min.js';
document.body.appendChild(gt_translate_script);
if(callback) gt_translate_script.addEventListener('load', callback, {once:true});
} else {
callback && callback();
}
}But it is also registered directly as a native DOM event listener:
e.addEventListener('pointerenter', load_tlib);
e.addEventListener('focusin', load_tlib);When the browser invokes an event listener, it always passes the triggering
Eventobject as the argument. So on everyfocusin/pointerenterfired this way,callbackinsideload_tlibis actually a nativeEvent, not a function.- First call (
window.gt_translate_scriptnot yet set): goes into theifbranch.gt_translate_script.addEventListener('load', callback, {once:true})is called withcallback= anEventobject. Per theaddEventListenerspec this is silently ignored (no crash, but also no real “on load” callback ever gets registered). - Any subsequent call on the same wrapper (user re-focuses or re-hovers the widget after the first interaction):
window.gt_translate_scriptnow exists, so execution hits theelsebranch:callback && callback();.callbackis again a truthyEventobject, so this attempts to invoke theEventinstance as a function — which throws:
Uncaught TypeError: callback is not a functionSteps to reproduce
- Load a page with the dropdown widget using default settings (
url_structure: 'none', so the interaction-based lazy-load path runs). - Move keyboard focus into the widget’s wrapper element once, or hover it with a pointer once — no error;
window.gt_translate_scriptgets set on this first pass. - Move focus/hover away and then back onto the wrapper a second time (or trigger
focusin/pointerenteron it again in any way) —Uncaught TypeError: callback is not a functionis thrown from thecallback && callback();line insideload_tlib. - This repeats on every subsequent focus/hover cycle on the same page load.
Suggested fix
load_tlibis used both as a plain callback-style helper (e.g. called manually insidedoGTranslatewith a real function) and directly as a native event listener — these two calling conventions are incompatible without normalizing the argument. Either:- (a) Wrap it before attaching as a listener, so it’s never invoked with the native
Eventas its argument:e.addEventListener('focusin', () => load_tlib());e.addEventListener('pointerenter', () => load_tlib()); - (b) Or guard the type inside
load_tlibitself, so any non-function argument is ignored instead of crashing:if (typeof callback === 'function') callback();(and the same guard before theaddEventListener('load', callback, ...)call).
Either change is small, localized to
load_tlib, and doesn’t affect the widget’s public config/settings. - First call (
You must be logged in to reply to this topic.