Commit de8ad4670d8e735edc5eb3202bd564b54fe9e103

Authored by bernard
1 parent b536dfe6

Added priority and skipped attributes to focus component.

@@ -43,5 +43,20 @@ @@ -43,5 +43,20 @@
43 </description> 43 </description>
44 <defaultvalue>""</defaultvalue> 44 <defaultvalue>""</defaultvalue>
45 </property> 45 </property>
  46 + <property>
  47 + <name>priority</name>
  48 + <classname>java.lang.Integer</classname>
  49 + <description>
  50 + If there are more components requesting focus, then component with lowest priority will be focused.
  51 + </description>
  52 + </property>
  53 + <property>
  54 + <name>skipped</name>
  55 + <classname>boolean</classname>
  56 + <description>
  57 + If set to true, component will not be concerned when calculating default focus.
  58 + </description>
  59 + <defaultvalue>false</defaultvalue>
  60 + </property>
46 </component> 61 </component>
47 </components> 62 </components>
@@ -5,32 +5,71 @@ import javax.faces.component.UIComponentBase; @@ -5,32 +5,71 @@ import javax.faces.component.UIComponentBase;
5 import javax.faces.component.UIForm; 5 import javax.faces.component.UIForm;
6 import javax.faces.component.UIInput; 6 import javax.faces.component.UIInput;
7 import javax.faces.context.FacesContext; 7 import javax.faces.context.FacesContext;
  8 +import java.util.ArrayList;
8 import java.util.HashSet; 9 import java.util.HashSet;
9 import java.util.Iterator; 10 import java.util.Iterator;
  11 +import java.util.List;
10 import java.util.Set; 12 import java.util.Set;
11 13
12 public abstract class UIFocus extends UIComponentBase { 14 public abstract class UIFocus extends UIComponentBase {
  15 +// ------------------------------ FIELDS ------------------------------
  16 +
  17 + public static final String COMPONENT_FAMILY = "org.richfaces.Focus";
13 18
14 public static final String COMPONENT_TYPE = "org.richfaces.Focus"; 19 public static final String COMPONENT_TYPE = "org.richfaces.Focus";
15 20
16 - public static final String COMPONENT_FAMILY = "org.richfaces.Focus"; 21 + public static final int DEFAULT_PRIORITY = Integer.MAX_VALUE;
  22 +
  23 + public static final String FOCUS_MODIFIER_FACET_NAME = "focusModifier";
17 24
18 public static final String TIMING_ON_LOAD = "onload"; 25 public static final String TIMING_ON_LOAD = "onload";
19 26
20 - public static final String FOCUS_MODIFIER_FACET_NAME = "focusModifier"; 27 +// -------------------------- STATIC METHODS --------------------------
21 28
22 - public Integer getDefaultPriority(FacesContext context) {  
23 - UIComponent parentForm = getParent(); 29 + public static UIFocusModifier findModifier(UIComponent component) {
  30 + if (component instanceof UIFocusModifier) {
  31 + return (UIFocusModifier) component;
  32 + }
  33 + UIFocusModifier modifier = (UIFocusModifier) component.getFacet(UIFocus.FOCUS_MODIFIER_FACET_NAME);
  34 + if (modifier == null) {
  35 + for (UIComponent child : component.getChildren()) {
  36 + modifier = findModifier(child);
  37 + if (modifier != null) {
  38 + break;
  39 + }
  40 + }
  41 + }
  42 + return modifier;
  43 + }
  44 +
  45 +// -------------------------- OTHER METHODS --------------------------
  46 +
  47 + public int calculatePriority(UIComponent component) {
  48 + final UIFocusModifier modifier = findModifier(component);
  49 + if (modifier != null && modifier.getPriority() != null) {
  50 + return modifier.getPriority();
  51 + }
  52 + UIComponent parentForm = component.getParent();
24 while (parentForm != null && !(parentForm instanceof UIForm)) { 53 while (parentForm != null && !(parentForm instanceof UIForm)) {
25 parentForm = parentForm.getParent(); 54 parentForm = parentForm.getParent();
26 } 55 }
27 if (parentForm != null) { 56 if (parentForm != null) {
28 - return getUIInputChildrenCount(parentForm, getTargetComponentId(context)); 57 + return getUIInputChildrenCount(parentForm, component.getId());
29 } else { 58 } else {
30 - return Integer.MAX_VALUE; 59 + return DEFAULT_PRIORITY;
31 } 60 }
32 } 61 }
33 62
  63 + public abstract String getFor();
  64 +
  65 + public abstract String getName();
  66 +
  67 + public abstract Integer getPriority();
  68 +
  69 + public abstract String getSuffix();
  70 +
  71 + public abstract String getTargetClientId();
  72 +
34 public String getTargetComponentId(FacesContext context) { 73 public String getTargetComponentId(FacesContext context) {
35 String aFor = getFor(); 74 String aFor = getFor();
36 75
@@ -43,68 +82,49 @@ public abstract class UIFocus extends UIComponentBase { @@ -43,68 +82,49 @@ public abstract class UIFocus extends UIComponentBase {
43 while (clientIdsWithMessages.hasNext()) { 82 while (clientIdsWithMessages.hasNext()) {
44 allowedClientIds.add(clientIdsWithMessages.next()); 83 allowedClientIds.add(clientIdsWithMessages.next());
45 } 84 }
46 - UIComponent component = getFirstInput(getParentForm(this), allowedClientIds);  
47 - return component == null ? null : component.getClientId(context); 85 + final List<UIInput> inputs = new ArrayList<UIInput>();
  86 + getInputs(getParentForm(this), allowedClientIds, inputs);
  87 + UIInput inputWithLowestPriority = null;
  88 + int lowestPriority = Integer.MAX_VALUE;
  89 + for (UIInput input : inputs) {
  90 + final int priority = calculatePriority(input);
  91 + if (priority < lowestPriority) {
  92 + inputWithLowestPriority = input;
  93 + lowestPriority = priority;
  94 + }
  95 + }
  96 + return inputWithLowestPriority == null ? null : inputWithLowestPriority.getClientId(context);
48 } else { 97 } else {
49 return getParent().getClientId(context); 98 return getParent().getClientId(context);
50 } 99 }
51 } 100 }
52 } 101 }
53 102
54 - private int getUIInputChildrenCount(UIComponent component, String breakOnId) {  
55 - int inputComponentsCount = 0;  
56 - for (UIComponent child : component.getChildren()) {  
57 - if (child.getId().equals(breakOnId)) {  
58 - break;  
59 - }  
60 - if (child instanceof UIInput) {  
61 - inputComponentsCount++;  
62 - } else {  
63 - int uIInputChildrenCount = getUIInputChildrenCount(child, breakOnId);  
64 - inputComponentsCount += uIInputChildrenCount;  
65 - }  
66 - }  
67 - return inputComponentsCount;  
68 - }  
69 -  
70 - public abstract String getFor(); 103 + public abstract String getTiming();
71 104
72 public abstract void setFor(String value); 105 public abstract void setFor(String value);
73 106
74 - public abstract String getTargetClientId();  
75 -  
76 - public abstract void setTargetClientId(String targetClientId);  
77 -  
78 - public abstract String getSuffix();  
79 -  
80 - public abstract void setSuffix(String value);  
81 -  
82 - public abstract Integer getPriority(); 107 + public abstract void setName(String name);
83 108
84 public abstract void setPriority(Integer value); 109 public abstract void setPriority(Integer value);
85 110
86 - public abstract String getTiming();  
87 -  
88 - public abstract String getName(); 111 + public abstract void setSuffix(String value);
89 112
90 - public abstract void setName(String name); 113 + public abstract void setTargetClientId(String targetClientId);
91 114
92 public abstract void setTiming(String timing); 115 public abstract void setTiming(String timing);
93 116
94 - private UIComponent getFirstInput(UIComponent parent, Set<String> allowedClientIds) {  
95 - UIComponent input = null; 117 + private void getInputs(UIComponent parent, Set<String> allowedClientIds, List<UIInput> inputs) {
96 FacesContext facesContext = getFacesContext(); 118 FacesContext facesContext = getFacesContext();
97 for (UIComponent child : parent.getChildren()) { 119 for (UIComponent child : parent.getChildren()) {
98 if (child instanceof UIInput && (allowedClientIds.size() == 0 || allowedClientIds.contains(child.getClientId(facesContext)))) { 120 if (child instanceof UIInput && (allowedClientIds.size() == 0 || allowedClientIds.contains(child.getClientId(facesContext)))) {
99 - return child;  
100 - } else {  
101 - input = getFirstInput(child, allowedClientIds);  
102 - if (input != null) {  
103 - break; 121 + final UIFocusModifier modifier = findModifier(child);
  122 + if (modifier == null || !modifier.isSkipped()) {
  123 + inputs.add((UIInput) child);
104 } 124 }
105 } 125 }
  126 + getInputs(child, allowedClientIds, inputs);
106 } 127 }
107 - return input;  
108 } 128 }
109 129
110 private UIForm getParentForm(UIComponent component) { 130 private UIForm getParentForm(UIComponent component) {
@@ -118,4 +138,36 @@ public abstract class UIFocus extends UIComponentBase { @@ -118,4 +138,36 @@ public abstract class UIFocus extends UIComponentBase {
118 return getParentForm(parent); 138 return getParentForm(parent);
119 } 139 }
120 } 140 }
  141 +
  142 + private int getUIInputChildrenCount(UIComponent component, String breakOnId) {
  143 + final Holder<Integer> childrenCount = new Holder<Integer>();
  144 + childrenCount.value = 0;
  145 + getUIInputChildrenCount(component, breakOnId, childrenCount);
  146 + return childrenCount.value;
  147 + }
  148 +
  149 + private boolean getUIInputChildrenCount(UIComponent component, String breakOnId, Holder<Integer> childrenCount) {
  150 + for (UIComponent child : component.getChildren()) {
  151 + if (child.getId().equals(breakOnId)) {
  152 + return true;
  153 + }
  154 + if (child instanceof UIInput) {
  155 + final UIFocusModifier modifier = findModifier(child);
  156 + if (modifier == null || !modifier.isSkipped()) {
  157 + childrenCount.value++;
  158 + }
  159 + } else {
  160 + if (getUIInputChildrenCount(child, breakOnId, childrenCount)) return true;
  161 + }
  162 + }
  163 + return false;
  164 + }
  165 +
  166 +// -------------------------- INNER CLASSES --------------------------
  167 +
  168 + private class Holder<T> {
  169 +// ------------------------------ FIELDS ------------------------------
  170 +
  171 + public T value;
  172 + }
121 } 173 }
@@ -11,11 +11,19 @@ public abstract class UIFocusModifier extends UIComponentBase { @@ -11,11 +11,19 @@ public abstract class UIFocusModifier extends UIComponentBase {
11 11
12 // -------------------------- OTHER METHODS -------------------------- 12 // -------------------------- OTHER METHODS --------------------------
13 13
14 - public abstract String getTargetClientId(); 14 + public abstract Integer getPriority();
15 15
16 public abstract String getSuffix(); 16 public abstract String getSuffix();
17 17
18 - public abstract void setTargetClientId(String focusClientId); 18 + public abstract String getTargetClientId();
  19 +
  20 + public abstract boolean isSkipped();
  21 +
  22 + public abstract void setPriority(Integer priority);
  23 +
  24 + public abstract void setSkipped(boolean skipped);
19 25
20 public abstract void setSuffix(String value); 26 public abstract void setSuffix(String value);
  27 +
  28 + public abstract void setTargetClientId(String focusClientId);
21 } 29 }
@@ -32,6 +32,7 @@ import org.richfaces.component.UIFocusModifier; @@ -32,6 +32,7 @@ import org.richfaces.component.UIFocusModifier;
32 32
33 import javax.faces.FacesException; 33 import javax.faces.FacesException;
34 import javax.faces.component.UIComponent; 34 import javax.faces.component.UIComponent;
  35 +import javax.faces.component.UIInput;
35 import javax.faces.context.FacesContext; 36 import javax.faces.context.FacesContext;
36 import javax.faces.context.ResponseWriter; 37 import javax.faces.context.ResponseWriter;
37 import java.io.IOException; 38 import java.io.IOException;
@@ -58,6 +59,26 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase { @@ -58,6 +59,26 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
58 return styles; 59 return styles;
59 } 60 }
60 61
  62 + private void checkValidity(FacesContext context, UIFocus component) {
  63 + String clientId = getUtils().clientId(context, component);
  64 + String name = component.getName();
  65 + String timing = component.getTiming();
  66 + String _for = component.getFor();
  67 + String targetClientId = component.getTargetClientId();
  68 + if ((name == null || "".equals(name.trim())) && "onJScall".equals(timing)) {
  69 + throw new FacesException(
  70 + "The name attribute of the focus component (id='" + clientId + "') must be specified when timing attribute equals to 'onJScall'");
  71 + }
  72 + if (name != null && !"".equals(name.trim()) && !"onJScall".equals(timing)) {
  73 + throw new FacesException(
  74 + "The timing attribute of the focus component (id='" + clientId + "') must be set to 'onJScall' when name attribute is specified");
  75 + }
  76 + if ((_for == null || "".equals(_for)) && (targetClientId == null || "".equals(targetClientId)) && !(component.getParent() instanceof UIInput)
  77 + && getUtils().getNestingForm(context, component) == null) {
  78 + throw new FacesException("Focus component must have either one of 'for' or 'targetClientId' attributes specified or be nested within UIForm or UIInput component");
  79 + }
  80 + }
  81 +
61 @Override 82 @Override
62 protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component) 83 protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component)
63 throws IOException { 84 throws IOException {
@@ -66,11 +87,8 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase { @@ -66,11 +87,8 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
66 } 87 }
67 UIFocus uiFocus = (UIFocus) component; 88 UIFocus uiFocus = (UIFocus) component;
68 final String clientId = getUtils().clientId(context, component); 89 final String clientId = getUtils().clientId(context, component);
69 - checkValidity(clientId, uiFocus.getName(), uiFocus.getTiming()); 90 + checkValidity(context, uiFocus);
70 Integer priority = uiFocus.getPriority(); 91 Integer priority = uiFocus.getPriority();
71 - if (priority == null) {  
72 - priority = uiFocus.getDefaultPriority(context);  
73 - }  
74 String targetClientId = uiFocus.getTargetClientId(); 92 String targetClientId = uiFocus.getTargetClientId();
75 if (targetClientId == null || "".equals(targetClientId)) { 93 if (targetClientId == null || "".equals(targetClientId)) {
76 String targetComponentId = uiFocus.getTargetComponentId(context); 94 String targetComponentId = uiFocus.getTargetComponentId(context);
@@ -83,7 +101,7 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase { @@ -83,7 +101,7 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
83 throw new FacesException("No component with id=" + targetComponentId + " found!"); 101 throw new FacesException("No component with id=" + targetComponentId + " found!");
84 } 102 }
85 targetClientId = forcomp.getClientId(context); 103 targetClientId = forcomp.getClientId(context);
86 - UIFocusModifier modifier = findModifier(forcomp); 104 + UIFocusModifier modifier = UIFocus.findModifier(forcomp);
87 if (modifier != null) { 105 if (modifier != null) {
88 final String modifiedTargetClientId = modifier.getTargetClientId(); 106 final String modifiedTargetClientId = modifier.getTargetClientId();
89 if (modifiedTargetClientId != null && !modifiedTargetClientId.equals("")) { 107 if (modifiedTargetClientId != null && !modifiedTargetClientId.equals("")) {
@@ -92,6 +110,9 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase { @@ -92,6 +110,9 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
92 suffix = modifier.getSuffix(); 110 suffix = modifier.getSuffix();
93 } 111 }
94 } 112 }
  113 + if (priority == null) {
  114 + priority = uiFocus.calculatePriority(forcomp);
  115 + }
95 if (suffix != null && !"".equals(suffix)) { 116 if (suffix != null && !"".equals(suffix)) {
96 targetClientId += suffix; 117 targetClientId += suffix;
97 } 118 }
@@ -99,6 +120,9 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase { @@ -99,6 +120,9 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
99 if (targetClientId == null || targetClientId.equals("")) { 120 if (targetClientId == null || targetClientId.equals("")) {
100 return; 121 return;
101 } 122 }
  123 + if (priority == null) {
  124 + priority = UIFocus.DEFAULT_PRIORITY;
  125 + }
102 writer.startElement(RendererUtils.HTML.SCRIPT_ELEM, null); 126 writer.startElement(RendererUtils.HTML.SCRIPT_ELEM, null);
103 writer.writeAttribute(RendererUtils.HTML.TYPE_ATTR, "text/javascript", "type"); 127 writer.writeAttribute(RendererUtils.HTML.TYPE_ATTR, "text/javascript", "type");
104 writer.writeAttribute(RendererUtils.HTML.id_ATTRIBUTE, clientId, RendererUtils.HTML.id_ATTRIBUTE); 128 writer.writeAttribute(RendererUtils.HTML.id_ATTRIBUTE, clientId, RendererUtils.HTML.id_ATTRIBUTE);
@@ -119,34 +143,7 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase { @@ -119,34 +143,7 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
119 writer.endElement(RendererUtils.HTML.SCRIPT_ELEM); 143 writer.endElement(RendererUtils.HTML.SCRIPT_ELEM);
120 } 144 }
121 145
122 - private void checkValidity(String clientId, String name, String timing) {  
123 - if ((name == null || "".equals(name.trim())) && "onJScall".equals(timing)) {  
124 - throw new FacesException(  
125 - "The name attribute of the focus component (id='" + clientId + "') must be specified when timing attribute equals to 'onJScall'");  
126 - }  
127 - if (name != null && !"".equals(name.trim()) && !"onJScall".equals(timing)) {  
128 - throw new FacesException(  
129 - "The timing attribute of the focus component (id='" + clientId + "') must be set to 'onJScall' when name attribute is specified");  
130 - }  
131 - }  
132 -  
133 protected Class<? extends UIComponent> getComponentClass() { 146 protected Class<? extends UIComponent> getComponentClass() {
134 return UIFocus.class; 147 return UIFocus.class;
135 } 148 }
136 -  
137 - private UIFocusModifier findModifier(UIComponent component) {  
138 - if (component instanceof UIFocusModifier) {  
139 - return (UIFocusModifier) component;  
140 - }  
141 - UIFocusModifier modifier = (UIFocusModifier) component.getFacet(UIFocus.FOCUS_MODIFIER_FACET_NAME);  
142 - if (modifier == null) {  
143 - for (UIComponent child : component.getChildren()) {  
144 - modifier = findModifier(child);  
145 - if (modifier != null) {  
146 - break;  
147 - }  
148 - }  
149 - }  
150 - return modifier;  
151 - }  
152 } 149 }
Please register or login to post a comment