This is an automated email from the ASF dual-hosted git repository. carlosrovira pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
The following commit(s) were added to refs/heads/develop by this push: new 07c2bea jewel-combobox: add key handling with arrow keys and enter to close popup. This was 07c2bea is described below commit 07c2beadaed206d56d8221e5cf8184d219afcd7d Author: Carlos Rovira <carlosrov...@apache.org> AuthorDate: Wed Apr 22 19:05:28 2020 +0200 jewel-combobox: add key handling with arrow keys and enter to close popup. This was --- .../jewel/beads/controllers/ComboBoxController.as | 107 ++++++++++++++++----- .../royale/jewel/beads/views/ComboBoxView.as | 6 +- .../apache/royale/jewel/beads/views/ListView.as | 2 +- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/ComboBoxController.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/ComboBoxController.as index 0a9b95b..919dfd8 100644 --- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/ComboBoxController.as +++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controllers/ComboBoxController.as @@ -24,10 +24,14 @@ package org.apache.royale.jewel.beads.controllers } import org.apache.royale.core.IBeadController; import org.apache.royale.core.IComboBoxModel; + import org.apache.royale.core.IItemRendererOwnerView; import org.apache.royale.core.IStrand; import org.apache.royale.events.Event; import org.apache.royale.events.IEventDispatcher; + import org.apache.royale.events.KeyboardEvent; import org.apache.royale.events.MouseEvent; + import org.apache.royale.html.beads.IListView; + import org.apache.royale.html.supportClasses.StyledDataItemRenderer; import org.apache.royale.jewel.List; import org.apache.royale.jewel.beads.controls.combobox.IComboBoxView; import org.apache.royale.jewel.beads.models.IJewelSelectionModel; @@ -63,7 +67,6 @@ package org.apache.royale.jewel.beads.controllers private var model:IComboBoxModel; private var _strand:IStrand; - /** * @copy org.apache.royale.core.IBead#strand * @@ -100,11 +103,11 @@ package org.apache.royale.jewel.beads.controllers { IEventDispatcher(viewBead.button).addEventListener(MouseEvent.CLICK, clickHandler); IEventDispatcher(viewBead.textinput).addEventListener(MouseEvent.CLICK, clickHandler); + IEventDispatcher(viewBead.textinput).addEventListener(KeyboardEvent.KEY_DOWN, textInputKeyEventHandler); COMPILE::JS{ - //keyboard navigation from textfield should also close the popup - viewBead.textinput.element.addEventListener('blur', handleFocusOut); + //keyboard navigation from textfield should also close the popup + viewBead.textinput.element.addEventListener('blur', handleFocusOut); } - } /** @@ -118,19 +121,18 @@ package org.apache.royale.jewel.beads.controllers viewBead.popUpVisible = true; COMPILE::JS { - //put focus in the textinput - if (event.target == viewBead.button) { - viewBead.textinput.element.focus(); - } + //put focus in the textinput + if (event.target == viewBead.button) + viewBead.textinput.element.focus(); } - // viewBead.popup is ComboBoxPopUp that fills 100% of browser window-> We want List inside its view popup = viewBead.popup as ComboBoxPopUp; popup.addEventListener(MouseEvent.MOUSE_DOWN, removePopUpWhenClickOutside); list = (popup.view as ComboBoxPopUpView).list; list.addEventListener(MouseEvent.MOUSE_DOWN, handleControlMouseDown); + list.addEventListener(KeyboardEvent.KEY_DOWN, listKeyEventHandler); list.addEventListener(Event.CHANGE, changeHandler); if (model is IJewelSelectionModel) { //don't let the pop-up's list take over as primary dispatcher @@ -139,6 +141,60 @@ package org.apache.royale.jewel.beads.controllers } } + /** + * key listener at TextInput level + * @private + */ + protected function textInputKeyEventHandler(event:KeyboardEvent):void + { + COMPILE::JS + { + if (document.activeElement !== viewBead.textinput.element) + return; + } + + // from this point we don't want to perform this actions if textinput is not active + + if(event.key === KeyboardEvent.KEYCODE__DOWN) + { + keyPressed = true + var view:IListView = list.view as IListView; + var dataGroup:IItemRendererOwnerView = view.dataGroup; + var goToIndex:int = list.selectedIndex == -1 ? 0 : list.selectedIndex; + list.scrollToIndex(goToIndex); + var ir:StyledDataItemRenderer = dataGroup.getItemRendererForIndex(goToIndex) as StyledDataItemRenderer; + COMPILE::JS + { + // this 'hack' is needed due to browsers scrolling list on popups when get focus + if(list.element.classList.contains("scroll")); + { + list.element.classList.remove("scroll"); + setTimeout(restoreScroll, 300); + } + list.element.focus({preventScroll:true}); + list.selectedIndex = goToIndex; + } + } + } + + /** + * key listener at global List level + * @private + */ + protected function listKeyEventHandler(event:KeyboardEvent):void + { + if(event.key === KeyboardEvent.KEYCODE__ENTER) + { + dismissPopUp(); + } + } + + COMPILE::JS + private function restoreScroll():void + { + list.element.classList.add("scroll"); + } + private var popup:ComboBoxPopUp; protected function handleControlMouseDown(event:MouseEvent):void @@ -146,7 +202,6 @@ package org.apache.royale.jewel.beads.controllers event.stopImmediatePropagation(); } - /** * @private */ @@ -162,7 +217,9 @@ package org.apache.royale.jewel.beads.controllers } protected function hidePopup():void{ - viewBead.popUpVisible = false; + if(!keyPressed) + viewBead.popUpVisible = false; + keyPressed = false; } /** * @royaleignorecoercion org.apache.royale.core.UIBase @@ -170,10 +227,7 @@ package org.apache.royale.jewel.beads.controllers */ protected function removePopUpWhenClickOutside(event:MouseEvent = null):void { - popup.removeEventListener(MouseEvent.MOUSE_DOWN, removePopUpWhenClickOutside); - list.removeEventListener(MouseEvent.MOUSE_DOWN, handleControlMouseDown); - list.removeEventListener(Event.CHANGE, changeHandler); - viewBead.popUpVisible = false; + dismissPopUp(); } /** @@ -183,19 +237,28 @@ package org.apache.royale.jewel.beads.controllers private function changeHandler(event:Event):void { event.stopImmediatePropagation(); - - popup.removeEventListener(MouseEvent.MOUSE_DOWN, removePopUpWhenClickOutside); - list.removeEventListener(MouseEvent.MOUSE_DOWN, handleControlMouseDown); - list.removeEventListener(Event.CHANGE, changeHandler); - model.selectedItem = IComboBoxModel(list.getBeadByType(IComboBoxModel)).selectedItem; - viewBead.popUpVisible = false; - IEventDispatcher(_strand).dispatchEvent(new Event(Event.CHANGE)); + dismissPopUp(); } protected function modelChangeHandler(event:Event):void{ IEventDispatcher(_strand).dispatchEvent(new Event(event.type)); } + + private var keyPressed:Boolean; + + private function dismissPopUp():void + { + if(!keyPressed) + { + popup.removeEventListener(MouseEvent.MOUSE_DOWN, removePopUpWhenClickOutside); + list.removeEventListener(MouseEvent.MOUSE_DOWN, handleControlMouseDown); + list.removeEventListener(Event.CHANGE, changeHandler); + list.removeEventListener(KeyboardEvent.KEY_DOWN, listKeyEventHandler); + viewBead.popUpVisible = false; + } + keyPressed = false; + } } } diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ComboBoxView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ComboBoxView.as index 93861cc..546eeab 100644 --- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ComboBoxView.as +++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ComboBoxView.as @@ -129,9 +129,8 @@ package org.apache.royale.jewel.beads.views }*/ _button = new Button(); - COMPILE::JS { - _button.element.setAttribute('tabindex', -1); - } + _button.tabIndex = -1; + _button.text = '\u25BC'; initSize(); @@ -200,6 +199,7 @@ package org.apache.royale.jewel.beads.views //popup width needs to be set before position inside bounding client to work ok _list.width = host.width; + _list.scrollToIndex(_list.selectedIndex); COMPILE::JS { diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ListView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ListView.as index 0703f84..21e34b3 100644 --- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ListView.as +++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/ListView.as @@ -32,6 +32,7 @@ package org.apache.royale.jewel.beads.views import org.apache.royale.core.IRollOverModel; import org.apache.royale.core.ISelectableItemRenderer; import org.apache.royale.core.ISelectionModel; + import org.apache.royale.core.StyledUIBase; import org.apache.royale.events.Event; import org.apache.royale.events.IEventDispatcher; import org.apache.royale.events.KeyboardEvent; @@ -39,7 +40,6 @@ package org.apache.royale.jewel.beads.views import org.apache.royale.jewel.beads.models.ListPresentationModel; import org.apache.royale.jewel.supportClasses.list.IListPresentationModel; import org.apache.royale.utils.getSelectionRenderBead; - import org.apache.royale.core.StyledUIBase; /** * The ListView class creates the visual elements of the org.apache.royale.jewel.List