在FireFox中文本输入字段变为活动(而不是onfocus)时触发事件

时间:2014-08-24 23:15:39

标签: javascript dom firefox-addon-sdk

我正在尝试检测文本输入字段何时处于活动状态。我最初使用onfocu实现,但是,当窗口不再是前景窗口时,会触发onblur事件。这在我的申请中会产生意想不到的后果。标识为DOMActivate的{​​{1}}事件,but in firefox this is NOT fired on text:input fields

  

文档中一次只能激活一个元素。一个活跃的   element不一定有焦点,但有焦点的元素是   始终是文档中的活动元素。例如,一个活跃的   窗口中不是前台窗口的元素没有   对焦。

     

开火:按钮,输入:按钮,输入:复选框,输入:文件,输入:图像,输入:密码,输入:收音机,输入:复位,输入:提交

     

不会触发:输入:text,select,textarea

我还使用input事件进行了测试。但是,只有在实际输入框中时才会触发此事件。对于我的应用程序,我需要捕获文本输入字段在键入的任何内容之前处于活动状态,并且当窗口不在前台时它无法更改状态。

我认为可能有一种方法可以使用变异观察器来执行此操作,然后检查该变异元素是否具有activeElement,但这似乎需要更多开销。我不认为有一个lostActiveElement事件,所以这也会增加一些额外的跟踪。有更直接/有效的方法吗?

这是使用addon sdk的firefox附加组件。

2 个答案:

答案 0 :(得分:1)

我使用如下突变显示器得到了可用的结果:

var activeInputObserver = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if(document.activeElement.tagName === "INPUT"){     
            // do stuff based on this being the active input                
        }else{  
            // the else event is being used like a lost focus event now
            // however, it now makes it global as opposed to per input  
        }       
    });    
});

var activeInputConfig = { attributes: true, childList: true, characterData: true, subtree: true }
var activeInputTarget = document.querySelector('body'); 

if(target != null){ 
    activeInputObserver.observe(activeInputTarget, activeInputConfig);
}

我在身体上使用突变观察者并使用subtree: true监视所有后代。这并不理想,因为现在只要元素变为活动状态,它就会运行我的所有逻辑,而不是仅在输入字段上运行。它需要制作一些变量并跟踪它而不是仅仅依赖于每个元素事件。无法通过这种方式检测到没有长寿的元素。这种作品,但并不是很理想。

我试图在每个输入字段上放置和变异观察者,但成为活动元素不会触发变异:

var activeInputObservers = [];
inputFields = document.querySelectorAll("input");
for each (var inputField in inputFields){

    var activeInputConfig = { attributes: true, childList: true, characterData: true, subtree: true }
    var activeInputTarget = inputField;

    var thisObserver = new MutationObserver(function(mutations) {
    activeInputObservers.push(thisObserver);
        mutations.forEach(function(mutation) {
            console.log("active element:" + JSON.stringify(document.activeElement)   );         
        });    
    });

    thisObserver.observe(activeInputTarget, activeInputConfig);     
}

使用上面的代码,只需单击元素或选中它就不会触发可观察到的更改(在字段中输入)。

activeElement是文档的属性,因此您需要监视文档的更改;再次,您仍然无法捕获特定元素中的事件和事件,因此您需要在每次活动元素更改时运行操作。看起来输入字段本身没有任何变化。

答案 1 :(得分:0)

根据@dandavis的一些建议并玩游戏,我发现当窗口不在焦点时document.activeElement不会取消设置。如果我在输入字段blur事件中设置条件,它将不会冒泡到窗口。我担心这会破坏窗口在页面处于背景时窗口接收模糊的其他脚本,但是,出于我的插件的目的,这可以防止模糊操作发生。

inputFields = document.querySelectorAll("input");
for each (var inputField in inputFields){

    inputField.onfocus = function(){
        //do something when the input field get's focus
    }   

    inputField.onblur = function(e){

        inputStillActive = false;
        if(this === document.activeElement){ //this will be the input field element
            inputStillActive = true;
            return; //or do something else knowing that inputStillActive will be true 
        }

    }

}

不应该提早回来,应该可以采取一些行动。如果你只做其他或不等于你应该能够考虑到#34;真的失去了焦点"而不是"仍然活跃,但窗口失去焦点"。

在我的情况下,如果我有一个活动的输入元素,我想捕获用于KeePass autotype的值,所以我将当前输入字段名称和id添加到窗口标题,所以简化版本是像这样的东西:

var activeInputAttributes = {};

inputFields = document.querySelectorAll("input");
for each (var inputField in inputFields){

    inputField.onfocus = function(){

        activeInputAttributes["name"] = this.getAttribute("name");
        activeInputAttributes["id"] = this.getAttribute("id");

        console.log(activeInputAttributes);

    }   

    inputField.onblur = function(e){

        inputStillActive = false;
        if(this !== document.activeElement){
            activeInputAttributes["name"] = null;
            activeInputAttributes["id"] = null; 
        }

        console.log(activeInputAttributes);

    }

}

当我实际离开输入字段时,activeInputAttributes仅打印到null,当我将窗口放在后台时,为null,这意味着值仍然可用于自动类型。我认为这比我在原始答案中观察更为理想。