nl.intercommit.weaves.components.InPlaceSelectBox.java Source code

Java tutorial

Introduction

Here is the source code for nl.intercommit.weaves.components.InPlaceSelectBox.java

Source

/*  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;
    }

}