I want to overwrite the function focus()
for all HTML elements in JavaScript.
How do I do that?
The question asks for just how to override the .focus()
method for HTML elements, so that will be answered first. There are however, other ways to trigger "focus" on elements, and overriding those methods are discussed below.
Please also note, it is probably not a good idea to override global prototypes.
.focus()
method on HTML elementsYou can override the focus function for all HTMLElement
's by modifying its prototype.
HTMLElement.prototype.focus = function () {
// ... do your custom stuff here
}
If you still want to run the default focus behavior and run your custom override, you can do the following:
let oldHTMLFocus = HTMLElement.prototype.focus;
HTMLElement.prototype.focus = function () {
// your custom code
oldHTMLFocus.apply(this, arguments);
};
This is done in a similar fashion to overriding the .focus()
method. However, in this case, we will target the EventTarget
constructor and modify the addEventListener
prototype:
let oldAddListener = HTMLElement.prototype.addEventListener;
EventTarget.prototype.addEventListener = function () {
let scope = this;
let func = arguments[1];
if (arguments[0] === 'focus') {
arguments[1] = function (e) {
yourCustomFunction(scope);
func(e);
};
}
oldAddListener.apply(this, arguments);
};
If you don't want original behavior at all, you can remove the func
call (func(e)
).
onfocus
attributeDoing this is actually quite tricky, and will most likely have some unforseen limitations. That said, I could not find a way to override this by modifying prototypes, etc. The only way I could get this work was by using MutationObservers. It works by finding all elements that have the attribute onfocus
and it sets the first function to run to your override function:
let observer = new MutationObserver(handleOnFocusElements);
let observerConfig = {
attributes: true,
childList: true,
subtree: true,
attributeFilter: ['onfocus']
};
let targetNode = document.body;
observer.observe(targetNode, observerConfig);
function handleOnFocusElements() {
Array
.from(document.querySelectorAll('[onfocus]:not([onfocus*="yourCustomFunction"])'))
.forEach(element => {
let currentCallbacks = element.getAttribute('onfocus');
element.setAttribute('onfocus', `yourCustomFunction(this); return; ${currentCallbacks}`);
});
}
If you want to stop the original onfocus from firing its events completely, you can just empty the onfocus attribute entirely on any mutation changes, and just set the value to your desired function.
(function() {
window.yourCustomFunction = function(target) {
console.log('OVERRIDE on element', target);
};
let observer = new MutationObserver(handleOnFocusElements);
let observerConfig = {
attributes: true,
childList: true,
subtree: true,
attributeFilter: ['onfocus']
};
let targetNode = document.body;
// Start overriding methods
// The HTML `.focus()` method
let oldHTMLFocus = HTMLElement.prototype.focus;
HTMLElement.prototype.focus = function() {
yourCustomFunction(this);
oldHTMLFocus.apply(this, arguments);
};
// Event Target's .addEventListener prototype
let oldAddListener = HTMLElement.prototype.addEventListener;
EventTarget.prototype.addEventListener = function() {
let scope = this;
let func = arguments[1];
if (arguments[0] === 'focus') {
arguments[1] = function(e) {
yourCustomFunction(scope);
func(e);
};
}
oldAddListener.apply(this, arguments);
};
// Handle the onfocus attributes
function handleOnFocusElements() {
Array
.from(document.querySelectorAll('[onfocus]:not([onfocus*="yourCustomFunction"])'))
.forEach(element => {
let currentCallbacks = element.getAttribute('onfocus');
element.setAttribute('onfocus', `yourCustomFunction(this); return; ${currentCallbacks}`);
});
}
window.addEventListener('load', () => {
handleOnFocusElements();
observer.observe(targetNode, observerConfig);
});
})();
let input = document.querySelector('input');
input.addEventListener('focus', function() {
console.log('Add Event Listener Focus');
});
function attributeHandler() {
console.log('Called From the Attribute Handler');
}
<input type="text" onfocus="attributeHandler()">
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With