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 = "↓";
getHost().addElement(_button);