diff --git a/pom.xml b/pom.xml
index b1d1b40..3e70a6c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
de.srsoftware
web4rail
- 1.4.14
+ 1.4.15
Web4Rail
jar
Java Model Railway Control
diff --git a/resources/css/style.css b/resources/css/style.css
index 2d980de..6edbca8 100644
--- a/resources/css/style.css
+++ b/resources/css/style.css
@@ -342,6 +342,10 @@ table tr.disabled:hover td {
background: yellow;
}
+tr.due td{
+ background: orange;
+}
+
table.brake-times tr > *{
border-style: solid;
border-color: black;
diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation
index 618ffba..4293612 100644
--- a/resources/translations/Application.de.translation
+++ b/resources/translations/Application.de.translation
@@ -130,9 +130,11 @@ disable {} : {} deaktivieren
disabled routes : deaktivierte Fahrstraßen
DisableEnableBlock : Block (de)aktivieren
Display "{}" on {}. : „{}“ auf {} anzeigen.
+driven distance : zurückgelegte Strecke
Drop : Verwerfen
Drop brake times : Bremszeiten löschen
Dropped destination of {}. : Ziel von {} verworfen.
+due after : fällig ab
1) Duration between 5 {} steps during brake process. : 1) Zeit zwischen 5 {}-Schritten beim Bremsvorgang.
EAST : Osten
edit : bearbeiten
@@ -147,6 +149,7 @@ enable {} : {} aktivieren
Engage {} : {} aktivieren
EngageDecoupler : Entkuppler aktivieren
Enter new name for plan : Neuen Namen für den Plan eingeben
+executed : ausgeführt
extended address : erweiterte Adresse
export : exportieren
Faster (10 {}) : 10 {} schneller
@@ -156,6 +159,7 @@ Firing {} : starte {}
For each {} do : Mit jedem {}
forward : vorwärts
Found {} routes. : {} Routen gefunden.
+free : frei machen
FreeStartBlock : Start-Block freigeben
Free tiles behind train : Kacheln hinter dem Zug freigeben
Fullscreen : Vollbild
@@ -170,6 +174,7 @@ If car of train\: inspect car number : Falls Fahrzeug aus Zug: Untersuche Fahrze
If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished.
Falls aktiviert, wird die Strecke anhand von Zug- und Kachel-Länge hinter dem Zug freigegeben, Falls deaktiviert wird die Strecke hinter dem Zug erst bei Abschluss der Route freigegeben.
internal contacts : interne Kontakte
+Interval : Intervall
inverted : invertiert
Inverts the direction {} is heading to. : Kehrt die Richtung, in welche {} fährt, um.
{} is not a block! : {} ist kein Block!
@@ -181,6 +186,7 @@ known locomotives : bekannte Lokomotiven
known trains : bekannte Züge
Label for state {} : Beschriftung für Status {}
Last blocks : Letzte Blöcke
+Last execution : letzte Ausführung
last parked train : letzten geparkten Zug
learn : lernen
LEFT : links
@@ -195,6 +201,7 @@ Locomotives : Lokomotiven
Locomotives and cars : Lokomotiven und Waggons
Loop : Wiederholung
Lower speed limit : Minimale Geschwindigkeit
+Maintenance : Wartung
Manage cars : Waggons verwalten
Manage locos : Lokomotiven verwalten
Manage trains : Züge verwalten
@@ -203,6 +210,7 @@ Maximum Speed : Höchstgeschwindigkeit
maximum speed vmax : Höchstgeschwindigkeit vmax
Maximum train length : maximale Zug-Länge
mid speed vmid : mittlere Geschwindigeit vmid
+mileage : Laufleistung
Minimum delay : minimale Verzögerung
Minimum and maximum times (in Miliseconds) trains with the respective tag have to wait in this block. : Minamle und maximale Block-Haltezeit (in Millisekunden) für Züge mit der entsprchender Markierung.
minimum starting voltage vmin : Mindestanfahrspannung vmin
@@ -351,6 +359,8 @@ Switch power on : Strom anschalten
SYSTEM : Betriebssystem
Tag : Markierung
Tags : Markierungen
+Task : Aufgabe
+Task type : Aufgabe
Text to display on clients : Text, welcher auf den Clients angezeigt werden soll
Text to show on display : Text, welcher in der Anzeige dargestellt werden soll
Tile(s) : Kachel(n)
diff --git a/src/main/java/de/srsoftware/web4rail/Application.java b/src/main/java/de/srsoftware/web4rail/Application.java
index 14198e0..27e7364 100644
--- a/src/main/java/de/srsoftware/web4rail/Application.java
+++ b/src/main/java/de/srsoftware/web4rail/Application.java
@@ -127,6 +127,8 @@ public class Application extends BaseClass{
return plan.controlUnit().process(params);
case REALM_LOCO:
return Locomotive.action(params,plan);
+ case REALM_MAINTENANCE:
+ return MaintnanceTask.action(params);
case REALM_PLAN:
return plan.action(params);
case REALM_ROUTE:
diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java
index 9cb8bb7..7d6071c 100644
--- a/src/main/java/de/srsoftware/web4rail/BaseClass.java
+++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java
@@ -2,6 +2,7 @@ package de.srsoftware.web4rail;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
@@ -567,6 +568,11 @@ public abstract class BaseClass implements Constants{
return Translation.get(Application.class, txt, fills);
}
+ public static String time(Date date) {
+ return isSet(date) ? new SimpleDateFormat("YYYY-dd-MM HH:mm").format(date) : null;
+ }
+
+
public static long timestamp() {
return new Date().getTime();
}
diff --git a/src/main/java/de/srsoftware/web4rail/Constants.java b/src/main/java/de/srsoftware/web4rail/Constants.java
index b5fe6bd..6a6ebf0 100644
--- a/src/main/java/de/srsoftware/web4rail/Constants.java
+++ b/src/main/java/de/srsoftware/web4rail/Constants.java
@@ -47,6 +47,7 @@ public interface Constants {
public static final String REALM_CONTACT = "contact";
public static final String REALM_CU = "cu";
public static final String REALM_LOCO = "loco";
+ public static final String REALM_MAINTENANCE = "maintenance";
public static final String REALM_ROUTE = "route";
public static final String REALM_PLAN = "plan";
public static final String REALM_TRAIN = "train";
diff --git a/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java b/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java
new file mode 100644
index 0000000..7fd4ae6
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java
@@ -0,0 +1,150 @@
+package de.srsoftware.web4rail;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.json.JSONObject;
+
+import de.srsoftware.web4rail.moving.Car;
+import de.srsoftware.web4rail.moving.Train;
+import de.srsoftware.web4rail.tags.AddSelect;
+import de.srsoftware.web4rail.tags.Button;
+import de.srsoftware.web4rail.tiles.Block;
+
+public class MaintnanceTask extends BaseClass{
+ private static final HashSet tasks = new HashSet<>();
+
+ private static final String NAME = "name";
+
+ public static final String INTERVAL = "interval";
+
+ private static final String LAST_DATE = "last_date";
+
+ private static final String LAST_DIST = "last_dist";
+
+ private long interval;
+ private long lastExecutionDist;
+ private Date lastExecutionDate;
+ private String name;
+
+ public MaintnanceTask(Car car, String name, long interval) {
+ this.name = name;
+ this.interval = interval;
+ parent(car);
+ register();
+ if (isSet(name)) tasks.add(name);
+ }
+
+ public static Object action(HashMap params) {
+ String action = params.get(ACTION);
+ if (isNull(action)) return t("No action set!");
+
+ MaintnanceTask task = BaseClass.get(Id.from(params));
+
+ switch (action) {
+ case ACTION_ADD:
+ Car car = BaseClass.get(Id.from(params, REALM_CAR));
+ return car.addTask(createTask(params));
+ case ACTION_DROP:
+ if (isSet(task)) {
+ BaseClass parent = task.parent();
+ task.remove();
+ return parent.properties();
+ }
+ return t("No task!");
+ case ACTION_START:
+ return isSet(task) ? task.executed() : t("No task!");
+ }
+ String err = t("unknown action: {}",action);
+ return (isSet(task)) ? task.parent().properties(err) : err;
+ }
+
+ private static MaintnanceTask createTask(HashMap params) {
+ String name = params.get(NAME);
+ long interval = Long.parseLong(params.get(INTERVAL));
+ Car car = BaseClass.get(Id.from(params, REALM_CAR));
+ return new MaintnanceTask(car, name,interval);
+ }
+
+ public Button execBtn() {
+ return button(t("executed"), Map.of(REALM,REALM_MAINTENANCE,ACTION,ACTION_START));
+ }
+
+ private Object executed() {
+ BaseClass parent = parent();
+ if (parent instanceof Car) {
+ Car car = (Car) parent;
+ lastExecutionDate = new Date();
+ lastExecutionDist = car.drivenDistance();
+ Train train = car.train();
+ if (isSet(train)) {
+ Block block = train.currentBlock();
+ if (isSet(block)) plan.place(block);
+ }
+ return car.properties();
+ }
+ return t("parent is not a car!");
+ }
+
+ public long interval() {
+ return interval;
+ }
+
+ public boolean isDue() {
+ return ((Car)parent()).drivenDistance() > lastExecutionDist+interval;
+ }
+
+ @Override
+ public JSONObject json() {
+ JSONObject json = super.json();
+ json.put(NAME, name);
+ json.put(INTERVAL, interval);
+ if (isSet(lastExecutionDate)) {
+ json.put(LAST_DATE, lastExecutionDate.getTime());
+ json.put(LAST_DIST, lastExecutionDist);
+ }
+ return json;
+ }
+
+ public Date lastDate() {
+ return lastExecutionDate;
+ }
+
+ public long lastMileage() {
+ return lastExecutionDist;
+ }
+
+ @Override
+ public MaintnanceTask load(JSONObject json) {
+ json.remove(ID); // we're using the id created by the constructor!
+ super.load(json);
+ name = json.getString(NAME);
+ interval = json.getLong(INTERVAL);
+ if (json.has(LAST_DATE)) lastExecutionDate = new Date(json.getLong(LAST_DATE));
+ if (json.has(LAST_DIST)) lastExecutionDist = json.getLong(LAST_DIST);
+ if (isSet(name)) tasks.add(name);
+ return this;
+ }
+
+ public long nextMileage() {
+ return lastExecutionDist+interval;
+ }
+
+ public Button removeBtn() {
+ return button(t("delete"), Map.of(REALM,REALM_MAINTENANCE,ACTION,ACTION_DROP));
+ }
+
+ public static AddSelect selector() {
+ AddSelect select = new AddSelect(NAME);
+ select.addOption(t("create new task type"));
+ tasks.forEach(task -> select.addOption(task));
+ return select;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java
index 8244396..e787c25 100644
--- a/src/main/java/de/srsoftware/web4rail/Route.java
+++ b/src/main/java/de/srsoftware/web4rail/Route.java
@@ -492,6 +492,10 @@ public class Route extends BaseClass {
return json;
}
+ public long length() {
+ return path.stream().mapToLong(Tile::length).sum();
+ }
+
private Route load(JSONObject json,Plan plan) {
if (json.has(ID)) id = Id.from(json);
if (json.has(NAME)) name(json.getString(NAME));
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Car.java b/src/main/java/de/srsoftware/web4rail/moving/Car.java
index 731f0f4..b1618dc 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Car.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Car.java
@@ -14,12 +14,14 @@ import java.util.TreeSet;
import java.util.Vector;
import java.util.stream.Collectors;
+import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
+import de.srsoftware.web4rail.MaintnanceTask;
import de.srsoftware.web4rail.Plan;
import de.srsoftware.web4rail.tags.Button;
import de.srsoftware.web4rail.tags.Fieldset;
@@ -45,7 +47,12 @@ public class Car extends BaseClass implements Comparable{
private static final String MAX_SPEED_REVERSE = "max_speed_reverse";
private static final String ORDER = "order";
private static final String ORIENTATION = "orientation";
- protected HashSet tags = new HashSet();
+
+ private static final String DRIVEN_DISTANCE = "driven_distance";
+
+ private static final String MAINTENANCE = "maintenance";
+ protected HashSet tags = new HashSet<>();
+ private HashSet tasks = new HashSet<>();
private String name;
public int length;
@@ -54,6 +61,7 @@ public class Car extends BaseClass implements Comparable{
protected int maxSpeedForward = 0;
protected int maxSpeedReverse = 0;
protected boolean orientation = FORWARD;
+ protected long distanceCounter = 0;
public Car(String name) {
this(name,null);
@@ -93,6 +101,11 @@ public class Car extends BaseClass implements Comparable{
return t("Unknown action: {}",params.get(ACTION));
}
+ public Object addTask(MaintnanceTask newTask) {
+ tasks.add(newTask);
+ return properties();
+ }
+
public Car clone() {
Car clone = new Car(name);
clone.maxSpeedForward = maxSpeedForward;
@@ -114,6 +127,14 @@ public class Car extends BaseClass implements Comparable{
public int compareTo(Car o) {
return (stockId+":"+name).compareTo(o.stockId+":"+o.name);
}
+
+ public Object addDistance(long len) {
+ return distanceCounter+= len;
+ }
+
+ public long drivenDistance() {
+ return distanceCounter;
+ }
public JSONObject json() {
JSONObject json = super.json();
@@ -123,7 +144,12 @@ public class Car extends BaseClass implements Comparable{
if (maxSpeedReverse != 0) json.put(MAX_SPEED_REVERSE, maxSpeedReverse);
json.put(ORIENTATION, orientation);
json.put(STOCK_ID, stockId);
+ if (distanceCounter>0) json.put(DRIVEN_DISTANCE, distanceCounter);
if (!tags.isEmpty()) json.put(TAGS, tags);
+ if (!tasks.isEmpty()) {
+ json.put(MAINTENANCE, tasks.stream().map(MaintnanceTask::json).collect(Collectors.toList()));
+ LOG.debug("json: {}",json);
+ }
return json;
}
@@ -166,9 +192,38 @@ public class Car extends BaseClass implements Comparable{
if (json.has(STOCK_ID)) stockId = json.getString(STOCK_ID);
if (json.has(TAGS)) json.getJSONArray(TAGS).forEach(elem -> { tags.add(elem.toString()); });
if (json.has(ORIENTATION)) orientation=json.getBoolean(ORIENTATION);
+ if (json.has(DRIVEN_DISTANCE)) distanceCounter = json.getLong(DRIVEN_DISTANCE);
+ if (json.has(MAINTENANCE)) loadMaintenance(json.getJSONArray(MAINTENANCE));
return this;
}
+ private void loadMaintenance(JSONArray arr) {
+ arr.forEach(o -> {
+ if (o instanceof JSONObject) {
+ tasks.add(new MaintnanceTask(this,null,0).load((JSONObject) o));
+ }
+ });
+ }
+
+ private Fieldset maintenance() {
+ Fieldset fieldset = new Fieldset(t("Maintenance")+(needsMaintenance()?NBSP+"⚠":""));
+ Table table = new Table();
+ table.addHead(t("Task"),t("Last execution"),t("due after"),t("Interval"),t("Actions"));
+ for (MaintnanceTask task : tasks) {
+ Tag row = table.addRow(task,time(task.lastDate())+" / "+task.lastMileage()+NBSP+Plan.lengthUnit,task.nextMileage()+NBSP+Plan.lengthUnit,task.interval()+NBSP+Plan.lengthUnit,task.execBtn()+NBSP+task.removeBtn());
+ if (task.isDue()) row.clazz("due");
+ }
+ table.addTo(fieldset);
+ Form form = new Form("create-task");
+ new Input(REALM,REALM_MAINTENANCE).hideIn(form);
+ new Input(ACTION,ACTION_ADD).hideIn(form);
+ new Input(REALM_CAR,id()).hideIn(form);
+ MaintnanceTask.selector().addTo(new Label(t("Task type")+NBSP)).addTo(form);
+ new Input(MaintnanceTask.INTERVAL,1_000_000).numeric().addTo(new Label(t("Interval")+NBSP)).content(NBSP+Plan.lengthUnit).addTo(form);
+ new Button(t("add"), form).addTo(form);
+ return form.addTo(fieldset);
+ }
+
public static Object manager(Map params) {
Window win = new Window("car-manager", t("Car manager"));
new Tag("h4").content(t("known cars")).addTo(win);
@@ -177,7 +232,7 @@ public class Car extends BaseClass implements Comparable{
String order = params.get(ORDER);
Tag nameLink = link("span", t("Name"), Map.of(REALM,REALM_CAR,ACTION,ACTION_PROPS,ORDER,NAME));
- Table table = new Table().addHead(t("Stock ID"),nameLink,t("Max. Speed",speedUnit),t("Length"),t("Train"),t("Tags"),t("Actions"));
+ Table table = new Table().addHead(t("Stock ID"),nameLink,t("Max. Speed",speedUnit),t("Length"),t("Train"),t("Tags"),t("driven distance"),t("Actions"));
List cars = BaseClass.listElements(Car.class)
.stream()
.filter(car -> !(car instanceof Locomotive))
@@ -210,6 +265,7 @@ public class Car extends BaseClass implements Comparable{
car.length+NBSP+lengthUnit,
isSet(car.train) ? car.train.link("span", car.train) : "",
String.join(", ", car.tags()),
+ car.distanceCounter,
actions
);
}
@@ -238,6 +294,12 @@ public class Car extends BaseClass implements Comparable{
return name;
}
+ boolean needsMaintenance() {
+ for (MaintnanceTask task : tasks) {
+ if (task.isDue()) return true;
+ }
+ return false;
+ }
public boolean orientation() {
return orientation;
}
@@ -252,15 +314,17 @@ public class Car extends BaseClass implements Comparable{
new Input(MAX_SPEED, maxSpeedForward).numeric().addTo(new Tag("p")).content(NBSP+speedUnit+NBSP+t("forward")).addTo(div);
new Input(MAX_SPEED_REVERSE, maxSpeedReverse).numeric().addTo(new Tag("p")).content(NBSP+speedUnit+NBSP+t("backward")).addTo(div);
formInputs.add(t("Maximum Speed"),div);
- if (train != null) formInputs.add(t("Train"), train.link());
+ if (isSet(train)) formInputs.add(t("Train"), train.link());
formInputs.add(t("Current orientation"),new Tag("span").content(orientation ? t("forward") : t("reverse")));
-
+ formInputs.add(t("driven distance"),new Tag("span").content(distanceCounter+" "+Plan.lengthUnit));
+ postForm.add(maintenance());
return super.properties(preForm,formInputs,postForm,errors);
}
-
+
@Override
protected void removeChild(BaseClass child) {
if (child == train) train = null;
+ tasks.remove(child);
super.removeChild(child);
}
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
index 91f5068..16a8b8b 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
@@ -270,14 +270,21 @@ public class Locomotive extends Car implements Constants,Device{
new Tag("p").content(t("Click on a name to edit the entry.")).addTo(win);
- Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Max. Speed",speedUnit),t("Protocol"),t("Address"),t("Length"),t("Tags"));
+ Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Max. Speed",speedUnit),t("Protocol"),t("Address"),t("Length"),t("driven distance"),t("Tags"));
List locos = BaseClass.listElements(Locomotive.class);
locos.sort(Comparator.comparing(loco -> loco.address));
locos.sort(Comparator.comparing(loco -> loco.stockId));
for (Locomotive loco : locos) {
String maxSpeed = (loco.maxSpeedForward == 0 ? "–":""+loco.maxSpeedForward)+NBSP;
if (loco.maxSpeedReverse != loco.maxSpeedForward) maxSpeed += "("+loco.maxSpeedReverse+")"+NBSP;
- table.addRow(loco.stockId,loco.link(),maxSpeed+speedUnit,loco.proto,loco.address,loco.length+NBSP+lengthUnit,String.join(", ", loco.tags()));
+ table.addRow(loco.stockId,
+ loco.link(),
+ maxSpeed+NBSP+speedUnit,
+ loco.proto,
+ loco.address,
+ loco.length+NBSP+lengthUnit,
+ loco.distanceCounter,
+ String.join(", ", loco.tags()));
}
table.addTo(win);
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java
index cd9223c..bbab858 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Train.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java
@@ -229,7 +229,7 @@ public class Train extends BaseClass implements Comparable {
boolean first = true;
for (Car car : cars) {
- Tag link = car.link(car.name()+(car.stockId.isEmpty() ? "" : " ("+car.stockId+")"));
+ Tag link = car.link(car.name()+(car.needsMaintenance()?"⚠":"")+(car.stockId.isEmpty() ? "" : " ("+car.stockId+")"));
Tag buttons = new Tag("span");
car.button(t("turn within train"),Map.of(ACTION,ACTION_TURN)).addTo(buttons);
@@ -390,6 +390,7 @@ public class Train extends BaseClass implements Comparable {
public String directedName() {
String result = name();
+ if (needsMainenance()) result+="⚠";
String mark = autopilot ? "ⓐ" : "";
if (isNull(direction)) return result;
switch (direction) {
@@ -516,6 +517,9 @@ public class Train extends BaseClass implements Comparable {
}
};
}
+
+ long len = endedRoute.length();
+ if (len>0) cars.forEach(car -> car.addDistance(len));
}
private Tag faster(int steps) {
@@ -733,6 +737,13 @@ public class Train extends BaseClass implements Comparable {
return this;
}
+ private boolean needsMainenance() {
+ for (Car car: cars) {
+ if (car.needsMaintenance()) return true;
+ }
+ return false;
+ }
+
public boolean onTrace(Tile t) {
return trace.contains(t);
}
@@ -783,7 +794,7 @@ public class Train extends BaseClass implements Comparable {
formInputs.add(t("Tags"), new Input(TAGS,String.join(", ", tags)));
if (this.hasLoco()) preForm.add(Locomotive.cockpit(this));
- postForm.add(propList.addTo(new Fieldset(t("other train properties")).id("props-other")));
+ postForm.add(propList.addTo(new Fieldset(t("other train properties")+(needsMainenance()?NBSP+"⚠":"")).id("props-other")));
postForm.add(brakeTimes());
postForm.add(blockHistory());
diff --git a/src/main/java/de/srsoftware/web4rail/tags/AddSelect.java b/src/main/java/de/srsoftware/web4rail/tags/AddSelect.java
new file mode 100644
index 0000000..d3b28a8
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/tags/AddSelect.java
@@ -0,0 +1,26 @@
+package de.srsoftware.web4rail.tags;
+
+import de.srsoftware.tools.Tag;
+
+public class AddSelect extends Input {
+ private static final long serialVersionUID = -2168654457876014503L;
+ private Tag dataList;
+
+ public AddSelect(String name) {
+ super("select");
+ attr("name",name);
+ attr("list","list-options");
+ dataList = new Tag("datalist").id("list-options");
+ dataList.addTo(this);
+ }
+
+ public Tag addOption(Object value) {
+ return addOption(value, value);
+ }
+
+ public Tag addOption(Object value, Object text) {
+ Tag option = new Tag("option").attr("value", value.toString()).content(text.toString());
+ option.addTo(dataList);
+ return option;
+ }
+}
\ No newline at end of file