@// Rythm template for Bootstrap form handling with validation
@import org.simplejavamail.email.Email
@import org.simplejavamail.email.EmailBuilder
@import org.simplejavamail.mailer.Mailer
@import com.bitplan.mail.SimpleMail
@import javax.ws.rs.core.MultivaluedMap
@import com.bitplan.smw.PropertyMap
@import com.bitplan.wikifrontend.PostService
@// field definitions
@def static {
//a form with fields
class Form {
boolean debug=false;
Captcha captcha;
boolean de; // true if things are to be displayed in german
Map<String,Field> fieldMap=new LinkedHashMap<String,Field>();
MultivaluedMap<String, String> formParams;
String title;
String title_de;
String success;
String success_de;
String subject=""Contact Form Request";
String submit="Send";
String submit_de="Absenden";
String task;
String id="contact_form";
boolean submitted=false;
public Form(boolean de,PostService postService,String postToken,Field[] fields) {
this.de=de;
for (Field field:fields) {
this.addField(field);
}
captcha=new Captcha();
task=de?captcha.task_de:captcha.task;
addField(new TextField("captcha",captcha.task,captcha.task_de,"question-sign",1));
addField(new HiddenField("expected",""+captcha.expected));
if (postService!=null) {
addField(new HiddenField("postToken",postService.getPostToken()));
fromPost(postService,postToken);
}
}
// true if the form has never been submitted yet
public boolean isNew() {
return !submitted;
}
public String getTask() {
return task;
}
public boolean isComplete() {
if (!submitted)
return false;
boolean result=false;
Field captchaField=getField("captcha");
Field expectedField=getField("expected");
if (captchaField!=null && expectedField!=null) {
String captchaValue=captchaField.value;
String expectedValue=expectedField.value;
result=captchaValue!=null && expectedValue!=null && !expectedValue.isEmpty() && expectedValue.equals(captchaValue);
}
return result;
}
public String asMail() {
String mail="";
for (Field field:getFields()) {
mail+=String.format("%s=%s\n",field.name,field.value);
}
return mail;
}
// constructor
public void fromPost(PostService postService,String postToken) {
if (postToken!=null) {
formParams=postService.getPostData(postToken);
if (formParams!=null) {
submitted=true;
for (Field field:getFields()) {
field.value=formParams.getFirst(field.name);
}
}
}
}
public void setTitle(String title, String title_de) {
this.title=title;
this.title_de=title_de;
}
public void setSubmit(String submit, String submit_de) {
this.submit=submit;
this.submit_de=submit_de;
}
public void setSuccess(String success, String success_de) {
this.success=success;
this.success_de=success_de;
}
public void setSubject(String subject) {
this.subject=subject;
}
public Collection<Field> getFields() {
return fieldMap.values();
}
public void addField(Field field) {
fieldMap.put(field.name,field);
}
public Field getField(String fieldName) {
Field field=fieldMap.get(fieldName);
return field;
}
}
class SelectField extends Field {
List<String> selections=new ArrayList<String>();
public void addSelection(String selection) {
selections.add(selection);
}
public void addSelections(String[] pSelections) {
selections.addAll(Arrays.asList(pSelections));
}
public SelectField(String name,String label_en, String label_de, String placeholder_en,String placeholder_de, String icon, int min) {
super(name,label_en,label_de,placeholder_en,placeholder_de,icon,min);
}
public SelectField(String name,String label_en, String label_de, String icon, int min) {
super(name,label_en,label_de,label_en,label_de,icon,min);
}
}
class HiddenField extends Field {
public HiddenField(String name,String value) {
super(name,name,name,"flash",0);
super.hidden=true;
super.value=value;
}
}
class TextAreaField extends Field {
public TextAreaField(String name,String label_en, String label_de, String placeholder_en,String placeholder_de, String icon, int min) {
super(name,label_en,label_de,placeholder_en,placeholder_de,icon,min);
}
public TextAreaField(String name,String label_en, String label_de, String icon, int min) {
super(name,label_en,label_de,label_en,label_de,icon,min);
}
}
class TextField extends Field {
public TextField(String name,String label_en, String label_de, String placeholder_en,String placeholder_de, String icon, int min) {
super(name,label_en,label_de,placeholder_en,placeholder_de,icon,min);
}
public TextField(String name,String label_en, String label_de, String icon, int min) {
super(name,label_en,label_de,label_en,label_de,icon,min);
}
}
// a field
class Field {
boolean hidden=false;
String id;
String name;
String label_en;
String label_de;
String labelClass="";
String placeholder_en;
String placeholder_de;
String icon;
String value;
int min;
public Field(String name,String label_en, String label_de, String placeholder_en,String placeholder_de, String icon, int min) {
this.name=name;
this.id=name;
this.label_en=label_en;
this.label_de=label_de;
this.placeholder_de=placeholder_de;
this.placeholder_en=placeholder_en;
this.icon=icon;
this.min=min;
}
public Field(String name,String label_en, String label_de, String icon, int min) {
this(name,label_en,label_de,label_en,label_de,icon,min);
}
}
class Captcha {
int expected;
String task;
String task_de;
public Captcha() {
int a1=(int)(Math.random() * 10 + 1);
int a2=(int)(Math.random() * 10 + 1);
expected=a1+a2;
task_de="Was ist "+a1+"+"+a2+"?";
task="What is "+a1+"+"+a2+"?";
}
} // Captcha
}
@// optional debugging of form
@def formDebug(Form form) {
@if (form.formParams!=null && form.debug) {
<pre>
@for(String key : form.formParams.keySet()){
@(key)=@(form.formParams.getFirst(key))
}
</pre>
}
}
@//optional feedback
@def feedback(Form form) {
<pre>
@for(String key : form.formParams.keySet()){
@{
Field field=form.getField(key);
}
@if (!field.hidden) {
@(key)=@(form.formParams.getFirst(key))
}
}
</pre>
}
@// display an alert
@def alert(String alertType,String icon, String message) {
<div class="row">
<div class="col-md-12">
<div class="alert alert-@(alertType)"><strong><span class="glyphicon glyphicon-@(icon)"></span> @(message)</strong></div>
</div>
</div>
}
@// add a bootstrap field validation
@def fieldvalidate(boolean de,Field field) {
@(field.name): @("{")
validators: @("{")
stringLength: @("{")
min: @(field.min),
@("}"),
notEmpty: @("{")
message: '@(de?"Bitte "+field.label_de+" eingeben":"Please supply "+field.label_en)'
@("}")
@("}")
@("}")
}
@// add a form field
@def field(boolean de,Field pField) {
@if (pField instanceof HiddenField) {
@hiddenField(de,(HiddenField) pField)
}
@if (pField instanceof TextField) {
@textField(de,(TextField)pField)
}
@if (pField instanceof TextAreaField) {
@textAreaField(de,(TextAreaField)pField)
}
@if (pField instanceof SelectField) {
@selectField(de,(SelectField)pField)
}
}
@// add a hidden form field
@def hiddenField(boolean de,HiddenField field) {
<!-- Hidden input -->
<input type="hidden" name="@(field.name)" id="@(field.id)" value="@(field.value)" >
}
@// add a textarea form field
@def textAreaField(boolean de,TextAreaField field) {
<!-- TextArea input-->
@preField(de,field)
<textarea name="@(field.name)" id="@(field.id)" placeholder="@(de?field.placeholder_de:field.placeholder_en)" class="form-control">@(field.value)</textarea>
@postField(field)
}
@// add a text form field
@def textField(boolean de,TextField field) {
<!-- Text input-->
@preField(de,field)
<input type="text" name="@(field.name)" id="@(field.id)" placeholder="@(de?field.placeholder_de:field.placeholder_en)" class="form-control" value="@(field.value)" >
@postField(field)
}
@// add a select form field
@def selectField(boolean de,SelectField field) {
<!-- Select input-->
@preField(de,field)
<select name="@(field.name)" id="@(field.id)" class="form-control selectpicker" >
<option value=" " >@(de?"Bitte "+field.label_de+" wählen":"Please select "+field.label_en)</option>
@for(String option:field.selections) {
@{ String selected=option.equals(field.value)?"selected":"";}
<option @(selected)>@(option)</option>
}
</select>
@postField(field)
}
@// open a form-group for a field
@def preField(boolean de,Field field) {
<div class="form-group">
<label class="col-md-3 control-label @field.labelClass">@(de?field.label_de:field.label_en)</label>
<div class="col-md-6 inputGroupContainer">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-@(field.icon)"></i></span>
}
@// close a form-group for a field
@def postField(Field field) {
</div>
</div>
</div>
}
@// formvalidation
@def formvalidate(Form form) {
<style>
#success_message{ display: none;}
</style>
<script>
$(document).ready(function() @("{")
$('#contact_form').bootstrapValidator(@("{")
// To use feedback icons, ensure that you use Bootstrap v3.1.0 or later
feedbackIcons: @("{")
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
@("}"),
fields: @("{")
@{ String delim="";}
@for (Field field:form.getFields()) {
@if (!field.hidden) {
@(delim)@(fieldvalidate(form.de,field))
@{ delim=",";}
}
}
@("}")
@("}"))
.on('success.form.bv', function(e) @("{")
$('#success_message').slideDown(@("{") opacity: "show" @("}"), "slow") // Do something ...
$('#contact_form').data('bootstrapValidator').resetForm();
// Prevent form submission
e.preventDefault();
@("}"));
@("}"));
</script>
}
@// show form content
@def showFormContent(Form form){
<form class="rounded form-horizontal" action=" " method="post" id="@(form.id)">
<fieldset>
<!-- Form Name -->
<legend>@(form.de?form.title_de:form.title)</legend>
@for (Field field:form.getFields()) {
@field(form.de,field)
}
<!-- Success message -->
<div class="alert alert-success" role="alert" id="success_message">Success <i class="glyphicon glyphicon-thumbs-up"></i> @(form.de?form.success_de:form.success)</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-4 control-label"></label>
<div class="col-md-4">
<button type="submit">@(form.de?form.submit_de:form.submit)<span class="glyphicon glyphicon-send"></span></button>
</div>
</div>
</fieldset>
</form>
}
@// show form
@def showform(Form form){
@if (form.isNew()) {
@showFormContent(form)
} else if (form.isComplete()) {
@{
String msg=form.de?"Entschuldigen Sie bitte - es ist ein Problem aufgetreten. Bitte nehmen Sie über einen anderen Weg laut Impressum Kontakt mit uns auf!!":"Sorry - there is a problem please contact us via a different channel as per our imprint!";
String alertType="danger";
String icon="alert";
try {
Mailer mailer=SimpleMail.getMailer();
if (mailer!=null) {
Email email=new EmailBuilder()
.from("BITPlan WebMaster","webmaster@bitplan.com")
.to("info@bitplan.com")
.subject(subject)
.text(form.asMail())
.build();
mailer.sendMail(email);
msg=form.de?"Vielen Dank - Ihre Nachricht wurde gesendet":"Thank you - your message was sent";
alertType="success";
icon="send";
}
} catch (Throwable th) {
msg="Exception "+th.getClass().getName()+":"+th.getMessage();
}
}
@alert(alertType,icon,msg)
@feedback(form)
} else {
@showFormContent(form)
@{
String msg_de="Bitte geben Sie das richtige Ergebnis für die Aufgabe "+form.getTask()+" ein";
String msg_en="Please enter the correct result for the task "+form.getTask();
String msg=form.de?msg_de:msg_en;
}
@alert("danger","alert",msg)
}
}