-
Notifications
You must be signed in to change notification settings - Fork 67
/
HandlebarsButton.java
157 lines (134 loc) · 5.96 KB
/
HandlebarsButton.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.wicketinaction;
import java.util.Map;
import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.attributes.AjaxCallListener;
import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.ajax.json.JsonFunction;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.JavaScriptHeaderItem;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.request.handler.TextRequestHandler;
import org.apache.wicket.request.resource.JavaScriptResourceReference;
import org.apache.wicket.resource.JQueryPluginResourceReference;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.lang.Generics;
import org.apache.wicket.util.template.PackageTextTemplate;
/**
* A button that uses Handlebars JavaScript templating library to
* update HTML element's content
*/
public abstract class HandlebarsButton<T> extends AjaxButton
{
/**
* Uses JQueryPluginResourceReference to specify that it depends on jQuery.
* This way jQuery will be delivered before handlebars.js
*/
private static final JavaScriptResourceReference HANDLEBARS_JS =
new JQueryPluginResourceReference(HandlebarsButton.class, "handlebars-1.0.0.beta.6.js");
/**
* The body of a Wicket.Ajax's #onSuccess() listener that uses the Ajax response
* which is passed with the special argument name 'data'
*/
private final JsonFunction onSuccessFunction;
/**
* Constructor.
*
* @param id the component id
* @param templateId the id of the Handlebars template
* E.g. <script id="THIS_ID" type="text/x-handlebars-template">
* @param targetSelector the css selector to use to find the HTML element that
* should be updated with the populated Handlebars template
*/
public HandlebarsButton(String id, String templateId, String targetSelector)
{
super(id);
Args.notEmpty(templateId, "templateId");
Args.notEmpty(targetSelector, "targetSelector");
PackageTextTemplate blogJs = new PackageTextTemplate(HandlebarsButton.class, "HandlebarsButton.js.tmpl");
Map<String, Object> variables = Generics.newHashMap();
variables.put("templateId", templateId);
variables.put("targetSelector", targetSelector);
this.onSuccessFunction = new JsonFunction(blogJs.asString(variables));
}
@Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes)
{
super.updateAjaxAttributes(attributes);
// let Wicket.Ajax/jQuery know that the result is JSON so it will parse it for you
attributes.setDataType("json");
// tell Wicket.Ajax to not try to process the Ajax response because it is not the normal <ajax-response>
attributes.setWicketAjaxResponse(false);
// register the onSuccess listener that will execute Handlebars logic
AjaxCallListener listener = new AjaxCallListener() {
@Override
public CharSequence getSuccessHandler(Component component)
{
// returns an instance of JsonFunction, so Wicket will render it as is
return onSuccessFunction;
}
};
// the following handlers are not JsonFunction and they will be wrapped in JsonFunction by Wicket and the
// appropriate parameters will be passed.
// For the 'before' handler it looks like: function(attrs, jqXHR, settings){Wicket.Log.info('[Wicket Ajax 6 demo]: executing a before handler');}
listener.onBefore("Wicket.Log.info('[Wicket Ajax 6 demo]: executing a before handler');");
// For the 'complete' handler it looks like: function(attrs, jqXHR, textStatus){Wicket.Log.info('[Wicket Ajax 6 demo]: executing a complete handler');}
listener.onComplete("Wicket.Log.info('[Wicket Ajax 6 demo]: executing a complete handler. Status: ' + textStatus);");
// change the return to 'false' and the Ajax call wont be executed at all.
listener.onPrecondition("return true;");
attributes.getAjaxCallListeners().add(listener);
}
/**
* Serializes the object to its JSON representation that will be used as
* an Ajax response.
* This method that should be implemented by the client of this component.
*
* @param object the object to serialize
* @return the JSON representation of the passed object
*/
protected abstract CharSequence asJson(T object);
/**
* Serializes the form's model object to JSON and delivers it to the browser.
*
* @param target the Ajax request handler. Since we work with JSON we just ignore it.
* @param form the form that contains this button. Keeps the POJO as a model object.
*/
@Override
protected final void onSubmit(AjaxRequestTarget target, Form<?> form)
{
T object = ((Form<T>) form).getModelObject();
String json = asJson(object).toString();
// schedule a request handler that will serve the JSON response
TextRequestHandler jsonHandler = new TextRequestHandler("application/json", "UTF-8", json);
// replace AjaxRequestHandler with the JSON one
getRequestCycle().replaceAllRequestHandlers(jsonHandler);
}
/**
* Contribute Handlebars.js
*
* @param response the response that writes the page headers
*/
@Override
public void renderHead(IHeaderResponse response)
{
super.renderHead(response);
response.render(JavaScriptHeaderItem.forReference(HANDLEBARS_JS));
}
}