Слежение за значением комбо-бокса в Firefox

Aug 12, 2013 16:07


На днях вышла 23-я версия «Файерфокс» и у нас внезапно сломался программный комплекс. Не катастрофа, ибо целевая версия - 3.6, а когда-нибудь в ещё даже не анонсированном светлом будущем - 15… Но - хотя целевой браузер у меня установлен и я с ним периодически сверяюсь, разработку веду всё-таки в актуальной версии (и не я один такой), и успел обновить, а генеральный директор вообще мне неподконтролен и смотрит нашу работу спасибо что не в «Опере». Короче, неприятность. А причина её в том, что перестал работать нестандартный (мораль!) метод watch на элементе select, говорит, «TypeError: can’t watch non-native objects of class Proxy». А у нас на него были завязаны иерархические комбо-боксы, а они почти в каждом фильтре, а фильтр почти в каждом модуле…

Захожу в мозилловский баг-трекер и вижу, что народ тоже уже заметил, а ведущий разработчик «Файерфокс» Борис Збарский любезно отвечает, что так, дескать, и должно быть, комбо-бокс это теперь «типа, прокси».

Это навело меня на мысль попытаться обернуть мой HTMLSelectElement в реальный Proxy (не путать с прокси-серверами, это новая конструкция Javascript такая, некоторым образом обобщение сеттеров/геттеров). Поначалу всё шло хорошо - пока не обнаружилось, что проксю нельзя пихать вместо настоящего DOM-узла в DOM-методы (например, навесить листенер или просто добавить дочерний узел). В умопомрачении я попытался отслеживать перемещение по опциям комбо-бокса HTML-атрибута selected посредством MutationObserver, не сообразив сразу, что никуда он не перемещается при смене значения хоть пользователем, хоть скриптом.

«Но что же нам делать?» - возопил я, и получил от Збарского лаконичную подсказку: «You can capture that by interposing your own setter that calls through to the canonical setter». Но нельзя просто взять и… Хм. В общем, он, может, такими вещами и занимается втихомолку, но я не смог нагуглить ничего внятного в качестве примера. Пришлось разбираться во всём самому методом тыка. Сначала оказалось, что если я переопределяю сеттер, то должен определить и геттер, потом, что в мозилловской реализации геттеров сломан контекст. В итоге у меня получился скрипт, состоящий сплошь из конструкций, которые я не применял никогда, которые применяю редко и которые применяю не так редко, но единственный в фирме.

let({get: canonicalGetter, set: canonicalSetter}=Object.getOwnPropertyDescriptor(Object.getPrototypeOf(combo), "value")){ Object.defineProperty(combo, "value", { configurable: true, enumerable: true, get: function() canonicalGetter.call(combo),//this нельзя, он сломан! set: function(value){ onChangeValue.call(this, "value", this.value, value);//onChangeValue - это мой обработчик canonicalSetter.call(this, value); } }); }; let({get: canonicalGetter, set: canonicalSetter}=Object.getOwnPropertyDescriptor(Object.getPrototypeOf(combo), "selectedIndex")){ Object.defineProperty(combo, "selectedIndex", { configurable: true, enumerable: true, get: function() canonicalGetter.call(combo), set: function(value){ let oldValue=this.value; canonicalSetter.call(this, value); onChangeValue.call(this, "value", oldValue, this.value); } }); }; combo.addEventListener( "change", function(){ onChangeValue.call(this, "value", comboValue, this.value);//comboValue - переменная замыкания, в которой запоминается текущее значение комбо-бокса в функции onChangeValue (если при изменении нас не интересует прежнее значение, можно обойтись без неё) }, false );
Напоследок - немного профессионального юмора. Ушедший в отпуск сотрудник оставил один свой новый модуль неработающим в новой версии браузера. Полез туда, а там необъявленная переменная. Это ладно, но имя этой переменной - quesyStringОptional. Само по себе уже забавно (должно быть query, а quesy в английском сленге означает «тошноту с бодуна»), а тут ещё и редактор на него ругается. Почему? Оказывается, там «О» в серёдке кириллическая. Нет, это допустимый идентификатор Javascript. Но как, как можно так опечататься случайно?

javascript, firefox, Web-программирование

Previous post Next post
Up