Java tutorial
/* Copyright 2014 InterCommIT b.v. * * This file is part of the "Weaves" project hosted on https://github.com/intercommit/Weaves * * Weaves is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * Weaves is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Weaves. If not, see <http://www.gnu.org/licenses/>. * */ package nl.intercommit.weaves.components; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Map; import org.apache.commons.lang.ArrayUtils; import org.apache.tapestry5.BindingConstants; import org.apache.tapestry5.ClientElement; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.EventConstants; import org.apache.tapestry5.Link; import org.apache.tapestry5.MarkupWriter; import org.apache.tapestry5.StreamResponse; import org.apache.tapestry5.annotations.Environmental; import org.apache.tapestry5.annotations.Import; import org.apache.tapestry5.annotations.Parameter; import org.apache.tapestry5.annotations.SupportsInformalParameters; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.json.JSONObject; import org.apache.tapestry5.services.Request; import org.apache.tapestry5.services.javascript.JavaScriptSupport; import org.apache.tapestry5.util.TextStreamResponse; /** * A "just in place" select/update component that doesnt have to be enclosed in a form * * Copied from http://js.antinoc.net/?q=node/23 * * @tapestrydoc * */ @SupportsInformalParameters @Import(library = { "classpath:${tapestry.scriptaculous.path}/controls.js", "InPlaceSelectBox.js" }) public class InPlaceSelectBox implements ClientElement { public final static String SAVE_EVENT = "save"; /** * The id used to generate a page-unique client-side identifier for the component. If a * component renders multiple times, a suffix will be appended to the to id to ensure * uniqueness. The uniqued value may be accessed via the * {@link #getClientId() clientId property}. */ @Parameter(value = "prop:componentResources.id", defaultPrefix = BindingConstants.LITERAL) private String clientId; /** * The value to be read and updated. This is not necessarily a string, a translator may be provided to convert * between client side and server side representations. If not bound, a default binding is made to a property of the * container matching the component's id. If no such property exists, then you will see a runtime exception due to * the unbound value parameter. */ @Parameter(required = true, principal = true) private String value; /** * Size of the input text tag. */ @Parameter(value = "20", required = false, defaultPrefix = BindingConstants.LITERAL) private String size; /** * Key, Value map with selectbox contents */ @Parameter(required = true) private Map<Long, String> content; @Parameter(required = false, value = "false") private Boolean blankOption; @Parameter(required = false, value = "message:title") private String emptyMessageKey; /** * The context for the link (optional parameter). This list of values will be converted into strings and included in * the URI. */ @Parameter(required = false) private List<?> context; @Inject private ComponentResources resources; @Inject private Messages messages; @Environmental private JavaScriptSupport jsSupport; @Inject private Request request; private String assignedClientId; private Object[] contextArray; void setupRender() { assignedClientId = jsSupport.allocateClientId(clientId); contextArray = context == null ? new Object[0] : context.toArray(); } void beginRender(MarkupWriter writer) { writer.element("span", "id", getClientId()); if (value != null && value.length() > 0) writer.write(value); else writer.writeRaw(emptyMessageKey); } void afterRender(MarkupWriter writer) { writer.end(); Link link = resources.createEventLink(EventConstants.ACTION, contextArray); jsSupport.addScript("new Ajax.InPlaceEditor('%s', '%s', {cancelControl: 'button', cancelText: '%s', " + "clickToEditText: '%s', savingText: '%s', okText: '%s', htmlResponse: true, size: %s, stripLoadedTextTags: true," + "selectOptions: [%s]});", getClientId(), link.toAbsoluteURI(), messages.get("cancelbutton"), messages.get("title"), messages.get("saving"), messages.get("savebutton"), size, getSelectboxContent()); } private String getSelectboxContent() { final StringBuilder builder = new StringBuilder(); JSONObject entry; if (blankOption) { entry = new JSONObject(); entry.append("name", ""); builder.append(entry.toString() + ","); } for (final Long key : content.keySet()) { entry = new JSONObject(); entry.append("name", content.get(key)); entry.append("value", key); entry.append("selected", (content.get(key).equals(value) ? "true" : "false")); builder.append(entry + ","); } builder.deleteCharAt(builder.length() - 1); return builder.toString().trim(); } StreamResponse onAction(Object[] ctx) throws UnsupportedEncodingException { String valueText = request.getParameter("value"); resources.triggerEvent(SAVE_EVENT, ArrayUtils.add(ctx, valueText), null); if (valueText == null || valueText.length() == 0) { valueText = emptyMessageKey; } else { valueText = content.get(Long.valueOf(valueText)); } return new TextStreamResponse("text/html", new String(valueText.getBytes("UTF8"))); } /** * Returns a unique id for the element. This value will be unique for any given rendering of a page. This value is * intended for use as the id attribute of the client-side element, and will be used with any DHTML/Ajax related * JavaScript. */ public String getClientId() { return assignedClientId; } }