You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by ca...@apache.org on 2020/04/22 17:05:32 UTC

[royale-asjs] branch develop updated: jewel-combobox: add key handling with arrow keys and enter to close popup. This was

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 <ca...@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