ui-select 输入在点击时没有获得焦点:与 angular-touch 冲突
ui-select input does not get focus on click : conflict with angular-touch
我在使用 ui-select 和 angular-touch 的 AngularJS 应用程序上遇到问题。
在 Safari 上,使用 iPad 或 iPhone 等移动设备,当我单击 ui-select 指令的文本输入字段时,虚拟键盘打不开,输入框没有焦点
我发现是 angular-touch 导致了问题,因为一旦我从应用程序中删除依赖项,一切都会再次正常。
HTML
<body ng-controller="DemoCtrl">
<ui-select multiple
theme="select2"
ng-model="multipleDemo.selection"
reset-search-input="true"
style="min-width: 300px;">
<ui-select-match placeholder="Enter an adress...">
{{$item.formatted_address}}
</ui-select-match>
<ui-select-choices repeat="address in addresses track by $index"
refresh="refreshAddresses($select.search)"
refresh-delay="250">
<div ng-bind-html="address.formatted_address | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<p>Selected : {{multipleDemo.selection | selectionFilter}}</p>
</body>
JS
var app = angular.module('demo', ['ngSanitize', 'ui.select', 'ngTouch']);
app.filter('selectionFilter', function() {
// Not important... see the plunker for detail.
});
app.controller('DemoCtrl', function($scope, $http) {
$scope.multipleDemo = {};
$scope.multipleDemo.selection = [];
$scope.address = {};
$scope.refreshAddresses = function(address) {
var params = {address: address, sensor: false};
return $http.get(
'http://maps.googleapis.com/maps/api/geocode/json',
{params: params}
).then(function(response) {
$scope.addresses = response.data.results;
});
};
});
http://plnkr.co/edit/dFBQ4si6hLMP1S9dal7m?p=preview
有人知道我可以做些什么来防止 ngTouch 引起问题吗?我不能只从依赖项中删除 ngTouch:我在其他地方需要它。
更新 16/09
问题似乎出在angular-touch (1.4.8) 的这一部分:
element.on('touchend', function(event) {
var diff = Date.now() - startTime;
// Use jQuery originalEvent
var originalEvent = event.originalEvent || event;
var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ?
originalEvent.changedTouches :
((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]);
var e = touches[0];
var x = e.clientX;
var y = e.clientY;
var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));
if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
// Call preventGhostClick so the clickbuster will catch the corresponding click.
preventGhostClick(x, y);
// Blur the focused element (the button, probably) before firing the callback.
// This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
// I couldn't get anything to work reliably on Android Chrome.
if (tapElement) {
tapElement.blur();
}
if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
element.triggerHandler('click', [event]);
}
}
resetState();
});
如果我禁用该条件,例如添加 && false
,输入将在点击时获得焦点。
我需要找到一种方法来禁用来自外部输入的此事件绑定 angular-touch lib.
下面的指令应用于 ui-select
父指令,解决了问题:
app.directive('fixFocusOnTouch', function(){
return {
restrict: 'A',
controller: function( $element ){
/*
Usually, event handlers binding are made in the link function.
But we need this handler to be executed first, so we add it in the controller function instead.
*/
var inputElement = $element[0].querySelector( 'input.ui-select-search' );
angular.element( inputElement ).bind( 'touchend', function( event ){
event.stopImmediatePropagation();
});
}
}
});
它会在 angular-touch 添加的处理程序可以执行之前终止 touchend 事件的当前传播(请参阅问题的 "update" 部分)。
我无法让它在 Plunkr 上运行,但我会再试一次以提供一个工作示例。
用法:
<ui-select multiple fix-focus-on-touch
theme="select2"
ng-model="multipleDemo.selection"
reset-search-input="true"
style="min-width: 300px;">
<ui-select-match placeholder="Enter an adress...">
{{$item.formatted_address}}
</ui-select-match>
<ui-select-choices repeat="address in addresses track by $index"
refresh="refreshAddresses($select.search)"
refresh-delay="250">
<div ng-bind-html="address.formatted_address | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
我在使用 ui-select 和 angular-touch 的 AngularJS 应用程序上遇到问题。
在 Safari 上,使用 iPad 或 iPhone 等移动设备,当我单击 ui-select 指令的文本输入字段时,虚拟键盘打不开,输入框没有焦点
我发现是 angular-touch 导致了问题,因为一旦我从应用程序中删除依赖项,一切都会再次正常。
HTML
<body ng-controller="DemoCtrl">
<ui-select multiple
theme="select2"
ng-model="multipleDemo.selection"
reset-search-input="true"
style="min-width: 300px;">
<ui-select-match placeholder="Enter an adress...">
{{$item.formatted_address}}
</ui-select-match>
<ui-select-choices repeat="address in addresses track by $index"
refresh="refreshAddresses($select.search)"
refresh-delay="250">
<div ng-bind-html="address.formatted_address | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
<p>Selected : {{multipleDemo.selection | selectionFilter}}</p>
</body>
JS
var app = angular.module('demo', ['ngSanitize', 'ui.select', 'ngTouch']);
app.filter('selectionFilter', function() {
// Not important... see the plunker for detail.
});
app.controller('DemoCtrl', function($scope, $http) {
$scope.multipleDemo = {};
$scope.multipleDemo.selection = [];
$scope.address = {};
$scope.refreshAddresses = function(address) {
var params = {address: address, sensor: false};
return $http.get(
'http://maps.googleapis.com/maps/api/geocode/json',
{params: params}
).then(function(response) {
$scope.addresses = response.data.results;
});
};
});
http://plnkr.co/edit/dFBQ4si6hLMP1S9dal7m?p=preview
有人知道我可以做些什么来防止 ngTouch 引起问题吗?我不能只从依赖项中删除 ngTouch:我在其他地方需要它。
更新 16/09
问题似乎出在angular-touch (1.4.8) 的这一部分:
element.on('touchend', function(event) {
var diff = Date.now() - startTime;
// Use jQuery originalEvent
var originalEvent = event.originalEvent || event;
var touches = (originalEvent.changedTouches && originalEvent.changedTouches.length) ?
originalEvent.changedTouches :
((originalEvent.touches && originalEvent.touches.length) ? originalEvent.touches : [originalEvent]);
var e = touches[0];
var x = e.clientX;
var y = e.clientY;
var dist = Math.sqrt(Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2));
if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) {
// Call preventGhostClick so the clickbuster will catch the corresponding click.
preventGhostClick(x, y);
// Blur the focused element (the button, probably) before firing the callback.
// This doesn't work perfectly on Android Chrome, but seems to work elsewhere.
// I couldn't get anything to work reliably on Android Chrome.
if (tapElement) {
tapElement.blur();
}
if (!angular.isDefined(attr.disabled) || attr.disabled === false) {
element.triggerHandler('click', [event]);
}
}
resetState();
});
如果我禁用该条件,例如添加 && false
,输入将在点击时获得焦点。
我需要找到一种方法来禁用来自外部输入的此事件绑定 angular-touch lib.
下面的指令应用于 ui-select
父指令,解决了问题:
app.directive('fixFocusOnTouch', function(){
return {
restrict: 'A',
controller: function( $element ){
/*
Usually, event handlers binding are made in the link function.
But we need this handler to be executed first, so we add it in the controller function instead.
*/
var inputElement = $element[0].querySelector( 'input.ui-select-search' );
angular.element( inputElement ).bind( 'touchend', function( event ){
event.stopImmediatePropagation();
});
}
}
});
它会在 angular-touch 添加的处理程序可以执行之前终止 touchend 事件的当前传播(请参阅问题的 "update" 部分)。
我无法让它在 Plunkr 上运行,但我会再试一次以提供一个工作示例。
用法:
<ui-select multiple fix-focus-on-touch
theme="select2"
ng-model="multipleDemo.selection"
reset-search-input="true"
style="min-width: 300px;">
<ui-select-match placeholder="Enter an adress...">
{{$item.formatted_address}}
</ui-select-match>
<ui-select-choices repeat="address in addresses track by $index"
refresh="refreshAddresses($select.search)"
refresh-delay="250">
<div ng-bind-html="address.formatted_address | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>