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 2018/12/14 10:59:38 UTC

[royale-asjs] branch develop updated: initials of focus special handling in some components like DateField and ComboBox that are composed of more than one subcomponents

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 9c08a05  initials of focus special handling in some components like DateField and ComboBox that are composed of more than one subcomponents
9c08a05 is described below

commit 9c08a058e6e6009458908e5fc0b5e5c401b5877b
Author: Carlos Rovira <ca...@apache.org>
AuthorDate: Fri Dec 14 11:59:31 2018 +0100

    initials of focus special handling in some components like DateField and ComboBox that are composed of more than one subcomponents
---
 .../jewel/beads/controllers/ComboBoxController.as  |  60 ++++++++---
 .../jewel/beads/controls/combobox/SearchFilter.as  |  91 +++++++++++++---
 .../royale/jewel/beads/views/ComboBoxView.as       | 114 +++++++++++----------
 .../royale/jewel/beads/views/DateFieldView.as      |   3 +
 4 files changed, 185 insertions(+), 83 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 e8958b8..cf187c3 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
@@ -32,12 +32,12 @@ package org.apache.royale.jewel.beads.controllers
 	import org.apache.royale.jewel.beads.controls.combobox.IComboBoxView;
 	import org.apache.royale.jewel.beads.views.ComboBoxPopUpView;
 	import org.apache.royale.jewel.supportClasses.combobox.ComboBoxPopUp;
-	
+
 	/**
 	 *  The ComboBoxController class is responsible for listening to
 	 *  mouse event related to ComboBox. Events such as selecting a item
 	 *  or changing the sectedItem.
-	 *  
+	 *
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10.2
 	 *  @playerversion AIR 2.6
@@ -47,7 +47,7 @@ package org.apache.royale.jewel.beads.controllers
 	{
 		/**
 		 *  constructor.
-		 *  
+		 *
 		 *  @langversion 3.0
 		 *  @playerversion Flash 10.2
 		 *  @playerversion AIR 2.6
@@ -56,16 +56,16 @@ package org.apache.royale.jewel.beads.controllers
 		public function ComboBoxController()
 		{
 		}
-		
+
 		protected var viewBead:IComboBoxView;
 		private var list:List;
 		private var model:IComboBoxModel;
-		
+
 		private var _strand:IStrand;
-		
+
 		/**
 		 *  @copy org.apache.royale.core.IBead#strand
-		 *  
+		 *
 		 *  @langversion 3.0
 		 *  @playerversion Flash 10.2
 		 *  @playerversion AIR 2.6
@@ -92,8 +92,13 @@ package org.apache.royale.jewel.beads.controllers
 		{
 			IEventDispatcher(viewBead.button).addEventListener(MouseEvent.CLICK, clickHandler);
             IEventDispatcher(viewBead.textinput).addEventListener(MouseEvent.CLICK, clickHandler);
+            COMPILE::JS{
+				//keyboard navigation from textfield should also close the popup
+                viewBead.textinput.element.addEventListener('blur', handleFocusOut);
+			}
+
 		}
-		
+
 		/**
          *  @royaleignorecoercion org.apache.royale.core.UIBase
          *  @royaleignorecoercion org.apache.royale.events.IEventDispatcher
@@ -101,13 +106,21 @@ package org.apache.royale.jewel.beads.controllers
 		protected function clickHandler(event:MouseEvent):void
 		{
 			event.stopImmediatePropagation();
-			
+
 			viewBead.popUpVisible = true;
-			
+
+			COMPILE::JS {
+				//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(Event.CHANGE, changeHandler);
@@ -119,6 +132,25 @@ package org.apache.royale.jewel.beads.controllers
 		{
 			event.stopImmediatePropagation();
 		}
+
+
+        /**
+         * @private
+         */
+        protected function handleFocusOut(event:Event):void
+        {
+            if (viewBead.popUpVisible) {
+				//allow a time to handle a selection from
+				//the popup as the possible reason for loss of focus
+				//(event.relatedObject seems null, so cannot check here)
+				//this should be less than 300
+                setTimeout(hidePopup, 280);
+            }
+        }
+
+        protected function hidePopup():void{
+            viewBead.popUpVisible = false;
+        }
 		/**
          *  @royaleignorecoercion org.apache.royale.core.UIBase
          *  @royaleignorecoercion org.apache.royale.events.IEventDispatcher
@@ -130,7 +162,7 @@ package org.apache.royale.jewel.beads.controllers
 			list.removeEventListener(Event.CHANGE, changeHandler);
 			viewBead.popUpVisible = false;
 		}
-		
+
 		/**
          *  @royaleignorecoercion org.apache.royale.core.UIBase
          *  @royaleignorecoercion org.apache.royale.events.IEventDispatcher
@@ -138,14 +170,14 @@ 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));
 		}
 	}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/combobox/SearchFilter.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/combobox/SearchFilter.as
index ad96707..dbf444c 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/combobox/SearchFilter.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/controls/combobox/SearchFilter.as
@@ -20,8 +20,10 @@ package org.apache.royale.jewel.beads.controls.combobox
 {
 	import org.apache.royale.core.IBead;
 	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.jewel.beads.controls.combobox.IComboBoxView;
 	import org.apache.royale.jewel.List;
 	import org.apache.royale.jewel.itemRenderers.ListItemRenderer;
 	import org.apache.royale.jewel.supportClasses.textinput.TextInputBase;
@@ -49,6 +51,8 @@ package org.apache.royale.jewel.beads.controls.combobox
 		{
 		}
 
+		private var _textInput:TextInputBase;
+
 
 		private var _strand:IStrand;
 
@@ -65,6 +69,18 @@ package org.apache.royale.jewel.beads.controls.combobox
 		{
 			_strand = value;
 			IEventDispatcher(_strand).addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
+            IEventDispatcher(_strand).addEventListener('beadsAdded', onBeadsAdded);
+		}
+
+		protected function onBeadsAdded(event:Event):void{
+            COMPILE::JS{
+                if ('view' in _strand && _strand['view'] is IComboBoxView) {
+                    _textInput = IComboBoxView(_strand['view']).textinput as TextInputBase;
+                    if (_textInput) {
+                        _textInput.element.addEventListener( 'focus', onInputFocus);
+                    }
+                }
+            }
 		}
 
 		/**
@@ -72,7 +88,7 @@ package org.apache.royale.jewel.beads.controls.combobox
 		 */
 		[Bindable]
 		public var filterFunction:Function = defaultFilterFunction;
-        
+
 		/**
 		 * default filter function just filters substrings
 		 * you can use other advanced methods like levenshtein distance
@@ -82,25 +98,66 @@ package org.apache.royale.jewel.beads.controls.combobox
 			return text.toUpperCase().indexOf(filterText) > -1;
 		}
 
+		COMPILE::JS
+		protected function onInputFocus(event:Event):void{
+            var popUpVisible:Boolean =  IComboBoxView(_strand['view']).popUpVisible;
+            if (!popUpVisible) {
+                //force popup ?:
+                IComboBoxView(_strand['view']).popUpVisible = true;
+
+                //or avoid ?:
+                //return;
+            }
+            applyFilter(_textInput);
+		}
+
         protected function keyUpHandler(event:KeyboardEvent):void
 		{
-			var filterText:String = (event.target as TextInputBase).text.toUpperCase();
-			
-			// the internal list in the combobox popup
-			var list:List = event.target.parent.view.popup.view.list;
-
-			var ir:ListItemRenderer;
-			var numElements:int = list.numElements;
-			for (var i:int = 0; i < numElements; i++)
-			{
-				ir = list.getElementAt(i) as ListItemRenderer;
-				if(filterFunction(ir.text, filterText))
-				{
-					ir.visible = true;
-				} else {
-					ir.visible = false;
-				}
+			const inputBase:TextInputBase = event.target as TextInputBase;
+			//keyup can include other things like tab navigation
+            IComboBoxView
+			if (!inputBase) {
+				//if (popUpVisible)  event.target.parent.view.popUpVisible = false;
+				return;
 			}
+            var popUpVisible:Boolean =  event.target.parent.view.popUpVisible;
+            if (!popUpVisible) {
+                //force popup ?:
+                event.target.parent.view.popUpVisible = true;
+
+                //or avoid ?:
+                //return;
+            }
+            applyFilter(inputBase);
         }
+
+        protected function applyFilter(input:TextInputBase):void{
+            var filterText:String = input.text.toUpperCase();
+
+            // the internal list in the combobox popup
+            var list:List =  Object(input).parent.view.popup.view.list;
+
+            var ir:ListItemRenderer;
+            var numElements:int = list.numElements;
+            var count:uint = 0;
+            var lastActive:ListItemRenderer;
+            for (var i:int = 0; i < numElements; i++)
+            {
+                ir = list.getElementAt(i) as ListItemRenderer;
+                if (filterFunction(ir.text, filterText))
+                {
+                    ir.visible = true;
+                    lastActive = ir;
+                    count++;
+                } else {
+                    ir.visible = false;
+                }
+            }
+            if (count == 1) {
+                //select lastActive if there is only one that matches?
+
+            }
+		}
+
 	}
 }
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 8d7aecb..cb029ea 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
@@ -41,12 +41,12 @@ package org.apache.royale.jewel.beads.views
 	import org.apache.royale.jewel.supportClasses.ResponsiveSizes;
 	import org.apache.royale.jewel.supportClasses.util.positionInsideBoundingClientRect;
 	import org.apache.royale.utils.UIUtils;
-	
+
 	/**
-	 *  The ComboBoxView class creates the visual elements of the org.apache.royale.jewel.ComboBox 
+	 *  The ComboBoxView class creates the visual elements of the org.apache.royale.jewel.ComboBox
 	 *  component. The job of the view bead is to put together the parts of the ComboBox such as the TextInput
 	 *  control and org.apache.royale.jewel.Button to trigger the pop-up.
-	 *  
+	 *
 	 *  @viewbead
 	 *  @langversion 3.0
 	 *  @playerversion Flash 10.2
@@ -59,11 +59,11 @@ package org.apache.royale.jewel.beads.views
 		{
 			super();
 		}
-		
+
 		private var _textinput:TextInput;
 		/**
 		 *  The TextInput component of the ComboBox.
-		 * 
+		 *
 		 *  @copy org.apache.royale.jewel.beads.controls.combobox.IComboBoxView#textinput
 		 *
 		 *  @langversion 3.0
@@ -75,11 +75,11 @@ package org.apache.royale.jewel.beads.views
 		{
 			return _textinput;
 		}
-		
+
 		private var _button:Button;
 		/**
 		 *  The Button component of the ComboBox.
-		 * 
+		 *
 		 *  @copy org.apache.royale.jewel.beads.controls.combobox.IComboBoxView#button
 		 *
 		 *  @langversion 3.0
@@ -91,13 +91,13 @@ package org.apache.royale.jewel.beads.views
 		{
 			return _button;
 		}
-		
+
 		private var _comboPopUp:ComboBoxPopUp;
 		private var _list:List;
-		
+
 		/**
 		 *  The pop-up list component of the ComboBox.
-		 * 
+		 *
 		 *  @copy org.apache.royale.jewel.beads.controls.combobox.IComboBoxView#popup
 		 *
 		 *  @langversion 3.0
@@ -109,7 +109,7 @@ package org.apache.royale.jewel.beads.views
 		{
 			return _comboPopUp;
 		}
-		
+
 		/**
 		 * @private
 		 * @royaleignorecoercion org.apache.royale.events.IEventDispatcher
@@ -118,33 +118,39 @@ package org.apache.royale.jewel.beads.views
 		override public function set strand(value:IStrand):void
 		{
 			super.strand = value;
-			
+
 			var host:StyledUIBase = _strand as StyledUIBase;
 
 			_textinput = new TextInput();
-			
+            /*COMPILE::JS {
+                _textinput.element.addEventListener('blur', handleFocusOut);
+            }*/
+
 			_button = new Button();
+			COMPILE::JS {
+                _button.element.setAttribute('tabindex', -1);
+			}
 			_button.text = '\u25BC';
-			
+
 			initSize();
-			
+
 			host.addElement(_textinput);
 			host.addElement(_button);
-			
+
 			model = _strand.getBeadByType(IComboBoxModel) as IComboBoxModel;
 			model.addEventListener("selectedIndexChanged", handleItemChange);
 			model.addEventListener("selectedItemChanged", handleItemChange);
 			model.addEventListener("dataProviderChanged", itemChangeAction);
-			
+
 			IEventDispatcher(_strand).addEventListener("sizeChanged", handleSizeChange);
 		}
 
 		private var model:IComboBoxModel;
-		
+
 		private var _popUpClass:Class;
 		/**
 		 *  Returns whether or not the pop-up is visible.
-		 * 
+		 *
 		 *  @copy org.apache.royale.jewel.beads.controls.combobox.IComboBoxView#popUpVisible
 		 *
 		 *  @langversion 3.0
@@ -154,7 +160,7 @@ package org.apache.royale.jewel.beads.views
 		 */
 		public function get popUpVisible():Boolean
 		{
-			return _comboPopUp == null ? false : true;
+			return _comboPopUp != null;
 		}
 		/**
 		 * @royaleignorecoercion org.apache.royale.core.IComboBoxModel
@@ -163,28 +169,30 @@ package org.apache.royale.jewel.beads.views
 		public function set popUpVisible(value:Boolean):void
 		{
 			if (value) {
-				if(!_popUpClass)
-				{
-					_popUpClass = ValuesManager.valuesImpl.getValue(_strand, "iPopUp") as Class;
-				}
-				_comboPopUp = new _popUpClass() as ComboBoxPopUp;
-				_comboPopUp.model = model;
+				if (_comboPopUp == null) {
+                    if(!_popUpClass)
+                    {
+                        _popUpClass = ValuesManager.valuesImpl.getValue(_strand, "iPopUp") as Class;
+                    }
+                    _comboPopUp = new _popUpClass() as ComboBoxPopUp;
+                    _comboPopUp.model = model;
 
-				var popupHost:IPopUpHost = UIUtils.findPopUpHost(_strand as IUIBase);
-				popupHost.popUpParent.addElement(_comboPopUp);
-				
-				// popup is ComboBoxPopUp that fills 100% of browser window-> We want the internal List inside its view to adjust height
-				_list = (_comboPopUp.view as ComboBoxPopUpView).list;
-				// _list.model = _comboPopUp.model;
-				
-				setTimeout(prepareForPopUp,  300);
+                    var popupHost:IPopUpHost = UIUtils.findPopUpHost(_strand as IUIBase);
+                    popupHost.popUpParent.addElement(_comboPopUp);
 
-				COMPILE::JS
-				{
-				window.addEventListener('resize', autoResizeHandler, false);
-				}
+                    // popup is ComboBoxPopUp that fills 100% of browser window-> We want the internal List inside its view to adjust height
+                    _list = (_comboPopUp.view as ComboBoxPopUpView).list;
+                    // _list.model = _comboPopUp.model;
+
+                    setTimeout(prepareForPopUp,  300);
 
-				autoResizeHandler();
+                    COMPILE::JS
+                    {
+                        window.addEventListener('resize', autoResizeHandler, false);
+                    }
+
+                    autoResizeHandler();
+				}
 			}
 			else if(_comboPopUp != null) {
 				UIUtils.removePopUp(_comboPopUp);
@@ -201,20 +209,23 @@ package org.apache.royale.jewel.beads.views
         {
 			COMPILE::JS
 			{
-				_comboPopUp.element.classList.add("open");
-				//avoid scroll in html
-				document.body.classList.add("viewport");
+				//check here for non-null in case popUpVisible was toggled off before timeout runs
+				if (_comboPopUp != null) {
+                    _comboPopUp.element.classList.add("open");
+                    //avoid scroll in html
+                    document.body.classList.add("viewport");
+				}
 			}
 		}
 
-		/**
+        /**
 		 * @private
 		 */
 		protected function handleSizeChange(event:Event):void
 		{
 			sizeChangeAction();
 		}
-		
+
 		/**
 		 * @private
 		 */
@@ -222,7 +233,7 @@ package org.apache.royale.jewel.beads.views
 		{
 			itemChangeAction();
 		}
-		
+
 		/**
 		 * @private
 		 * @royaleignorecoercion org.apache.royale.core.IComboBoxModel
@@ -232,10 +243,10 @@ package org.apache.royale.jewel.beads.views
 			var model:IComboBoxModel = _strand.getBeadByType(IComboBoxModel) as IComboBoxModel;
 			_textinput.text = getLabelFromData(model, model.selectedItem);
 		}
-		
+
 		/**
 		 * Size the component at start up
-		 * 
+		 *
 		 * @private
 		 */
 		protected function initSize():void
@@ -257,7 +268,7 @@ package org.apache.royale.jewel.beads.views
 
 		/**
 		 * Manages the resize of the component
-		 * 
+		 *
 		 * @private
 		 */
 		protected function sizeChangeAction():void
@@ -265,7 +276,6 @@ package org.apache.royale.jewel.beads.views
 			host.width = _textinput.width + _button.width;
 		}
 
-		protected var comboList:ComboBoxPopUp;
 		/**
 		 *  Adapt the popup list to the right position taking into account
 		 *  if we are in DESKTOP screen size or in PHONE/TABLET screen size
@@ -282,11 +292,11 @@ package org.apache.royale.jewel.beads.views
 				var outerWidth:Number = document.body.getBoundingClientRect().width;
 				// handle potential scrolls offsets
 				var top:Number = (window.pageYOffset || document.documentElement.scrollTop)  - (document.documentElement.clientTop || 0);
-				
+
 				// Desktop width size
 				if(outerWidth > ResponsiveSizes.DESKTOP_BREAKPOINT)
 				{
-					//poopup width needs to be set before position inside bounding client to work ok
+					//popup width needs to be set before position inside bounding client to work ok
 					_list.width = _textinput.width + _button.width;
 
 					var origin:Point = new Point(0, button.y + button.height - top);
@@ -298,7 +308,7 @@ package org.apache.royale.jewel.beads.views
 				{
 					_list.positioner.style["left"] = "50%";
 					_list.positioner.style["top"] = "calc(100% - 10px)";
-					// _list.positioner.style["width"] = "initial"; 
+					// _list.positioner.style["width"] = "initial";
 				}
 			}
 		}
diff --git a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DateFieldView.as b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DateFieldView.as
index 359dd59..2821d88 100644
--- a/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DateFieldView.as
+++ b/frameworks/projects/Jewel/src/main/royale/org/apache/royale/jewel/beads/views/DateFieldView.as
@@ -131,6 +131,9 @@ package org.apache.royale.jewel.beads.views
 			getHost().addElement(_textInput);
 
 			_button = new Button();
+			COMPILE::JS {
+                _button.element.setAttribute('tabindex', -1);
+			}
 			_button.text = "&darr;";
 			getHost().addElement(_button);