Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #11 (permalink)  
Старый 22.05.2016, 15:08
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 25.06.2009
Сообщений: 1,033

$<цифры-буквы><13>
С баксом проблем нет, грид его пропускает. И все остальное тоже, кроме 13.

.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Ответить с цитированием
  #12 (permalink)  
Старый 22.05.2016, 15:10
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 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.
Ответить с цитированием
  #13 (permalink)  
Старый 23.05.2016, 22:53
Аватар для nohuhu
Профессор
Отправить личное сообщение для nohuhu Посмотреть профиль Найти все сообщения от nohuhu
 
Регистрация: 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 тоже должно сработать.

Учтите также, что несмотря на кажущуюся простоту кода, механизмы здесь задействуются сложные и колдунство вельми сильное. Если нужно что-нибудь поменять, лучше сперва спросите. Я с удовольствием объясню, что и как, но это может оказаться надолго. :)
Ответить с цитированием
  #14 (permalink)  
Старый 23.05.2016, 23:04
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 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.
Ответить с цитированием
  #15 (permalink)  
Старый 24.05.2016, 01:54
Аватар для nohuhu
Профессор
Отправить личное сообщение для nohuhu Посмотреть профиль Найти все сообщения от nohuhu
 
Регистрация: 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 был вовсе не праздным, промышленную версию этого решения неплохо бы обвешать предохранителями на тему ложных срабатываний. Как говорил незабвенный поручик, случаи разные бывают...
Ответить с цитированием
  #16 (permalink)  
Старый 24.05.2016, 10:46
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 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.
Ответить с цитированием
  #17 (permalink)  
Старый 24.05.2016, 20:05
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 25.06.2009
Сообщений: 1,033

Здесь тоже есть опция capture, но недокументированная

http://docs.sencha.com/extjs/6.0/6.0...xt.util.KeyMap
http://docs.sencha.com/extjs/6.0/6.0...xt.util.KeyNav

плюс еще опция priority тоже есть.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Ответить с цитированием
  #18 (permalink)  
Старый 31.05.2016, 21:49
Аватар для nohuhu
Профессор
Отправить личное сообщение для nohuhu Посмотреть профиль Найти все сообщения от nohuhu
 
Регистрация: 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 это недокументированная опция, надо заметить...
Это баг, пофиксим. Спасибо, что нашли. ;)
Ответить с цитированием
  #19 (permalink)  
Старый 01.06.2016, 07:21
Аватар для khusamov
Соединяю Node.js и Ext JS
Отправить личное сообщение для khusamov Посмотреть профиль Найти все сообщения от khusamov
 
Регистрация: 25.06.2009
Сообщений: 1,033

Цитата:
Остальные хитрости нужны затем, чтобы максимально использовать возможности браузера и существующий код фреймворка без необходимости изобретать велосипед.
Странно. Все эти хитрости, направлены на то, чтобы при помощи фокуса отлавливать нажатия кнопок. Чтобы никто не смог заблокировать.

Но ведь опция { capture: true } гарантированно решает эту проблему.

Зачем "максимально использовать возможности браузера", если проблема перехвата так легко решается? Хотя бы ценой смены события keypress на keydown.
__________________
Хусамов Сухроб, Москва, khusamov@yandex.ru
Мой JS-стек: Sencha ExtJS 6, Node.js, TypeScript.
Ответить с цитированием
  #20 (permalink)  
Старый 01.06.2016, 20:30
Аватар для nohuhu
Профессор
Отправить личное сообщение для nohuhu Посмотреть профиль Найти все сообщения от nohuhu
 
Регистрация: 21.05.2015
Сообщений: 321

Сообщение от khusamov Посмотреть сообщение
Зачем "максимально использовать возможности браузера", если проблема перехвата так легко решается? Хотя бы ценой смены события keypress на keydown.
Затем, что проблема на самом деле нетривиальна и перехват клавиатурных событий имеет побочные эффекты, которые могут выйти боком. Затем, что "очевидный" способ решить эту проблему - это конечный автомат, которых надо избегать, как огня, потому что любой такой автомат кончает прицельным выстрелом в вашу ногу. Затем, что в браузере вы не можете читать поток ввода, когда вам удобно, а вместо этого вынуждены реагировать на события - а асинхронный конечный автомат бьёт по площадям дробью размером с пушечное ядро.

А самое главное: для обработки этих событий вам нужно писать код, а код === баги === стоимость поддержки. Единственный способ уменьшить количество багов, это уменьшить количество кода.

Но вы не подумайте чего, я не буду вас уговаривать. Ваш проект, ваша головная боль... ;)
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск