Package com.google.gsoc.web.mixins

Source Code of com.google.gsoc.web.mixins.MixinAutoCompleteObject

// Copyright 2010 The Apache Software Foundation

//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gsoc.web.mixins;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.CSSClassConstants;
import org.apache.tapestry5.ComponentEventCallback;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.ContentType;
import org.apache.tapestry5.EventConstants;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.OptionModel;
import org.apache.tapestry5.RenderSupport;
import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Events;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectContainer;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.MarkupWriterFactory;
import org.apache.tapestry5.services.ResponseRenderer;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.apache.tapestry5.util.TextStreamResponse;

import com.google.gsoc.web.components.AutoCompleteObject;

/**
* A mixin for a AutoCompleteObject that allows for autocompletion of text fields. This is based on Prototype's autocompleter
* control.
* <p/>
* The mixin renders an (initially invisible) progress indicator after the field (it will also be after the error icon
* most fields render). The progress indicator is made visible during the request to the server. The mixin then renders
* a &lt;div&gt; that will be filled in on the client side with dynamically obtained selections.
* <p/>
*
* The container is responsible for providing an event handler for event "providecompletions". The context will be the
* partial input string sent from the client. The return value must be a SelectModel with the possibles options
* <p/>
*
* <pre>
* SelectModel onProvideCompletionsFromMyField(String input)
* {
*   return . . .;
* }
* </pre>
*/

/**
*
* @author Pablo Henrique dos Reis
*
*/
@Import(library = {"${tapestry.scriptaculous}/controls.js", "autocompleteobject.js"})
@Events(EventConstants.PROVIDE_COMPLETIONS)
public class MixinAutoCompleteObject 
{
  static final String PREFIX_COMPONENTE = "autocomplete:";
 
  static final String EVENT_NAME = "autocomplete";

    private static final String PARAM_NAME = "t:input";

    /**
     * The field component to which this mixin is attached.
     */
    @InjectContainer
    private AutoCompleteObject field;
   
    @Inject
    private ComponentResources resources;

    @Inject
    private JavaScriptSupport javaScriptSupport;

    @Inject
    private TypeCoercer coercer;

    @Inject
    private MarkupWriterFactory factory;

    @Inject
    @Path("${tapestry.spacer-image}")
    private Asset spacerImage;

    /**
     * Overwrites the default minimum characters to trigger a server round trip (the default is 1).
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private int minChars;

    @Inject
    private ResponseRenderer responseRenderer;

    /**
     * Overrides the default check frequency for determining whether to send a server request. The default is .4
     * seconds.
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private double frequency;
   
    private SelectModel model;

   
    /**
     * Mixin afterRender phrase occurs after the component itself. This is where we write the &lt;div&gt; element and
     * the JavaScript.
     *
     * @param writer
     */
    void afterRender(MarkupWriter writer)
    {
        String id = field.getClientId();

        String menuId = id + ":menu";
        String loaderId = id + ":loader";

        // The spacer image is used as a placeholder, allowing CSS to determine what image
        // is actually displayed.
        writer.element("img",

                       "src", spacerImage.toClientURL(),

                       "class", "t-autoloader-icon " + CSSClassConstants.INVISIBLE,

                       "alt", "",

                       "id", loaderId);
        writer.end();

        writer.element("div",

                       "id", menuId,

                       "class", "t-autocomplete-menu");
        writer.end();

        Link link = resources.createEventLink(EVENT_NAME);


        JSONObject config = new JSONObject();
        config.put("paramName", PARAM_NAME);
        config.put("indicator", loaderId);

        if (resources.isBound("minChars")) config.put("minChars", minChars);

        if (resources.isBound("frequency")) config.put("frequency", frequency);

        String methodAfterUpdate = "recordFields" + getIdField();
        config.put("updateElement", methodAfterUpdate);
       

        String configString = config.toString();
        configString = configString.toString().replace("\""+methodAfterUpdate + "\"" ,methodAfterUpdate);
       
        // Let subclasses do more.
        configure(config);

         
        javaScriptSupport.addScript(
        "new Ajax.Autocompleter('%s', '%s', '%s', %s);", id, menuId,
        link.toAbsoluteURI(), configString );
       
    }
   
    /**
     * Return the id field with the first character uppercase
     *
     */
    protected String getIdField() {
      String id = field.getClientId();
    String initial = id.substring(0, 1);

    return initial.toUpperCase() + id.substring(1);
    }
   
    /**
     * Invoked to allow subclasses to further configure the parameters passed to the JavaScript Ajax.Autocompleter
     * options. The values minChars and frequency my be pre-configured. Subclasses may override this method to
     * configure additional features of the Ajax.Autocompleter.
     * <p/>
     * <p/>
     * This implementation does nothing.
     *
     * @param config
     *            parameters object
     */
    protected void configure(JSONObject config)
    {
       
    }
   
    Object onAutocomplete(@RequestParameter(PARAM_NAME) String input)
    {

        ComponentEventCallback<SelectModel> callback = new ComponentEventCallback<SelectModel>()
        {
            public boolean handleResult(SelectModel result)
            {
                SelectModel matches = coercer.coerce(result, SelectModel.class);
               
                model = matches;

                return true;
            }
        };

        resources.triggerEvent(EventConstants.PROVIDE_COMPLETIONS, new Object[] { input }, callback);

        ContentType contentType = responseRenderer.findContentType(this);

        MarkupWriter writer = factory.newPartialMarkupWriter(contentType);

        generateResponseMarkup(writer, model);

        return new TextStreamResponse(contentType.toString(), writer.toString());
    }

    /**
     * Generates the markup response that will be returned to the client; this should be an &lt;ul&gt; element with
     * nested &lt;li&gt; elements. Subclasses may override this to produce more involved markup (including images and
     * CSS class attributes).
     *
     * @param writer
     *            to write the list to
     * @param model
     *            to write each option
     */
  protected void generateResponseMarkup(MarkupWriter writer, SelectModel model)
    {

        writer.element("ul");

        if(model != null)
        {
          for (OptionModel o : model.getOptions())
          {
              writer.element("li",
                       "id", toClient(o.getValue()));
              writer.write(o.getLabel());
              writer.end();
          }
        }
       
        writer.end(); // ul
    }
 
  public String toClient(Object object)
  {
    return field.toClient(object);
  }
 
}
TOP

Related Classes of com.google.gsoc.web.mixins.MixinAutoCompleteObject

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.