如何确定给定 div 中的某些内容是否具有焦点?
How to find out if something in a given div has focus?
使用 angularjs,我正在显示这样的 2 级列表
- first main item
- first subitem of the first main item
- second subitem of the first main item
- AN EMPTY ITEM AS PLACEHOLDER TO ENTER THE NEXT SUBITEM
- second main item
- first subitem of the second main item
- second subitem of the second main item
- AN EMPTY ITEM AS PLACEHOLDER TO ENTER THE NEXT SUBITEM
为了节省位置,我想仅在相应 div
中的任何内容具有焦点时才显示 PLACEHOLDER,因此只有一个这样的占位符。我知道有 ngFocus
,但我更喜欢比创建大量事件处理程序更简单的方法。也许是这样的:
<div ng-focus-model="mainItem.hasFocus" ng-repeat="mainItem in list">
... main item line
... all subitems
</div>
单向绑定就足够了,因为我不需要设置焦点。
不幸的是,唯一可靠的方法是响应输入中的 focus\blur 事件...这是获得通知的唯一方法。
您可以将隐藏的输入作为每个 div 中的第一个元素并在其上放置 NgFocus 属性,但这仅在用户按 Tab 键进入时才有效。
这里的问题如下;我们希望避免为每个 child 添加事件侦听器,而是仅将其添加到 parent。 parent 将负责采取适当的行动。对此的一般解决方案是使用均匀传播(委托)。我们只将一个侦听器附加到 parent,当 child 上发生事件时(在本例中关注 input 元素),它将冒泡到 parent 和 parent 将执行侦听器。
指令如下:
app.directive('ngFocusModel', function () {
return function (scope, element) {
var focusListener = function () {
scope.hasFocus = true;
scope.$digest();
};
var blurListener = function () {
scope.hasFocus = false;
scope.$digest();
};
element[0].addEventListener('focus', focusListener, true);
element[0].addEventListener('blur', blurListener, true);
};
});
该指令侦听事件并相应地在范围内设置值,因此我们可以进行条件更改。
这里有几点需要注意。
focus
和 blur
事件没有 "bubble",我们需要使用 "event capturing" 来捕捉它们。这就是为什么不使用 element.on('focus/blur')
(它不允许捕获,afaik)而是使用 addEventListener
方法的原因。此方法允许我们通过相应地将第三个参数设置为 false
或 true
来指定侦听器是否将在 "event bubbling" 或 "event capturing" 上执行。
我们本可以使用 focusin
和 focusout
事件 "bubble",不幸的是 Firefox (focusin and focusout) 不支持这些事件。
这里是 plunker 的实现。
更新:
在我看来,这可以通过使用 :focus
pseudo-class 的纯 CSS 来完成,唯一的缺点是占位符需要相对于输入元素处于适当的位置(兄弟) .参见 codepen。
我创建了一个小指令,可用于您的需要:
app.directive('childFocus', function($window){
var registered = [];
// observing focus events in single place
$window.addEventListener('focus', function(event){
registered.forEach(function(element){
if(element.contains(event.target)){
// if element with focus is a descendant of the
// element with our directive then action is triggered
element._scope.$apply(element._scope.action);
}
});
}, true)
return {
scope : {
action : '&childFocus' // you can pass whatever expression here
},
link : function(scope, element){
// keep track ref to scope object
element[0]._scope = scope;
// (probably better would be to register
// scope with attached element)
registered.push(element[0]);
scope.$on('destroy', function(){
registered.splice(registered.indexOf(element[0]),1);
});
}
}
});
您可以使用 '.parent *'
选择器的 focus
事件来捕获任何焦点事件,然后遍历每个父 DIV
并使用 :focus
JQuery 选择器检查具有焦点的子元素,然后将 class 添加到父元素 DIV
并将该 class 用于 show/hide 占位符(see this jsfiddle):
$(function(){
$('.parent *').focus(function(){
$('.selected').removeClass('selected');
$('.parent').each(function(index, el){
(function($el){
setTimeout(function(){
console.log($el.attr('id'));
if($el.find(':focus').length){
$el.addClass('selected');
}
});
})($(el));
});
});
});
.parent{
padding:1rem;
margin:1rem;
border:solid 1px green;
}
.selected{
border:solid 1px red;
}
.parent .placeholder{
display:none;
}
.parent.selected .placeholder{
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='parent' id='div1'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
<div class='parent' id='div2'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
<div class='parent' id='div3'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
<div class='parent' id='div4'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
使用 angularjs,我正在显示这样的 2 级列表
- first main item
- first subitem of the first main item
- second subitem of the first main item
- AN EMPTY ITEM AS PLACEHOLDER TO ENTER THE NEXT SUBITEM
- second main item
- first subitem of the second main item
- second subitem of the second main item
- AN EMPTY ITEM AS PLACEHOLDER TO ENTER THE NEXT SUBITEM
为了节省位置,我想仅在相应 div
中的任何内容具有焦点时才显示 PLACEHOLDER,因此只有一个这样的占位符。我知道有 ngFocus
,但我更喜欢比创建大量事件处理程序更简单的方法。也许是这样的:
<div ng-focus-model="mainItem.hasFocus" ng-repeat="mainItem in list">
... main item line
... all subitems
</div>
单向绑定就足够了,因为我不需要设置焦点。
不幸的是,唯一可靠的方法是响应输入中的 focus\blur 事件...这是获得通知的唯一方法。
您可以将隐藏的输入作为每个 div 中的第一个元素并在其上放置 NgFocus 属性,但这仅在用户按 Tab 键进入时才有效。
这里的问题如下;我们希望避免为每个 child 添加事件侦听器,而是仅将其添加到 parent。 parent 将负责采取适当的行动。对此的一般解决方案是使用均匀传播(委托)。我们只将一个侦听器附加到 parent,当 child 上发生事件时(在本例中关注 input 元素),它将冒泡到 parent 和 parent 将执行侦听器。
指令如下:
app.directive('ngFocusModel', function () {
return function (scope, element) {
var focusListener = function () {
scope.hasFocus = true;
scope.$digest();
};
var blurListener = function () {
scope.hasFocus = false;
scope.$digest();
};
element[0].addEventListener('focus', focusListener, true);
element[0].addEventListener('blur', blurListener, true);
};
});
该指令侦听事件并相应地在范围内设置值,因此我们可以进行条件更改。
这里有几点需要注意。
focus
和 blur
事件没有 "bubble",我们需要使用 "event capturing" 来捕捉它们。这就是为什么不使用 element.on('focus/blur')
(它不允许捕获,afaik)而是使用 addEventListener
方法的原因。此方法允许我们通过相应地将第三个参数设置为 false
或 true
来指定侦听器是否将在 "event bubbling" 或 "event capturing" 上执行。
我们本可以使用 focusin
和 focusout
事件 "bubble",不幸的是 Firefox (focusin and focusout) 不支持这些事件。
这里是 plunker 的实现。
更新:
在我看来,这可以通过使用 :focus
pseudo-class 的纯 CSS 来完成,唯一的缺点是占位符需要相对于输入元素处于适当的位置(兄弟) .参见 codepen。
我创建了一个小指令,可用于您的需要:
app.directive('childFocus', function($window){
var registered = [];
// observing focus events in single place
$window.addEventListener('focus', function(event){
registered.forEach(function(element){
if(element.contains(event.target)){
// if element with focus is a descendant of the
// element with our directive then action is triggered
element._scope.$apply(element._scope.action);
}
});
}, true)
return {
scope : {
action : '&childFocus' // you can pass whatever expression here
},
link : function(scope, element){
// keep track ref to scope object
element[0]._scope = scope;
// (probably better would be to register
// scope with attached element)
registered.push(element[0]);
scope.$on('destroy', function(){
registered.splice(registered.indexOf(element[0]),1);
});
}
}
});
您可以使用 '.parent *'
选择器的 focus
事件来捕获任何焦点事件,然后遍历每个父 DIV
并使用 :focus
JQuery 选择器检查具有焦点的子元素,然后将 class 添加到父元素 DIV
并将该 class 用于 show/hide 占位符(see this jsfiddle):
$(function(){
$('.parent *').focus(function(){
$('.selected').removeClass('selected');
$('.parent').each(function(index, el){
(function($el){
setTimeout(function(){
console.log($el.attr('id'));
if($el.find(':focus').length){
$el.addClass('selected');
}
});
})($(el));
});
});
});
.parent{
padding:1rem;
margin:1rem;
border:solid 1px green;
}
.selected{
border:solid 1px red;
}
.parent .placeholder{
display:none;
}
.parent.selected .placeholder{
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='parent' id='div1'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
<div class='parent' id='div2'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
<div class='parent' id='div3'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>
<div class='parent' id='div4'>
<input type="text" />
<div class='placeholder'>Placeholder</div>
</div>