James Moger
2015-12-10 63e4d9660de3f4c615a8e9444aaf3c3de128e77c
Merge pull request #982 from gitblit/978-milestone-date-selector

fix for #978 - HTML5 date input support
2 files added
4 files modified
190 ■■■■■ changed files
src/main/java/com/gitblit/wicket/Html5DateField.java 156 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html 4 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/scripts/wicketHtml5Patch.js 13 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/Html5DateField.java
New file
@@ -0,0 +1,156 @@
package com.gitblit.wicket;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import org.apache.wicket.Session;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.form.AbstractTextComponent.ITextFormatProvider;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.convert.converters.DateConverter;
public class Html5DateField extends TextField<Date> implements ITextFormatProvider {
    private static final long serialVersionUID = 1L;
    private static final String DEFAULT_PATTERN = "MM/dd/yyyy";
    private String datePattern = null;
    private IConverter converter = null;
    /**
     * Creates a new Html5DateField, without a specified pattern. This is the same as calling
     * <code>new Html5DateField(id, Date.class)</code>
     *
     * @param id
     *            The id of the date field
     */
    public Html5DateField(String id)
    {
        this(id, null, defaultDatePattern());
    }
    /**
     * Creates a new Html5DateField, without a specified pattern. This is the same as calling
     * <code>new Html5DateField(id, object, Date.class)</code>
     *
     * @param id
     *            The id of the date field
     * @param model
     *            The model
     */
    public Html5DateField(String id, IModel<Date> model)
    {
        this(id, model, defaultDatePattern());
    }
    /**
     * Creates a new Html5DateField bound with a specific <code>SimpleDateFormat</code> pattern.
     *
     * @param id
     *            The id of the date field
     * @param datePattern
     *            A <code>SimpleDateFormat</code> pattern
     *
     */
    public Html5DateField(String id, String datePattern)
    {
        this(id, null, datePattern);
    }
    /**
     * Creates a new DateTextField bound with a specific <code>SimpleDateFormat</code> pattern.
     *
     * @param id
     *            The id of the date field
     * @param model
     *            The model
     * @param datePattern
     *            A <code>SimpleDateFormat</code> pattern
     */
    public Html5DateField(String id, IModel<Date> model, String datePattern)
    {
        super(id, model, Date.class);
        this.datePattern = datePattern;
        converter = new DateConverter()
        {
            private static final long serialVersionUID = 1L;
            /**
             * @see org.apache.wicket.util.convert.converters.DateConverter#getDateFormat(java.util.Locale)
             */
            @Override
            public DateFormat getDateFormat(Locale locale)
            {
                if (locale == null)
                {
                    locale = Locale.getDefault();
                }
                return new SimpleDateFormat(Html5DateField.this.datePattern, locale);
            }
        };
    }
    /**
     * Returns the default converter if created without pattern; otherwise it returns a
     * pattern-specific converter.
     *
     * @param type
     *            The type for which the converter should work
     *
     * @return A pattern-specific converter
     */
    @Override
    public IConverter getConverter(Class<?> type)
    {
        if (converter == null)
        {
            return super.getConverter(type);
        }
        else
        {
            return converter;
        }
    }
    /**
     * Returns the date pattern.
     *
     * @see org.apache.wicket.markup.html.form.AbstractTextComponent.ITextFormatProvider#getTextFormat()
     */
    public String getTextFormat()
    {
        return datePattern;
    }
    /**
     * Try to get datePattern from user session locale. If it is not possible, it will return
     * {@link #DEFAULT_PATTERN}
     *
     * @return date pattern
     */
    private static String defaultDatePattern()
    {
        Locale locale = Session.get().getLocale();
        if (locale != null)
        {
            DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, locale);
            if (format instanceof SimpleDateFormat)
            {
                return ((SimpleDateFormat)format).toPattern();
            }
        }
        return DEFAULT_PATTERN;
    }
    @Override
    protected String getInputType()
    {
        return "date";
    }
}
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.html
@@ -19,7 +19,7 @@
        <!-- Edit Milestone Table -->
        <table class="ticket">
            <tr><th><wicket:message key="gb.milestone"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="name" id="name"></input></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input> &nbsp;<span class="help-inline" wicket:id="dueFormat"></span></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="date" wicket:id="due"></input> &nbsp;<span class="help-inline" wicket:id="dueFormat"></span></td></tr>
            <tr><th><wicket:message key="gb.status"></wicket:message><span style="color:red;">*</span></th><td class="edit"><select class="input-large" wicket:id="status"></select></td></tr>
            <tr><th></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="notify" /> &nbsp;<span class="help-inline"><wicket:message key="gb.notifyChangedOpenTickets"></wicket:message></span></label></td></tr>
        </table>
src/main/java/com/gitblit/wicket/pages/EditMilestonePage.java
@@ -24,7 +24,6 @@
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.markup.html.form.DateTextField;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.CheckBox;
@@ -42,6 +41,7 @@
import com.gitblit.tickets.TicketMilestone;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.Html5DateField;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.BasePanel.JavascriptEventConfirmation;
@@ -106,10 +106,12 @@
        notificationModel = Model.of(true);
        form.add(new TextField<String>("name", nameModel));
        form.add(new DateTextField("due", dueModel, "yyyy-MM-dd"));
        form.add(new Html5DateField("due", dueModel, "yyyy-MM-dd"));
        form.add(new Label("dueFormat", "yyyy-MM-dd"));
        form.add(new CheckBox("notify", notificationModel));
        addBottomScriptInline("{var e=document.createElement('input');e.type='date';if(e.type=='date'){$('[name=\"due\"]~.help-inline').hide()}}");
        addBottomScript("scripts/wicketHtml5Patch.js");
        List<Status> statusChoices = Arrays.asList(Status.Open, Status.Closed);
        form.add(new DropDownChoice<TicketModel.Status>("status", statusModel, statusChoices));
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.html
@@ -5,6 +5,7 @@
      lang="en"> 
<wicket:extend>
<body onload="document.getElementById('name').focus();">
    
<div class="container">
@@ -19,7 +20,7 @@
        <!-- New Milestone Table -->
        <table class="ticket">
            <tr><th><wicket:message key="gb.milestone"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="name" id="name"></input></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="text" wicket:id="due"></input> &nbsp;<span class="help-inline" wicket:id="dueFormat"></span></td></tr>
            <tr><th><wicket:message key="gb.due"></wicket:message></th><td class="edit"><input class="input-large" type="date" wicket:id="due"></input> &nbsp;<span class="help-inline" wicket:id="dueFormat"></span></td></tr>
        </table>
    </div>
    </div>    
@@ -32,6 +33,5 @@
    </form>
</div>
</body>
</wicket:extend>
</html>
src/main/java/com/gitblit/wicket/pages/NewMilestonePage.java
@@ -21,7 +21,6 @@
import org.apache.wicket.RestartResponseException;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.extensions.markup.html.form.DateTextField;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
@@ -35,6 +34,7 @@
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.Html5DateField;
import com.gitblit.wicket.WicketUtils;
/**
@@ -78,9 +78,10 @@
        dueModel = Model.of(new Date(System.currentTimeMillis() + TimeUtils.ONEDAY));
        form.add(new TextField<String>("name", nameModel));
        form.add(new DateTextField("due", dueModel, "yyyy-MM-dd"));
        form.add(new Html5DateField("due", dueModel, "yyyy-MM-dd"));
        form.add(new Label("dueFormat", "yyyy-MM-dd"));
        addBottomScriptInline("{var e=document.createElement('input');e.type='date';if(e.type=='date'){$('[name=\"due\"]~.help-inline').hide()}}");
        addBottomScript("scripts/wicketHtml5Patch.js");
        form.add(new AjaxButton("create") {
            private static final long serialVersionUID = 1L;
src/main/java/com/gitblit/wicket/pages/scripts/wicketHtml5Patch.js
New file
@@ -0,0 +1,13 @@
//This provides a basic patch/hack to allow Wicket 1.4 to support HTML5 input types
Wicket.Form.serializeInput_original = Wicket.Form.serializeInput;
Wicket.Form.serializeInput = function(input)
{
    if (input.type.toLowerCase() == "date")
    {
        return Wicket.Form.encode(input.name) + "=" + Wicket.Form.encode(input.value) + "&";
    }
    return Wicket.Form.serializeInput_original(input);
}