Клуб API Карт

Баг в работе с событиями onselectstart и ondragstart

Пост в архиве.

Последние несколько дней занимаюсь прикручиванием Яндекс карт к нашему сайту и уже нашел несколько серьезных багов. Опишу самый вопиющий. Рядом с картой у нас на странице есть ползунок, который пользователь может перетаскивать. Реализован этот контрол с использованием jquery.draggable. Сегодня заметил, что ползунок работает корректно ровно до того момента, пока не кликнешь на карту. После этого он просто умирает, и сдвинуть его с места нет никакой возможности. Стал копать код. Сначала поставил нежатую библиотеку JQuery UI, думал, что они там что-то нахимичили. Покопавшись с часок с евентами и успевши не раз чертыхнуться, понял, что кто-то делает preventDefault событию dragstart, из-за чего перестает работать перетаскивание ползунка. Пришлось следом поставить нежатую версию самой jQuery и копаться уже в ней. В конце концов оказалось, что на элемент document в свойстве ondragstart повешена некая функция falseFunction:

 

falseFunction = function () {

return false;
};

Как видим, она ничего не делает кроме того, что режет все события, на которые она повешена, и находится эта функция в коде яндекс карт. После этого дело пошло куда быстрее. Вот что выяснилось:

В момент начала перетаскивания карты выполняется функция карт _setupDragger, в которой есть такое место:

// Предотвращаем стандартное поведение выделения текста.

if ('ondragstart' in document) {
   onDragStartBackup = document.ondragstart;
   document.ondragstart = falseFunction;
}
if ('onselectstart' in document) {
   onSelectStartBackup = document.onselectstart;
   document.onselectstart = falseFunction;
}
Тут уже имеющиеся функции записываются в переменные, чтобы, видимо, позже вернуть их на обратно, а на их место ставится falseFunction, режущая наши события, чтобы текст не выделялся, как мы видим из комментариев. А как же происходит возвращение в исходное состояние? А вот как:
_clearDragger: function () {
.....
  if (onSelectStartBackup) {
    document.onselectstart = onSelectStartBackup;
  }
  if (onDragStartBackup) {
    document.ondragstart = onDragStartBackup;
  }
}
И тут все становится на свои места. Поскольку на ondragstart документа ничего не было повешено, то
onDragStartBackup у нас пустой и, соответственно, falseFunction прдолжает как ни в чем не бывало сидеть на своем месте вечно, убивая все события drag.
По итогам можно дать два совета:
1. (разработчикам карт) - уберите, пожалуйста, проверку на пустоту onSelectStartBackup и onDragStartBackup - какими вы эти функции взяли, такими и возвращайте.
2. (прочим разработчикам) - проблема решается добавлением пустого обработчика:
document.ondragstart=function(){return true};
Его-то код и будет подставлять обратно после окончания перетаскивания карты.
6 комментариев

Наверное речь о том же баге

Да, похоже как раз на мой случай, просто у меня с объяснением причин и вариантами борьбы с проблемой.

Лучший вариант борьбы - переключиться на новый релиз, где эта ошибка будет поправлена.

Спасибо за Ваше сообщение

Sergey Konstantinov
28 января 2016, 01:44
Вы можете откатиться на версию 2.0.30 до выхода 2.0.32.
Sergey Konstantinov
28 января 2016, 01:44
А опишите менее вопиющие баги, пожалуйста.

Я догадывался, что эта просьба поступит. Отпишусь отдельным постом.