Difference between revisions of "MediaWiki:Form.rythm"

From BITPlan Wiki
Jump to navigation Jump to search
 
(73 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
= Links =
 +
* https://codepen.io/jaycbrf/pen/iBszr
 +
* {{Link|target=MediaWiki:Bootstrap.rythm}}
 +
* https://www.w3schools.com/bootstrap/bootstrap_ref_comp_glyphs.asp
 +
 
= Rythm template source =
 
= Rythm template source =
 
<source lang='java'>
 
<source lang='java'>
 +
@// Rythm template for Bootstrap form handling with validation
 
@import org.simplejavamail.email.Email
 
@import org.simplejavamail.email.Email
 
@import org.simplejavamail.email.EmailBuilder
 
@import org.simplejavamail.email.EmailBuilder
Line 10: Line 16:
 
@// field definitions
 
@// field definitions
 
@def static {
 
@def static {
  // a form with fields
+
// a form with fields
 
   class Form {
 
   class Form {
 +
    boolean debug = false;
 
     Captcha captcha;
 
     Captcha captcha;
 
     boolean de; // true if things are to be displayed in german
 
     boolean de; // true if things are to be displayed in german
     Map<String,Field> fieldMap=new HashMap<String,Field>();
+
     Map<String, Field> fieldMap = new LinkedHashMap<String, Field>();
 
     MultivaluedMap<String, String> formParams;
 
     MultivaluedMap<String, String> formParams;
 +
 
     String title;
 
     String title;
 
     String title_de;
 
     String title_de;
      
+
 
     public Form(boolean de,PostService postService,String postToken,Field[] fields) {
+
    String success;
       this.de=de;
+
    String success_de;
       for (Field field:fields) {
+
 
 +
     String subject = "Contact Form Request";
 +
 
 +
    String submit = "Send";
 +
    String submit_de = "Absenden";
 +
 
 +
    String id = "contact_form";
 +
 
 +
    boolean submitted = false;
 +
 
 +
    /**
 +
    * construct the form
 +
    *
 +
    * @param de
 +
    *          - german?
 +
    * @param postService
 +
    * @param postToken
 +
    * @param fields
 +
    */
 +
     public Form(boolean de, PostService postService, String postToken,
 +
        Field[] fields) {
 +
       this.de = de;
 +
      // get the form parameters from the postService
 +
      this.getFormParams(postService, postToken);
 +
      // add all fields
 +
       for (Field field : fields) {
 
         this.addField(field);
 
         this.addField(field);
 
       }
 
       }
       captcha=new Captcha();
+
       captcha = new Captcha(formParams, de);
       addField(new Field("captcha",captcha.task,captcha.task_de,"question-sign",1));
+
      for (Field field : captcha.getFields()) {
       addField(new HiddenField("expected",""+captcha.expected));
+
        addField(field);
       addField(new HiddenField("postToken",postService.getPostToken()));
+
       }
       fromPost(postService,postToken);
+
 
 +
      if (postService != null) {
 +
        addField(new HiddenField("postToken", postService.getPostToken()));
 +
        fromPost();
 +
      }
 +
    }
 +
 
 +
    // true if the form has never been submitted yet
 +
    public boolean isNew() {
 +
      return !submitted;
 +
    }
 +
 
 +
    // check whether the form is complete
 +
    // and the captcha has been entered
 +
    public String robotCheck() {
 +
      String msg = null;
 +
      if (!submitted)
 +
        return msg;
 +
      Field captchaField = getField("captcha");
 +
      Field expectedField = getField("expected");
 +
       // check that captcha and expected Field are ok.
 +
      if (captchaField != null && expectedField != null) {
 +
        String captchaValue = captchaField.value;
 +
        String expectedValue = expectedField.value;
 +
        boolean ok = captchaValue != null && expectedValue != null
 +
            && !expectedValue.isEmpty() && expectedValue.equals(captchaValue);
 +
        if (!ok) {
 +
          String msg_de = "Bitte geben Sie das richtige Ergebnis für die Aufgabe "
 +
              + captcha.task + " ein.";
 +
          String msg_en = "Please enter the correct result for the task "
 +
              + captcha.task + ".";
 +
          msg = de ? msg_de : msg_en;
 +
        }
 +
      }
 +
      Field robotField = getField("whatami");
 +
       if (robotField != null) {
 +
        String robotValue = robotField.value;
 +
        boolean noRobot = robotValue.equals("Human")
 +
            || robotValue.equals("Mensch");
 +
        if (!noRobot) {
 +
          String msg_de = "Als Roboter geht es hier nicht weiter ...";
 +
          String msg_en = "As a robot there is no progress here ...";
 +
          msg = de ? msg_de : msg_en;
 +
        }
 +
      }
 +
       return msg;
 
     }
 
     }
  
     public String asMail() {  
+
     public String asMail() {
       String mail="";
+
       String mail = "";
       for (Field field:getFields()) {
+
       for (Field field : getFields()) {
         mail+=String.format("%s=%s\n",field.name,field.value);
+
         mail += String.format("%s=%s\n", field.name, field.value);
 
       }
 
       }
 
       return mail;
 
       return mail;
 
     }
 
     }
  
     // constructor
+
     //
     public void fromPost(PostService postService,String postToken) {
+
     public void getFormParams(PostService postService, String postToken) {
       if (postToken!=null) {
+
       if (postToken != null) {
        formParams=postService.getPostData(postToken);
+
        formParams = postService.getPostData(postToken);
        if (formParams!=null) {
+
        if (formParams != null) {
          for (Field field:getFields()) {
+
          submitted = true;
            field.value=formParams.getFirst(field.name);
+
        }
          }
 
        }
 
 
       }
 
       }
 +
    }
 +
 +
    /**
 +
    * get my fields from the post
 +
    */
 +
    public void fromPost() {
 +
      if (submitted) {
 +
        for (Field field : getFields()) {
 +
          field.value = formParams.getFirst(field.name);
 +
        } // for
 +
      } // if
 
     }
 
     }
  
 
     public void setTitle(String title, String title_de) {
 
     public void setTitle(String title, String title_de) {
       this.title=title;
+
       this.title = title;
       this.title_de=title_de;  
+
       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) {
 
     public void setSuccess(String success, String success_de) {
       this.success=success;
+
       this.success = success;
       this.success_de=success_de;  
+
       this.success_de = success_de;
 
     }
 
     }
      
+
 
 +
     public void setSubject(String subject) {
 +
      this.subject = subject;
 +
    }
 +
 
 
     public Collection<Field> getFields() {
 
     public Collection<Field> getFields() {
 
       return fieldMap.values();
 
       return fieldMap.values();
 
     }
 
     }
   
+
 
 
     public void addField(Field field) {
 
     public void addField(Field field) {
       fieldMap.put(field.name,field);
+
       fieldMap.put(field.name, field);
 
     }
 
     }
   
+
 
 
     public Field getField(String fieldName) {
 
     public Field getField(String fieldName) {
       Field field=fieldMap.get(fieldName);
+
       Field field = fieldMap.get(fieldName);
 
       return field;
 
       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 {
 
   class HiddenField extends Field {
     public HiddenField(String name,String value) {
+
     public HiddenField(String name, String value) {
       super(name,name,name,"flash",0),
+
       super(name, name, name, "flash", 0);
       super.hidden=true;
+
       super.hidden = true;
       super.value=value;
+
       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
 
   // a field
 
   class Field {
 
   class Field {
    boolean hidden;
+
    boolean hidden = false;
    String name;
+
    String id;
    String label_en;
+
    String name;
    String label_de;  
+
    String label_en;
    String placeholder_en;
+
    String label_de;
    String placeholder_de;
+
    String labelClass = "";
    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) {
+
    String placeholder_en;
        this.name=name;
+
    String placeholder_de;
        this.label_en=label_en;
+
    String icon;
        this.label_de=label_de;
+
    String value;
        this.placeholder_de=placeholder_de;
+
    int min;
        this.placeholder_en=placeholder_en;
+
 
        this.icon=icon;
+
    public Field(String name, String label_en, String label_de,
        this.min=min;
+
        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) {
+
     public Field(String name, String label_en, String label_de, String icon,
       this(name,label_en,label_de,label_en,label_de,icon,min);
+
        int min) {
 +
       this(name, label_en, label_de, label_en, label_de, icon, min);
 
     }
 
     }
 +
 
   }
 
   }
  
 +
  /**
 +
  * turing test by performing a mathematical task
 +
  */
 
   class Captcha {
 
   class Captcha {
     int expected;
+
     String expected;
 
     String task;
 
     String task;
     String task_de;
+
     List<Field> fields = new ArrayList<Field>();
 +
 
 +
    /**
 +
    * create a captcha
 +
    *
 +
    * @param formParams
 +
    */
 +
    public Captcha(MultivaluedMap<String, String> formParams, boolean de) {
 +
      if (formParams!=null && formParams.containsKey("expected")) {
 +
        expected = formParams.getFirst("expected");
 +
        task = formParams.getFirst("task");
 +
      } else {
 +
        int a1 = (int) (Math.random() * 10 + 1);
 +
        int a2 = (int) (Math.random() * 10 + 1);
 +
        expected = "" + (a1 + a2);
 +
        String task_de = "Was ist " + a1 + "+" + a2 + "?";
 +
        String task_en = "What is " + a1 + "+" + a2 + "?";
 +
        task = de ? task_de : task_en;
 +
      }
 +
      // not quite ok since we have the language preselected
 +
      fields.add(new TextField("captcha", task, task, "question-sign", 1));
 +
      fields.add(new HiddenField("task", task));
 +
      fields.add(new HiddenField("expected", expected));
 +
      SelectField robotField = new SelectField("whatami", "What am i?",
 +
          "Was bin ich?", "Human", "Mensch", "book", 0);
 +
      String[] robots_en = { "Human", "Robot" };
 +
      String[] robots_de = { "Mensch", "Roboter" };
 +
      if (de) {
 +
        robotField.addSelections(robots_de);
 +
      } else {
 +
        robotField.addSelections(robots_en);
 +
      }
 +
      fields.add(robotField);
 +
    }
  
     public void Captcha() {
+
     /**
      int a1=(int)(Math.random() * 10 + 1);
+
    * get the fields that are needed for the Captcha/Robot check
      int a2=(int)(Math.random() * 10 + 1);
+
    *  
      expected=a1+a2;
+
    * @return
      task_de="Was ist "+a1+"+"+a2+"?"
+
    */
       task="What is "+a1+"+"+a2+"?";
+
    public List<Field> getFields() {
 +
       return fields;
 
     }
 
     }
 +
  } // 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
 
@// add a bootstrap field validation
Line 130: Line 352:
 
     @("}"),
 
     @("}"),
 
     notEmpty: @("{")
 
     notEmpty: @("{")
         message: '@(de?"Bitte "+field.label_de+" eingeben":"Please supply your "+field.label_en)'
+
         message: '@(de?"Bitte "+field.label_de+" eingeben":"Please enter "+field.label_en)'
 
       @("}")
 
       @("}")
 
     @("}")
 
     @("}")
Line 136: Line 358:
 
}
 
}
 
@// add a form field
 
@// add a form field
@def field(boolean de,Field field) {
+
@def field(boolean de,Field pField) {
<!-- Text input-->
+
  @if (pField instanceof HiddenField) {
<div class="form-group">
+
    @hiddenField(de,(HiddenField) pField)
  <label class="col-md-4 control-label">@(de?field.label_de:field.label_en)</label>   
+
  }
  <div class="col-md-4 inputGroupContainer">
+
  @if (pField instanceof TextField) {
  <div class="input-group">
+
    @textField(de,(TextField)pField)
  <span class="input-group-addon"><i class="glyphicon glyphicon-@(field.icon)"></i></span>
+
  }
  <input  name="@(field.name)" placeholder="@(de?field.placeholder_de:field.placeholder_en)" class="form-control" value="@(field.value)" type="text">
+
  @if (pField instanceof TextAreaField) {
    </div>
+
    @textAreaField(de,(TextAreaField)pField)
  </div>
+
  }
</div>
+
  @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
 
@// formvalidation
Line 165: Line 435:
 
@{ String delim="";}
 
@{ String delim="";}
 
@for (Field field:form.getFields()) {
 
@for (Field field:form.getFields()) {
 +
@if (!field.hidden) {
 
@(delim)@(fieldvalidate(form.de,field))
 
@(delim)@(fieldvalidate(form.de,field))
 
@{ delim=",";}
 
@{ delim=",";}
 +
}
 
}
 
}
 
     @("}")
 
     @("}")
Line 180: Line 452:
 
   </script>
 
   </script>
 
}
 
}
@// show form
+
@// show form content
@def showform(Form form){
+
@def showFormContent(Form form){
   <form class="well form-horizontal" action=" " method="post"  id="contact_form">
+
   <form class="rounded form-horizontal" action=" " method="post"  id="@(form.id)">
 
       <fieldset>
 
       <fieldset>
 
         <!-- Form Name -->
 
         <!-- Form Name -->
          <legend>@(form.de?form.title_de:form.title)</legend>
+
        <legend>@(form.de?form.title_de:form.title)</legend>
 
@for (Field field:form.getFields()) {
 
@for (Field field:form.getFields()) {
 
@field(form.de,field)
 
@field(form.de,field)
 
}
 
}
<!-- Success message -->
+
        <!-- 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>
+
        <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 -->
+
        <!-- Button -->
<div class="form-group">
+
        <div class="form-group">
  <label class="col-md-4 control-label"></label>
+
          <label class="col-md-4 control-label"></label>
  <div class="col-md-4">
+
          <div class="col-md-4">
    <button type="submit" class="btn btn-warning" >Send <span class="glyphicon glyphicon-send"></span></button>
+
            <button type="submit">@(form.de?form.submit_de:form.submit)<span class="glyphicon glyphicon-send"></span></button>
  </div>
+
          </div>
</div>
+
        </div>
</fieldset>
+
      </fieldset>
</form>
+
    </form>
 +
}
 +
@// show form
 +
@def showform(Form form){
 +
  @if (form.isNew()) {
 +
    @showFormContent(form)
 +
  } else {
 +
    @{
 +
      String msg=form.robotCheck();
 +
    }
 +
    @if (msg==null) {
 +
      @{
 +
        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(form.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)
 +
      @alert("danger","alert",msg)
 +
    }
 +
  }
 
}
 
}
 
</source>
 
</source>
 +
[[Category:RythmTemplate]]

Latest revision as of 14:17, 21 July 2018

Links

Rythm template source

@// 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 id = "contact_form";

    boolean submitted = false;

    /**
     * construct the form
     * 
     * @param de
     *          - german?
     * @param postService
     * @param postToken
     * @param fields
     */
    public Form(boolean de, PostService postService, String postToken,
        Field[] fields) {
      this.de = de;
      // get the form parameters from the postService
      this.getFormParams(postService, postToken);
      // add all fields
      for (Field field : fields) {
        this.addField(field);
      }
      captcha = new Captcha(formParams, de);
      for (Field field : captcha.getFields()) {
        addField(field);
      }

      if (postService != null) {
        addField(new HiddenField("postToken", postService.getPostToken()));
        fromPost();
      }
    }

    // true if the form has never been submitted yet
    public boolean isNew() {
      return !submitted;
    }

    // check whether the form is complete
    // and the captcha has been entered
    public String robotCheck() {
      String msg = null;
      if (!submitted)
        return msg;
      Field captchaField = getField("captcha");
      Field expectedField = getField("expected");
      // check that captcha and expected Field are ok.
      if (captchaField != null && expectedField != null) {
        String captchaValue = captchaField.value;
        String expectedValue = expectedField.value;
        boolean ok = captchaValue != null && expectedValue != null
            && !expectedValue.isEmpty() && expectedValue.equals(captchaValue);
        if (!ok) {
          String msg_de = "Bitte geben Sie das richtige Ergebnis für die Aufgabe "
              + captcha.task + " ein.";
          String msg_en = "Please enter the correct result for the task "
              + captcha.task + ".";
          msg = de ? msg_de : msg_en;
        }
      }
      Field robotField = getField("whatami");
      if (robotField != null) {
        String robotValue = robotField.value;
        boolean noRobot = robotValue.equals("Human")
            || robotValue.equals("Mensch");
        if (!noRobot) {
          String msg_de = "Als Roboter geht es hier nicht weiter ...";
          String msg_en = "As a robot there is no progress here ...";
          msg = de ? msg_de : msg_en;
        }
      }
      return msg;
    }

    public String asMail() {
      String mail = "";
      for (Field field : getFields()) {
        mail += String.format("%s=%s\n", field.name, field.value);
      }
      return mail;
    }

    //
    public void getFormParams(PostService postService, String postToken) {
      if (postToken != null) {
        formParams = postService.getPostData(postToken);
        if (formParams != null) {
          submitted = true;
        }
      }
    }

    /**
     * get my fields from the post
     */
    public void fromPost() {
      if (submitted) {
        for (Field field : getFields()) {
          field.value = formParams.getFirst(field.name);
        } // for
      } // if
    }

    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);
    }

  }

  /**
   * turing test by performing a mathematical task
   */
  class Captcha {
    String expected;
    String task;
    List<Field> fields = new ArrayList<Field>();

    /**
     * create a captcha
     * 
     * @param formParams
     */
    public Captcha(MultivaluedMap<String, String> formParams, boolean de) {
      if (formParams!=null && formParams.containsKey("expected")) {
        expected = formParams.getFirst("expected");
        task = formParams.getFirst("task");
      } else {
        int a1 = (int) (Math.random() * 10 + 1);
        int a2 = (int) (Math.random() * 10 + 1);
        expected = "" + (a1 + a2);
        String task_de = "Was ist " + a1 + "+" + a2 + "?";
        String task_en = "What is " + a1 + "+" + a2 + "?";
        task = de ? task_de : task_en;
      }
      // not quite ok since we have the language preselected
      fields.add(new TextField("captcha", task, task, "question-sign", 1));
      fields.add(new HiddenField("task", task));
      fields.add(new HiddenField("expected", expected));
      SelectField robotField = new SelectField("whatami", "What am i?",
          "Was bin ich?", "Human", "Mensch", "book", 0);
      String[] robots_en = { "Human", "Robot" };
      String[] robots_de = { "Mensch", "Roboter" };
      if (de) {
        robotField.addSelections(robots_de);
      } else {
        robotField.addSelections(robots_en);
      }
      fields.add(robotField);
    }

    /**
     * get the fields that are needed for the Captcha/Robot check
     * 
     * @return
     */
    public List<Field> getFields() {
      return fields;
    }
  } // 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 enter "+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 {
    @{
      String msg=form.robotCheck();
    }
    @if (msg==null) {
      @{ 
        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(form.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)
      @alert("danger","alert",msg)
    }
  } 
}