/** {@inheritDoc} */ public boolean render(Context context, Object focus) { PrintWriter response = context.getResponseWriter(); // included? if (!isIncluded(context, focus)) return false; // read only? boolean readOnly = false; if (this.readOnly != null) { readOnly = this.readOnly.decide(context, focus); } // read only collapsed? boolean readOnlyCollapsed = false; if (this.readOnlyCollapsed != null) { readOnlyCollapsed = this.readOnlyCollapsed.decide(context, focus); if (readOnlyCollapsed) readOnly = true; } // single select? boolean single = true; if (this.singleSelectDecision != null) { single = this.singleSelectDecision.decide(context, focus); } // alert if empty at submit? boolean onEmptyAlert = false; if (this.onEmptyAlertMsg != null) { onEmptyAlert = true; if (this.onEmptyAlertDecision != null) { onEmptyAlert = this.onEmptyAlertDecision.decide(context, focus); } } // find values and display text List<String> values = new ArrayList<String>(); if (!this.selectionValues.isEmpty()) { for (Message msg : this.selectionValues) { if (msg != null) { values.add(msg.getMessage(context, focus)); } else { values.add(""); } } } List<String> display = new ArrayList<String>(); if (!this.selectionMessages.isEmpty()) { for (Message msg : this.selectionMessages) { if (msg != null) { display.add(msg.getMessage(context, focus)); } else { display.add(""); } } } if (this.noprintflag) response.println("<div class=\"noprint\">"); // add in any from the model boolean fromModel = false; if ((this.selectionValueMessage != null) && (this.selectionDisplayMessage != null) && (this.selectionReference != null)) { // get the main collection Collection collection = null; Object obj = this.selectionReference.readObject(context, focus); if (obj != null) { if (obj instanceof Collection) { collection = (Collection) obj; } else if (obj.getClass().isArray()) { Object[] array = (Object[]) obj; collection = new ArrayList(array.length); for (Object o : array) { collection.add(o); } } } // if we got something if (collection != null) { // like iteration, make each object available then get the value and display int index = -1; for (Object o : collection) { index++; // place the item if (this.iteratorName != null) { context.put( this.iteratorName, o, this.selectionReference.getEncoding(context, o, index)); } values.add(this.selectionValueMessage.getMessage(context, o)); display.add(this.selectionDisplayMessage.getMessage(context, o)); fromModel = true; // remove item if (this.iteratorName != null) { context.remove(this.iteratorName); } } } } // read the current value(s) Set<String> value = new HashSet<String>(); if (this.propertyReference != null) { Object obj = this.propertyReference.readObject(context, focus); if (obj != null) { // any sort of collection if (obj instanceof Collection) { for (Object o : ((Collection) obj)) { value.add(o.toString()); } } // any sort of array if (obj.getClass().isArray()) { for (Object o : ((Object[]) obj)) { value.add(o.toString()); } } // otherwise take it as a string else { value.add(obj.toString()); } } } if (this.orientation == Orientation.dropdown) { renderDropdown(context, focus, readOnly, single, values, display, value); return true; } // generate some ids int idRoot = context.getUniqueId(); String id = getId(); if (id == null) id = this.getClass().getSimpleName() + "_" + idRoot; String decodeId = "decode_" + idRoot; String dependencyId = id + "_dependencies"; // read the "correct" value String correctValue = null; boolean includeCorrectMarkers = false; if ((this.correctReference != null) && ((this.correctDecision == null) || (this.correctDecision.decide(context, focus)))) { correctValue = this.correctReference.read(context, focus); if (correctValue != null) { includeCorrectMarkers = true; } } if (onEmptyAlert) { // this will become visible if a submit happens and the validation fails response.println( "<div class=\"ambrosiaAlert\" style=\"display:none\" id=\"alert_" + id + "\">" + this.onEmptyAlertMsg.getMessage(context, focus) + "</div>"); } boolean includeSelectAll = this.selectAll && (!single); // title if we are doing select all if (includeSelectAll) { response.print( "<input type=\"checkbox\" id=\"all_" + id + "\"" + " onclick=\"ambrosiaSelectGroup(this, ids_" + id + ");\"" + " />"); if (this.titleMessage != null) { response.print("<label for=\"all_" + id + "\">"); response.print(this.titleMessage.getMessage(context, focus)); response.println("</label><br /><br />"); } } // title otherwise else if (this.titleMessage != null) { response.print("<div class=\"ambrosiaComponentTitle\">"); response.print(this.titleMessage.getMessage(context, focus)); response.println("</div>"); } // for a single option (unless we are using values from the model, even just one) if ((values.size() == 1) && !fromModel) { final StringBuffer dependency = new StringBuffer(); dependency.append("var " + dependencyId + "=["); String startingValue = null; boolean needDependencies = false; String onclick = ""; boolean hasContained = false; for (ContainerRef cr : this.selectionContainers) { if ((cr.container != null) && (!cr.container.getContained().isEmpty())) { hasContained = true; break; } } if (this.submitDestination != null) { onclick = "onclick=\""; if (hasContained) { // onclick += "ambrosiaSelectDependencies(this.value, " + dependencyId + ");"; onclick += "ambrosiaSelectDependencies(document.getElementById(\'" + id + "\').checked, " + dependencyId + ");"; } String destination = this.submitDestination.getDestination(context, focus); onclick += "ambrosiaSubmit('" + destination + "')\" "; } else if (this.submitValue) { onclick = "onclick=\""; if (hasContained) { // onclick += "ambrosiaSelectDependencies(this.value, " + dependencyId + ");"; onclick += "ambrosiaSelectDependencies(document.getElementById(\'" + id + "\').checked, " + dependencyId + ");"; } onclick += "ambrosiaSubmit(this.value)\" "; } else if (hasContained) { // onclick = "onclick=\"ambrosiaSelectDependencies(this.value, " + dependencyId + ")\" "; onclick = "onclick=\"ambrosiaSelectDependencies(document.getElementById(\'" + id + "\').checked, " + dependencyId + ")\" "; } /* * if (this.submitDestination != null) { String destination = this.submitDestination.getDestination(context, focus); onclick = "onclick=\"ambrosiaSubmit('" + destination + "')\" "; } else if (this.submitValue) { onclick = * "onclick=\"ambrosiaSubmit(this.value)\" "; } */ // convert to boolean boolean checked = value.contains("true"); // if we are doing correct marking if (includeCorrectMarkers) { // if checked, mark as correct or not if (checked) { // is the value correct? boolean correct = (correctValue == null) ? false : Boolean.parseBoolean(correctValue) == checked; if (correct) { response.print( "<img src=\"" + context.getUrl(this.correctIcon) + "\" style=\"border-style: none;\" alt=\"" + this.correctMessage.getMessage(context, focus) + "\" title=\"" + this.correctMessage.getMessage(context, focus) + "\"/>"); } else { response.print( "<img src=\"" + context.getUrl(this.incorrectIcon) + "\" style=\"border-style: none;\" alt=\"" + this.incorrectMessage.getMessage(context, focus) + "\" title=\"" + this.incorrectMessage.getMessage(context, focus) + "\"/>"); } } // else leave a placeholder else { response.println("<div style=\"float:left;width:16px\"> </div>"); } } // the check box response.println( "<input " + onclick + "type=\"checkbox\" name=\"" + id + "\" id=\"" + id + "\" value=\"" + values.get(0) + "\" " + (checked ? "CHECKED" : "") + (readOnly ? " disabled=\"disabled\"" : "") + " />"); context.editComponentRendered(id); // the decode directive if ((this.propertyReference != null) && (!readOnly)) { response.println( "<input type=\"hidden\" name=\"" + decodeId + "\" value =\"" + id + "\" />" + "<input type=\"hidden\" name=\"" + "prop_" + decodeId + "\" value=\"" + this.propertyReference.getFullReference(context) + "\" />" + "<input type=\"hidden\" name=\"" + "null_" + decodeId + "\" value=\"" + this.notSelectedValue + "\" />"); } // title after (right) for the single check box version if ((display.size() > 0) && (display.get(0) != null)) { response.print("<label for=\"" + id + "\">"); response.print(display.get(0)); response.println("</label>"); } String fragment = ""; String val = null; ContainerRef containerRef = this.selectionContainers.get(0); // container of dependent components if ((containerRef != null) && (containerRef.container != null) && (!containerRef.container.getContained().isEmpty())) { needDependencies = true; val = values.get(0); dependency.append("[\"" + val + "\","); // dependency.append(Boolean.toString(true) + ","); dependency.append(Boolean.toString(containerRef.reversed) + ","); RenderListener listener = new RenderListener() { public void componentRendered(String id) { dependency.append("\"" + id + "\","); } }; // listen for any dependent edit components being rendered context.addEditComponentRenderListener(listener); // ContainerRef containerRef = this.selectionContainers.get(0); if (containerRef.separate) { context.setCollecting(); response = context.getResponseWriter(); } // render the dependent components for (Component c : containerRef.container.getContained()) { if (containerRef.separate) { if (containerRef.indented) { response.println("<div class=\"ambrosiaContainerComponentIndented\">"); } else { response.println("<div class=\"ambrosiaContainerComponent\">"); } } c.render(context, focus); if (containerRef.separate) response.println("</div>"); } if (containerRef.separate) { fragment += context.getCollected(); response = context.getResponseWriter(); } // stop listening context.removeEditComponentRenderListener(listener); dependency.setLength(dependency.length() - 1); dependency.append("],"); } /* * boolean selected = value.contains(val); * * if (selected) { startingValue = val; } */ if (needDependencies) { dependency.setLength(dependency.length() - 1); dependency.append("];\n"); context.addScript(dependency.toString()); // if read only, skip the initial setting if (!readOnly) { startingValue = String.valueOf(checked); // context.addScript("ambrosiaSelectDependencies(\"" + startingValue + "\", " + // dependencyId + ");\n"); context.addScript( "ambrosiaSelectDependencies(document.getElementById(\'" + id + "\').checked, " + dependencyId + ");\n"); // context.addScript("ambrosiaSelectDependencies(document.getElementById(" + id + // ").value, " + dependencyId + ");\n"); } } // the decode directive /* * if ((this.propertyReference != null) && (!readOnly)) { response.println("<input type=\"hidden\" name=\"" + decodeId + "\" value =\"" + id + "\" />" + "<input type=\"hidden\" name=\"" + "prop_" + decodeId + "\" value=\"" + * this.propertyReference.getFullReference(context) + "\" />"); } */ // for onEmptyAlert, add some client-side validation if ((onEmptyAlert) && (!readOnly) && single) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < values.size(); i++) { buf.append( "!document.getElementById('" + id + "_" + Integer.toString(i) + "').checked &&"); } buf.setLength(buf.length() - 3); context.addValidation( " if (" + buf.toString() + ")\n" + " {\n" + " if (document.getElementById('alert_" + id + "').style.display == \"none\")\n" + " {\n" + " document.getElementById('alert_" + id + "').style.display = \"\";\n" + " rv=false;\n" + " }\n" + " }\n"); } if (fragment.length() > 0) { response.print(fragment); } } else { final StringBuffer dependency = new StringBuffer(); dependency.append("var " + dependencyId + "=["); String startingValue = null; boolean needDependencies = false; String onclick = ""; boolean hasContained = false; for (ContainerRef cr : this.selectionContainers) { if ((cr.container != null) && (!cr.container.getContained().isEmpty())) { hasContained = true; break; } } if (this.submitDestination != null) { onclick = "onclick=\""; if (hasContained) { onclick += "ambrosiaSelectDependencies(this.value, " + dependencyId + ");"; } String destination = this.submitDestination.getDestination(context, focus); onclick += "ambrosiaSubmit('" + destination + "')\" "; } else if (this.submitValue) { onclick = "onclick=\""; if (hasContained) { onclick += "ambrosiaSelectDependencies(this.value, " + dependencyId + ");"; } onclick += "ambrosiaSubmit(this.value)\" "; } else if (hasContained) { onclick = "onclick=\"ambrosiaSelectDependencies(this.value, " + dependencyId + ")\" "; } else if (includeSelectAll) { onclick = "onclick=\"ambrosiaSelectChange(this, ids_" + id + ", 'all_" + id + "');\" "; } // collect the rendered ids List<String> ids = new ArrayList<String>(); // collected dependent components marked separate String fragment = ""; for (int i = 0; i < values.size(); i++) { String val = values.get(i); String message = ""; if (i < display.size()) { message = display.get(i); } ContainerRef containerRef = null; if (i < this.selectionContainers.size()) { containerRef = this.selectionContainers.get(i); } boolean selected = value.contains(val); if ((!selected) && readOnlyCollapsed) continue; if (selected) { startingValue = val; } // if we are doing correct marking if (includeCorrectMarkers) { // if checked, mark as correct or not if (selected) { // is this one the correct one? boolean correct = (correctValue == null) ? false : correctValue.equals(val); if (correct) { response.print( "<img src=\"" + context.getUrl(this.correctIcon) + "\" style=\"border-style: none;\" alt=\"" + this.correctMessage.getMessage(context, focus) + "\" title=\"" + this.correctMessage.getMessage(context, focus) + "\"/>"); } else { response.print( "<img src=\"" + context.getUrl(this.incorrectIcon) + "\" style=\"border-style: none;\" alt=\"" + this.incorrectMessage.getMessage(context, focus) + "\" title=\"" + this.incorrectMessage.getMessage(context, focus) + "\"/>"); } } // else leave a placeholder else { response.println("<div style=\"float:left;width:16px\"> </div>"); } } // use a radio for single select String thisId = id + "_" + i; if (single) { // the radio button response.println( "<input " + onclick + "type=\"radio\" name=\"" + id + "\" id=\"" + thisId + "\" value=\"" + val + "\" " + (selected ? "CHECKED" : "") + (readOnly ? " disabled=\"disabled\"" : "") + " />"); } // for multiple selection, use a checkbox set else { response.println( "<input " + onclick + "type=\"checkbox\" name=\"" + id + "\" id=\"" + thisId + "\" value=\"" + val + "\" " + (selected ? "CHECKED" : "") + (readOnly ? " disabled=\"disabled\"" : "") + " />"); } ids.add(thisId); // message response.print("<label for=\"" + thisId + "\">"); response.print(message); response.println("</label>"); // container of dependent components if ((containerRef != null) && (containerRef.container != null) && (!containerRef.container.getContained().isEmpty())) { needDependencies = true; dependency.append("[\"" + val + "\","); dependency.append(Boolean.toString(containerRef.reversed) + ","); RenderListener listener = new RenderListener() { public void componentRendered(String id) { dependency.append("\"" + id + "\","); } }; // listen for any dependent edit components being rendered context.addEditComponentRenderListener(listener); if (containerRef.separate) { context.setCollecting(); response = context.getResponseWriter(); } // render the dependent components for (Component c : containerRef.container.getContained()) { if (containerRef.separate) { if (containerRef.indented) { response.println("<div class=\"ambrosiaContainerComponentIndented\">"); } else { response.println("<div class=\"ambrosiaContainerComponent\">"); } } c.render(context, focus); if (containerRef.separate) response.println("</div>"); } if (containerRef.separate) { fragment += context.getCollected(); response = context.getResponseWriter(); } // stop listening context.removeEditComponentRenderListener(listener); dependency.setLength(dependency.length() - 1); dependency.append("],"); } if (this.orientation == Orientation.vertical) { response.println("<br />"); } } // register the ids in reverse order // Note: reverse order so that the first choice gets processed last, as in when this is a // dependent component to another selection Collections.reverse(ids); for (String thisId : ids) { context.editComponentRendered(thisId); } // record the group of checkbox element ids if (includeSelectAll) { StringBuilder buf = new StringBuilder(); buf.append("var ids_" + id + "=["); for (String oneId : ids) { buf.append("\"" + oneId + "\","); } buf.setLength(buf.length() - 1); buf.append("];\n"); context.addScript(buf.toString()); } if (needDependencies) { dependency.setLength(dependency.length() - 1); dependency.append("];\n"); context.addScript(dependency.toString()); // if read only, skip the initial setting if (!readOnly) { context.addScript( "ambrosiaSelectDependencies(\"" + startingValue + "\", " + dependencyId + ");\n"); } } // the decode directive if ((this.propertyReference != null) && (!readOnly)) { response.println( "<input type=\"hidden\" name=\"" + decodeId + "\" value =\"" + id + "\" />" + "<input type=\"hidden\" name=\"" + "prop_" + decodeId + "\" value=\"" + this.propertyReference.getFullReference(context) + "\" />"); } // for onEmptyAlert, add some client-side validation if ((onEmptyAlert) && (!readOnly) && single) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < values.size(); i++) { buf.append( "!document.getElementById('" + id + "_" + Integer.toString(i) + "').checked &&"); } buf.setLength(buf.length() - 3); context.addValidation( " if (" + buf.toString() + ")\n" + " {\n" + " if (document.getElementById('alert_" + id + "').style.display == \"none\")\n" + " {\n" + " document.getElementById('alert_" + id + "').style.display = \"\";\n" + " rv=false;\n" + " }\n" + " }\n"); } if (fragment.length() > 0) { response.print(fragment); } } if (this.noprintflag) response.println("</div>"); return true; }
/** {@inheritDoc} */ protected void renderDropdown( Context context, Object focus, boolean readOnly, boolean single, List<String> values, List<String> display, Set<String> value) { // generate some ids int idRoot = context.getUniqueId(); String id = this.getClass().getSimpleName() + "_" + idRoot; String decodeId = "decode_" + idRoot; PrintWriter response = context.getResponseWriter(); // Note: correct / incorrect markings not supported for dropdown // title if (this.titleMessage != null) { response.print("<label class=\"ambrosiaComponentTitle\" for=\"" + id + "\">"); response.print(this.titleMessage.getMessage(context, focus)); response.println("</label>"); } String onchange = ""; if (this.submitDestination != null) { String destination = this.submitDestination.getDestination(context, focus); onchange = " onchange=\"ambrosiaSubmit('" + destination + "');\" "; } else if (this.submitValue) { onchange = " onchange=\"ambrosiaSubmit(this.value);\" "; } response.println( "<select size=\"" + Integer.toString(this.height) + "\" " + (single ? "" : "multiple ") + "name=\"" + id + "\" id=\"" + id + "\"" + (readOnly ? " disabled=\"disabled\"" : "") + onchange + ">"); // TODO: must have selection values // TODO: selectionContainers not supported for (int i = 0; i < values.size(); i++) { String val = values.get(i); String message = ""; if (i < display.size()) { message = display.get(i); } boolean selected = value.contains(val); // the option response.println( "<option " + "value=\"" + val + "\" " + (selected ? "selected=\"selected\"" : "") + ">" + message + "</option>"); } response.println("</select>"); // the decode directive if ((this.propertyReference != null) && (!readOnly)) { response.println( "<input type=\"hidden\" name=\"" + decodeId + "\" value =\"" + id + "\" />" + "<input type=\"hidden\" name=\"" + "prop_" + decodeId + "\" value=\"" + this.propertyReference.getFullReference(context) + "\" />"); } }