Как исправить автозаполнение интерфейса JQuery в сочетании с Touch Punch?

Выбор слов в поле ввода автозаполнения (в диалоге) не работает должным образом при использовании интерфейса JQuery в сочетании с Touch Punch. Кажется, это работает, если поле автозаполнения находится непосредственно на странице HTML, но не в диалоговом окне. Обратите внимание, что выбор с помощью мыши работает отлично во всех случаях, но выбор на ощупь (т.е. на мобильном устройстве) нет.

Я сократил весь случай до нескольких строк кода HTML и JavaScript. Один раз с JQuery UI Touch Punch, один раз без JQuery UI Touch Punch.

Я могу воспроизвести ошибку со всеми комбинациями браузера и ОС, например, Chrome на iPhone, Chrome на мобильном телефоне Android, а также Safari на iPad,

Было бы хорошо, если кто-то знает обходной путь.

1 ответ

Я думаю, что такое поведение является результатом того факта, что, с одной стороны, разработчики Touch Punch не настолько умны, а с другой стороны, пользовательский интерфейс jQuery, похоже, не очень совместим с Touch Punch.

Существует два способа запуска события мыши:

  • браузер может симулировать click события после сенсорных событий
  • какая-то библиотека может симулировать click события после сенсорных событий

Ваш пример без Touch Punch работает, потому что мобильные браузеры в настоящее время имитируют события нажатия.

Так как работает Touch Punch и как он все портит? Если вы посмотрите на исходный код https://github.com/furf/jquery-ui-touch-punch/blob/master/jquery.ui.touch-punch.js вы увидите, что он переносится $.ui.mouse.prototype._mouseInit с собственным кодом и основным намерением является присоединение различных сенсорных слушателей для всех наследующих виджетов $.ui.mouse, Все идет нормально. Но что именно делают эти слушатели? _touchStart Обработчик запускает проверку, используя $.ui.mouse внутренний API:

self._mouseCapture(event.originalEvent.changedTouches[0])

чтобы проверить, нужно ли имитировать события мыши. Логика такова: если в виджете нет обработчика кликов, имитировать клик не нужно. На первый взгляд, все в порядке, но что не так? autocomplete Виджет помещает свое раскрывающееся меню во внешний контекст содержащегося диалога и, таким образом, события касания в элементах меню фактически поражают слушателей, зарегистрированных с помощью сенсорного удара для диалога (или, скорее, для его draggable а также resizable суб-компонента). Но у подкомпонентов диалога нет прослушивателей щелчков, и, следовательно, события не моделируются библиотекой. Более того, draggable в вашей версии (см. https://github.com/jquery/jquery-ui/blob/1-11-stable/ui/draggable.js) звонки

this._blurActiveElement( event );

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

Похоже, что в ветке разработки jQuery UI ошибка исправлена https://github.com/jquery/jquery-ui/commit/8c66934434214ab92cbcf46240beb739154fdfbf но по несколько иной причине. Это исправление доступно в пользовательском интерфейсе jQuery 1.12.1, но не в вашем 1.12.0

Таким образом, самое простое решение - обновить пользовательский интерфейс jQuery до версии 1.12.1.

Смотрите рабочую демонстрацию с jQuery UI 1.12.1 на https://jsfiddle.net/cjvgv102/1/ и http://jsfiddle.net/cjvgv102/1/embedded/result/

Гадкий хак (остановитесь здесь, если вам действительно не нужно)

Если по каким-то причинам вы не можете обновить интерфейс jQuery, вы можете взломать, явно создав фальшивку mouse объект в раскрывающемся списке и вызова его _mouseInit поэтому событие не будет обрабатываться подкомпонентами диалога.

  $( "#demoDlg" ).dialog({
  autoOpen: false,
  modal: true,
  buttons: {
    "Close": function() {
      $( this ).dialog( "close" );
    }
  },
  open: function(event, ui) {
    $( "#words" ).autocomplete({
      source: ["these", "are", "some", "words"]
    });
    // super-hack
    $( "#words" ).autocomplete("instance").menu.element.mouse().mouse("instance")._mouseInit();
  }
});

Смотрите полную демонстрацию на https://jsfiddle.net/3ptgks3t/1/

Другие вопросы по тегам