Как исправить автозаполнение интерфейса 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/