Ввод ui-select не фокусируется на щелчке: конфликт с angular-touch

У меня проблема с приложением AngularJS, которое использует ui-select и angular-touch.

В Safari при использовании мобильного устройства, такого как iPad или iPhone, когда я нажимаю на поле ввода текста директивы ui-select, виртуальная клавиатура не открывается, ввод не получает фокус.

Я обнаружил, что проблема заключается в угловом прикосновении, поскольку, как только я удаляю зависимость из приложения, все снова работает нормально.

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.

1 ответ

Решение

Директива ниже, примененная к 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();
      });
    }
  }
});

Он убивает текущее распространение события touchend до того, как обработчик, добавленный angular-touch, может исполниться (см. Часть вопроса "обновление").

Я не мог заставить его работать на 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>
Другие вопросы по тегам