我想覆盖focus()
JavaScript 中所有 HTML 元素的函数。
我怎么做?
该问题询问如何覆盖 HTML 元素的.focus()
方法,因此将首先回答。但是,还有其他方法可以触发对元素的“关注”,下面将讨论覆盖这些方法。
另请注意,覆盖全局原型可能不是一个好主意。
.focus()
HTML 元素上的方法HTMLElement
您可以通过修改其原型来覆盖 all 的焦点功能。
HTMLElement.prototype.focus = function () {
// ... do your custom stuff here
}
如果您仍想运行默认焦点行为并运行自定义覆盖,您可以执行以下操作:
let oldHTMLFocus = HTMLElement.prototype.focus;
HTMLElement.prototype.focus = function () {
// your custom code
oldHTMLFocus.apply(this, arguments);
};
这以与覆盖该方法类似的方式完成.focus()
。但是,在这种情况下,我们将针对EventTarget
构造函数并修改addEventListener
原型:
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);
};
如果您根本不想要原始行为,则可以删除func
调用 ( func(e)
)。
onfocus
属性设置的焦点事件这样做实际上非常棘手,并且很可能会有一些无法预料的限制。也就是说,我找不到通过修改原型等来覆盖它的方法。我可以完成这项工作的唯一方法是使用MutationObservers。它通过查找所有具有该属性的元素来工作,onfocus
并将第一个函数设置为运行覆盖函数:
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}`);
});
}
如果您想完全阻止原始 onfocus 触发其事件,您可以在任何突变更改时完全清空 onfocus 属性,并将值设置为您想要的函数。
(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()">
在纯 JS 中:
HTML:
<input id="test" type="textfield" />
JS:
var myInput = document.getElementById("test");
myInput.addEventListener("focus",deFocus(myInput),true);
function deFocus(element) {
element.setAttribute('readonly','readonly');
return false;
}
工作小提琴
在 JQuery 中:
HTML
<input id="test" type="textfield" />
jQuery
$('#test').focus(function() {
$(this).blur();
});
工作小提琴
您可以将其添加EventListener
到您想要的任何内容、类、id 等,并通过函数运行它或触发其他东西来解锁它们。JQuery 也可以非常顺利地处理这个问题,但如果你走那条路,我建议使用一个类作为选择器,然后你可以动态添加和删除该类以禁用焦点。