This is because of the this
problem. Per MDN documentation:
Code executed by setTimeout()
is called from a separate execution context to the function from which setTimeout
was called. The usual rules for setting the this
keyword for the called function apply, and if you have not set this
in the call or with bind
, it will default to the global (or window
) object in non–strict mode, or be undefined
in strict mode. It will not be the same as the this value for the function that called setTimeout
.
In JavaScript, there's a concept of "execution contexts", which are contexts that hold information about what is currently executing. There's a global execution context, and when a function is called, a new execution context is created. The this
value then depends on the execution context and is set according to the current execution context. Since setTimeout
creates a new execution context when the target function is called, this
does not represent the jQuery object from the DOM, but the global object (as it is by default, or undefined in strict mode). Thus when jQuery internally calls this.trigger
it is trying to call window.trigger
which does not exist.
Try using Function#bind
which explicitly sets the this
value:
setTimeout($('#selector').focus.bind($('#selector')), 100);
Or, as Ryan mentions:
setTimeout($.fn.focus.bind($('#selector')), 100);
Of course, you could, as squint mentioned, use an arrow function instead, which is faster than using bind
and more idiomatic:
setTimeout(() => $('#selector').focus(), 100);