Commit de8ad4670d8e735edc5eb3202bd564b54fe9e103

Authored by bernard
1 parent b536dfe6

Added priority and skipped attributes to focus component.

... ... @@ -43,5 +43,20 @@
43 43 </description>
44 44 <defaultvalue>""</defaultvalue>
45 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 61 </component>
47 62 </components>
... ...
... ... @@ -5,32 +5,71 @@ import javax.faces.component.UIComponentBase;
5 5 import javax.faces.component.UIForm;
6 6 import javax.faces.component.UIInput;
7 7 import javax.faces.context.FacesContext;
  8 +import java.util.ArrayList;
8 9 import java.util.HashSet;
9 10 import java.util.Iterator;
  11 +import java.util.List;
10 12 import java.util.Set;
11 13
12 14 public abstract class UIFocus extends UIComponentBase {
  15 +// ------------------------------ FIELDS ------------------------------
  16 +
  17 + public static final String COMPONENT_FAMILY = "org.richfaces.Focus";
13 18
14 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 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 53 while (parentForm != null && !(parentForm instanceof UIForm)) {
25 54 parentForm = parentForm.getParent();
26 55 }
27 56 if (parentForm != null) {
28   - return getUIInputChildrenCount(parentForm, getTargetComponentId(context));
  57 + return getUIInputChildrenCount(parentForm, component.getId());
29 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 73 public String getTargetComponentId(FacesContext context) {
35 74 String aFor = getFor();
36 75
... ... @@ -43,68 +82,49 @@ public abstract class UIFocus extends UIComponentBase {
43 82 while (clientIdsWithMessages.hasNext()) {
44 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 97 } else {
49 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 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 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 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 118 FacesContext facesContext = getFacesContext();
97 119 for (UIComponent child : parent.getChildren()) {
98 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 130 private UIForm getParentForm(UIComponent component) {
... ... @@ -118,4 +138,36 @@ public abstract class UIFocus extends UIComponentBase {
118 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
12 12 // -------------------------- OTHER METHODS --------------------------
13 13
14   - public abstract String getTargetClientId();
  14 + public abstract Integer getPriority();
15 15
16 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 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 32
33 33 import javax.faces.FacesException;
34 34 import javax.faces.component.UIComponent;
  35 +import javax.faces.component.UIInput;
35 36 import javax.faces.context.FacesContext;
36 37 import javax.faces.context.ResponseWriter;
37 38 import java.io.IOException;
... ... @@ -58,6 +59,26 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
58 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 82 @Override
62 83 protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent component)
63 84 throws IOException {
... ... @@ -66,11 +87,8 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
66 87 }
67 88 UIFocus uiFocus = (UIFocus) component;
68 89 final String clientId = getUtils().clientId(context, component);
69   - checkValidity(clientId, uiFocus.getName(), uiFocus.getTiming());
  90 + checkValidity(context, uiFocus);
70 91 Integer priority = uiFocus.getPriority();
71   - if (priority == null) {
72   - priority = uiFocus.getDefaultPriority(context);
73   - }
74 92 String targetClientId = uiFocus.getTargetClientId();
75 93 if (targetClientId == null || "".equals(targetClientId)) {
76 94 String targetComponentId = uiFocus.getTargetComponentId(context);
... ... @@ -83,7 +101,7 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
83 101 throw new FacesException("No component with id=" + targetComponentId + " found!");
84 102 }
85 103 targetClientId = forcomp.getClientId(context);
86   - UIFocusModifier modifier = findModifier(forcomp);
  104 + UIFocusModifier modifier = UIFocus.findModifier(forcomp);
87 105 if (modifier != null) {
88 106 final String modifiedTargetClientId = modifier.getTargetClientId();
89 107 if (modifiedTargetClientId != null && !modifiedTargetClientId.equals("")) {
... ... @@ -92,6 +110,9 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
92 110 suffix = modifier.getSuffix();
93 111 }
94 112 }
  113 + if (priority == null) {
  114 + priority = uiFocus.calculatePriority(forcomp);
  115 + }
95 116 if (suffix != null && !"".equals(suffix)) {
96 117 targetClientId += suffix;
97 118 }
... ... @@ -99,6 +120,9 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
99 120 if (targetClientId == null || targetClientId.equals("")) {
100 121 return;
101 122 }
  123 + if (priority == null) {
  124 + priority = UIFocus.DEFAULT_PRIORITY;
  125 + }
102 126 writer.startElement(RendererUtils.HTML.SCRIPT_ELEM, null);
103 127 writer.writeAttribute(RendererUtils.HTML.TYPE_ATTR, "text/javascript", "type");
104 128 writer.writeAttribute(RendererUtils.HTML.id_ATTRIBUTE, clientId, RendererUtils.HTML.id_ATTRIBUTE);
... ... @@ -119,34 +143,7 @@ public class HtmlFocusRenderer extends HeaderResourcesRendererBase {
119 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 146 protected Class<? extends UIComponent> getComponentClass() {
134 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