22.05.2016, 15:08
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
$<цифры-буквы><13>
С баксом проблем нет, грид его пропускает. И все остальное тоже, кроме 13.
.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
22.05.2016, 15:10
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Цитата:
|
...Enter переводит таблицу из навигационного режима (Navigable mode) в активизационный режим (Actionable mode).
|
Об это есть где подробнее прочесть? Пока не смог найти.
Цитата:
|
Изменять это поведение в общем случае я бы не рекомендовал, но если есть чёткое понимание, как UI должен работать, то можно сделать исключение. Хотя и непонятно пока, зачем.
|
А как отключить этот перехват без патчей?
Пробовал найти такую опцию в классах:
Ext.view.AbstractView
Ext.view.View
Ext.panel.Table
Ext.grid.Panel
.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 22.05.2016 в 15:14.
|
|
23.05.2016, 22:53
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Сообщение от khusamov
|
У меня работа со сканером глобальная. То есть не привязана ни к какому элементу. Поэтому пользователю не требуется перед сканированием указывать фокус (то есть специально выбирать элемент, куда будет произведен ввод со сканера).
|
Всё страньше и страньше, сказала Алиса... Т.е. у вас общение со сканером односторонее и по факту сканер эмулирует клавиатурный ввод на уровне ОС в активное приложение? А что будет, если окно браузера не в фокусе и "нажатия клавиш" улетят мимо?
Хм. Если подумать, то задачка-то забавно нетривиальная даже без учёта вопроса с браузерным окном. Отслеживание активного компонента тут слабо поможет, особенно если вашему приложению нужно работать в IE. Я бы пошёл другим путём: можно установить обработчик события keydown на уровне документа со срабатыванием в фазе перехвата, и при опознавании префикса "подставлять" под следующие за ним "нажатия клавиш" некое специальное поле. Примерно так:
Ext.define('My.app.Application', {
extend: 'Ext.app.Application',
launch: function() {
this.scannerField = new Ext.form.field.Text({
renderTo: Ext.getBody(),
floating: true,
hidden: true,
focusOnToFront: true,
cls: 'x-hidden-clip',
shadow: false,
listeners: {
specialkey: function(field, e) {
if (e.getKey() === e.ENTER) {
e.preventDefault();
e.stopEvent();
// Это просто чтобы не заморачиваться с разрешением
// scope через references в этом примере
Ext.app.Application.instance.fireEvent('scanner_input', this.getValue());
this.setRawValue('');
this.hide();
}
}
}
});
Ext.getDoc().on('keydown', function(e) {
// 52 это код клавиши для '$'
if (e.getKey() === 52) {
e.preventDefault();
e.stopEvent();
Ext.app.Application.instance.scannerField.show();
return false;
}
}, { capture: true });
}
});
Это решение не на 100% свободно от побочных эффектов, но в вашем случае такого решения скорее всего вообще нет. Для пущего спокойствия душевного, я бы проделал серию бесчеловечных экспериментов над живым сканером; главный вопрос это насколько быстро случается "ввод", т.е. каков разрыв по времени между префиксом и постфиксом. Я очень сильно подозреваю, что разрыв близок к 0 мс, но могут быть варианты. Если разрыв минимален, то вышеописанное решение должно иметь приемлемую надёжность. Я протестировал по-быстрому в Chrome, но по идее в IE тоже должно сработать.
Учтите также, что несмотря на кажущуюся простоту кода, механизмы здесь задействуются сложные и колдунство вельми сильное. Если нужно что-нибудь поменять, лучше сперва спросите. Я с удовольствием объясню, что и как, но это может оказаться надолго. :)
|
|
23.05.2016, 23:04
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Цитата:
|
Т.е. у вас общение со сканером односторонее и по факту сканер эмулирует клавиатурный ввод на уровне ОС в активное приложение? А что будет, если окно браузера не в фокусе и "нажатия клавиш" улетят мимо?
|
У меня браузер в режиме киоска. Да и вообще, этот вопрос не самый главный. Пока считаем, что проблем с активным приложением нет или ее решает сам пользователь.
Цитата:
|
...со срабатыванием в фазе перехвата
|
1) Вот этого точно у меня сейчас нет. Я так понимаю, этот режим включает опция capture: true... Но что за режим такое вообще "фаза перехвата"?
Здесь я ничего не нашел:
http://docs.sencha.com/extjs/6.0/6.0...iner-method-on
Цитата:
|
Я протестировал по-быстрому в Chrome, но по идее в IE...
|
Пока задача такова, что браузер я выбираю, а не пользователь.
2) И еще вопрос:
А зачем после $ надо показывать поле Ext.app.Application.instance.scannerField.show(); а потом после 13 - скрывать?
Из-за этой опции focusOnToFront: true? Хитро однако...
.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 23.05.2016 в 23:19.
|
|
24.05.2016, 01:54
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Сообщение от khusamov
|
У меня браузер в режиме киоска. Да и вообще, этот вопрос не самый главный. Пока считаем, что проблем с активным приложением нет или ее решает сам пользователь.
|
А если честно, то других вариантов с браузерными приложениями и нету вовсе. Из JavaScript всё равно никак не сфокусировать браузерное окно, поэтому остаётся только предполагать, что оно будет в фокусе.
Цитата:
|
1) Вот этого точно у меня сейчас нет. Я так понимаю, этот режим включает опция capture: true... Но что за режим такое вообще "фаза перехвата"?
|
Capture phase, первая стадия прохождения DOM событий: http://javascript.info/tutorial/bubbling-and-capturing. В нашем случае перехватчик устанавливается на самом верху иерархии, документе, поэтому срабатывает перед любыми другими обработчиками событий на элементах в теле документа.
Цитата:
|
Пока задача такова, что браузер я выбираю, а не пользователь.
|
Это хорошо. Я не стал упоминать, что это решение не будет работать в IE < 9, тихо понадеявшись на то, что такой вопрос даже не встанет. :)
Цитата:
|
2) И еще вопрос:
А зачем после $ надо показывать поле Ext.app.Application.instance.scannerField.show(); а потом после 13 - скрывать?
Из-за этой опции focusOnToFront: true? Хитро однако...
.
|
Это поле нам нужно только для ввода сканерных событий, и фактически только на период между началом ввода префиксом '$' и окончанием ввода (Enter). На мой взгляд, не имеет смысла держать это поле постоянно видимым на экране - у пользователей ручки шаловливые и киоск или не киоск, а проблем будет меньше, если этим ручкам не давать повода для шалостей.
Поэтому поле сделано невидимым, но фокусируемым, с помощью CSS правила clip: rect(0,0,0,0), которое применяется стилем 'x-hidden-clip'. Остальные хитрости как раз для автомагического управления фокусом: поле у нас "плавающий" компонент с абсолютным позиционированием в теле документа, поэтому в раскладках не участвует и на другие компоненты не влияет. Когда мы это поле показываем через scannerField.show(), глобальный ZIndexManager сортирует свою коллекцию плавучих компонентов и выпихивает наверх наше поле, попутно его фокусируя. Поле, оказываясь наверху стека и получая фокус, запоминает предыдущий сфокусированный элемент и отпуливает фокус обратно, когда мы это поле скрываем. Флаг focusOnToFront должен быть true по умолчанию для всех плавучек, но я просто подстраховался, т.к. некоторые классы его меняют и я не помню точно, какие именно.
Примерно так, если без нюансов. :)
А ещё если подумать, то надо очистку поля через setRawValue('') передвинуть из обработчика specialkey в глобальный перехватчик. И вопрос о длительности интервала между $ и Enter был вовсе не праздным, промышленную версию этого решения неплохо бы обвешать предохранителями на тему ложных срабатываний. Как говорил незабвенный поручик, случаи разные бывают...
|
|
24.05.2016, 10:46
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Цитата:
|
А если честно, то других вариантов с браузерными приложениями и нету вовсе. Из JavaScript всё равно никак не сфокусировать браузерное окно, поэтому остаётся только предполагать, что оно будет в фокусе.
|
Я еще нашел вариант: это собрать свою сборку Хромиума на С++. Там можно многое добавить из мира нативных десктопных программ (если вообще не все возможности). И наверное можно добавить дополнительный API, доступный внутри JS-кода.
Это для задач, где пользователь не решает, какой браузер ему использовать.
Цитата:
|
Capture phase, первая стадия прохождения DOM событий: http://javascript.info/tutorial/bubbling-and-capturing. В нашем случае перехватчик устанавливается на самом верху иерархии, документе, поэтому срабатывает перед любыми другими обработчиками событий на элементах в теле документа.
|
Хе, а зачем все остальные хитрости? Это как раз то, что нужно. Я свой обработчик, что сейчас есть, туда выставлю и он перехватит коды 13 и пробел, которые теряются в гриде!!!
Я попробовал в действии опцию { capture: true }. Для keydown она работает, грид не может перехватить и заблокировать событие, а вот для keypress эта опция не сработала, грид заблокировал событие, почему такая разница???
В итоге, мне в общем-то достаточно опции capture, чтобы решить проблему, разве что событие keypress придется поменять на keydown. Но, единственный недостаток решения это то, что capture это недокументированная опция, надо заметить...
.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Последний раз редактировалось khusamov, 24.05.2016 в 12:11.
|
|
24.05.2016, 20:05
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
31.05.2016, 21:49
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Сообщение от khusamov
|
Я еще нашел вариант: это собрать свою сборку Хромиума на С++. Там можно многое добавить из мира нативных десктопных программ (если вообще не все возможности). И наверное можно добавить дополнительный API, доступный внутри JS-кода.
|
Свою сборку Chromium делать накладно, лучше использовать Electron. Мы так и сделали в Sencha Test.
Цитата:
|
Хе, а зачем все остальные хитрости? Это как раз то, что нужно. Я свой обработчик, что сейчас есть, туда выставлю и он перехватит коды 13 и пробел, которые теряются в гриде!!!
|
Остальные хитрости нужны затем, чтобы максимально использовать возможности браузера и существующий код фреймворка без необходимости изобретать велосипед.
Цитата:
|
Я попробовал в действии опцию { capture: true }. Для keydown она работает, грид не может перехватить и заблокировать событие, а вот для keypress эта опция не сработала, грид заблокировал событие, почему такая разница???
|
Потому что keypress это синтетическое событие для "печатных" символов, оно не имеет действия по умолчанию: http://www.quirksmode.org/dom/events/keys.html
Цитата:
|
Но, единственный недостаток решения это то, что capture это недокументированная опция, надо заметить...
|
Это баг, пофиксим. Спасибо, что нашли. ;)
|
|
01.06.2016, 07:21
|
|
Соединяю Node.js и Ext JS
|
|
Регистрация: 25.06.2009
Сообщений: 1,033
|
|
Цитата:
|
Остальные хитрости нужны затем, чтобы максимально использовать возможности браузера и существующий код фреймворка без необходимости изобретать велосипед.
|
Странно. Все эти хитрости, направлены на то, чтобы при помощи фокуса отлавливать нажатия кнопок. Чтобы никто не смог заблокировать.
Но ведь опция { capture: true } гарантированно решает эту проблему.
Зачем "максимально использовать возможности браузера", если проблема перехвата так легко решается? Хотя бы ценой смены события keypress на keydown.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
|
|
01.06.2016, 20:30
|
|
Профессор
|
|
Регистрация: 21.05.2015
Сообщений: 321
|
|
Сообщение от khusamov
|
Зачем "максимально использовать возможности браузера", если проблема перехвата так легко решается? Хотя бы ценой смены события keypress на keydown.
|
Затем, что проблема на самом деле нетривиальна и перехват клавиатурных событий имеет побочные эффекты, которые могут выйти боком. Затем, что "очевидный" способ решить эту проблему - это конечный автомат, которых надо избегать, как огня, потому что любой такой автомат кончает прицельным выстрелом в вашу ногу. Затем, что в браузере вы не можете читать поток ввода, когда вам удобно, а вместо этого вынуждены реагировать на события - а асинхронный конечный автомат бьёт по площадям дробью размером с пушечное ядро.
А самое главное: для обработки этих событий вам нужно писать код, а код === баги === стоимость поддержки. Единственный способ уменьшить количество багов, это уменьшить количество кода.
Но вы не подумайте чего, я не буду вас уговаривать. Ваш проект, ваша головная боль... ;)
|
|
|
|