element. */
+ @Property
+ @Parameter(required = true, defaultPrefix = BindingConstants.LITERAL)
+ private String title;
+
+ @Property
+ private String pageName;
+
+ @Property
+ @Parameter(defaultPrefix = BindingConstants.LITERAL)
+ private String sidebarTitle;
+
+ @Property
+ @Parameter(defaultPrefix = BindingConstants.LITERAL)
+ private Block sidebar;
+
+ @Inject
+ private ComponentResources resources;
+
+ public String getClassForPageName()
+ {
+ return resources.getPageName().equalsIgnoreCase(pageName)
+ ? "current_page_item"
+ : null;
+ }
+
+ public String[] getPageNames()
+ {
+ return new String[] { "Index", "About", "Contact" };
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/data/CountryEnum.java b/src/main/java/fr/exanpe/t5/demo/data/CountryEnum.java
new file mode 100644
index 0000000..4cf666c
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/data/CountryEnum.java
@@ -0,0 +1,23 @@
+package fr.exanpe.t5.demo.data;
+
+import java.io.Serializable;
+
+public enum CountryEnum implements Serializable
+{
+ FRANCE(new String[]
+ { "Paris", "Lyon", "Marseille" }), UK(new String[]
+ { "London", "Liverpool", "Manchester" }), USA(new String[]
+ { "New York", "Washington", "Los Angeles", "San Francisco", "Miami" });
+
+ private final String[] cities;
+
+ private CountryEnum(String[] cities)
+ {
+ this.cities = cities;
+ }
+
+ public String[] getCities()
+ {
+ return cities;
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/data/FranceCityEnum.java b/src/main/java/fr/exanpe/t5/demo/data/FranceCityEnum.java
new file mode 100644
index 0000000..c5eb6a1
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/data/FranceCityEnum.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.data;
+
+public enum FranceCityEnum
+{
+ PARIS, LYON, NANTES;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/data/ThirdEnum.java b/src/main/java/fr/exanpe/t5/demo/data/ThirdEnum.java
new file mode 100644
index 0000000..92f61cd
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/data/ThirdEnum.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.data;
+
+public enum ThirdEnum
+{
+ HOUSE, FLAT, CAVE;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/data/UKCityEnum.java b/src/main/java/fr/exanpe/t5/demo/data/UKCityEnum.java
new file mode 100644
index 0000000..da7581a
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/data/UKCityEnum.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.data;
+
+public enum UKCityEnum
+{
+ LONDON, MANCHESTER, LIVERPOOL;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/data/USACityEnum.java b/src/main/java/fr/exanpe/t5/demo/data/USACityEnum.java
new file mode 100644
index 0000000..6c7fff0
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/data/USACityEnum.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.data;
+
+public enum USACityEnum
+{
+ NEW_YORK, WASHINGTON, LOS_ANGELES, SAN_FRANCISCO, MIAMI;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/data/User.java b/src/main/java/fr/exanpe/t5/demo/data/User.java
new file mode 100644
index 0000000..3b2b79c
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/data/User.java
@@ -0,0 +1,31 @@
+package fr.exanpe.t5.demo.data;
+
+import org.apache.tapestry5.beaneditor.NonVisual;
+
+public class User
+{
+ @NonVisual
+ private long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ private int age;
+
+ public long getId() { return id; }
+
+ public void setId(long id) { this.id = id; }
+
+ public String getFirstName() { return firstName; }
+
+ public void setFirstName(String firstName) { this.firstName = firstName; }
+
+ public String getLastName() { return lastName; }
+
+ public void setLastName(String lastName) { this.lastName = lastName; }
+
+ public int getAge() { return age; }
+
+ public void setAge(int age) { this.age = age; }
+}
\ No newline at end of file
diff --git a/src/main/java/fr/exanpe/t5/demo/grouping/Mail.java b/src/main/java/fr/exanpe/t5/demo/grouping/Mail.java
new file mode 100644
index 0000000..b0ed5cf
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/grouping/Mail.java
@@ -0,0 +1,73 @@
+package fr.exanpe.t5.demo.grouping;
+
+import java.io.Serializable;
+import java.util.Date;
+
+public class Mail implements Serializable
+{
+ private int id;
+ private String subject;
+ private String content;
+ private Date date;
+ private String from;
+
+ public Mail(int id, String subject, String content, Date date, String from)
+ {
+ this.id = id;
+ this.subject = subject;
+ this.content = content;
+ this.date = date;
+ this.from = from;
+ }
+
+ public int getId()
+ {
+ return id;
+ }
+
+ public void setId(int id)
+ {
+ this.id = id;
+ }
+
+ public String getSubject()
+ {
+ return subject;
+ }
+
+ public void setSubject(String subject)
+ {
+ this.subject = subject;
+ }
+
+ public String getContent()
+ {
+ return content;
+ }
+
+ public void setContent(String content)
+ {
+ this.content = content;
+ }
+
+ public Date getDate()
+ {
+ return date;
+ }
+
+ public void setDate(Date date)
+ {
+ this.date = date;
+ }
+
+ public String getFrom()
+ {
+ return from;
+ }
+
+ public void setFrom(String from)
+ {
+ this.from = from;
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/grouping/MailboxSumUp.java b/src/main/java/fr/exanpe/t5/demo/grouping/MailboxSumUp.java
new file mode 100644
index 0000000..6261613
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/grouping/MailboxSumUp.java
@@ -0,0 +1,59 @@
+package fr.exanpe.t5.demo.grouping;
+
+public class MailboxSumUp
+{
+ private int total;
+ private int unread;
+ private int sent;
+ private int deleted;
+
+ public MailboxSumUp(int total, int unread, int sent, int deleted)
+ {
+ super();
+ this.total = total;
+ this.unread = unread;
+ this.sent = sent;
+ this.deleted = deleted;
+ }
+
+ public int getTotal()
+ {
+ return total;
+ }
+
+ public void setTotal(int total)
+ {
+ this.total = total;
+ }
+
+ public int getUnread()
+ {
+ return unread;
+ }
+
+ public void setUnread(int unread)
+ {
+ this.unread = unread;
+ }
+
+ public int getSent()
+ {
+ return sent;
+ }
+
+ public void setSent(int sent)
+ {
+ this.sent = sent;
+ }
+
+ public int getDeleted()
+ {
+ return deleted;
+ }
+
+ public void setDeleted(int deleted)
+ {
+ this.deleted = deleted;
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/About.java b/src/main/java/fr/exanpe/t5/demo/pages/About.java
new file mode 100644
index 0000000..e2b01e2
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/About.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages;
+
+public class About
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/Contact.java b/src/main/java/fr/exanpe/t5/demo/pages/Contact.java
new file mode 100644
index 0000000..9bad6a4
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/Contact.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages;
+
+public class Contact
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/Index.java b/src/main/java/fr/exanpe/t5/demo/pages/Index.java
new file mode 100644
index 0000000..55dc7cf
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/Index.java
@@ -0,0 +1,10 @@
+package fr.exanpe.t5.demo.pages;
+
+
+/**
+ * Start page of application exanpe-t5-demo.
+ */
+public class Index
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/Grouping.java b/src/main/java/fr/exanpe/t5/demo/pages/components/Grouping.java
new file mode 100644
index 0000000..0bb7749
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/Grouping.java
@@ -0,0 +1,99 @@
+package fr.exanpe.t5.demo.pages.components;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.tapestry5.EventConstants;
+import org.apache.tapestry5.annotations.Component;
+import org.apache.tapestry5.annotations.OnEvent;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.ioc.annotations.Inject;
+
+import fr.exanpe.t5.demo.grouping.Mail;
+import fr.exanpe.t5.demo.grouping.MailboxSumUp;
+import fr.exanpe.t5.demo.services.MailboxService;
+import fr.exanpe.t5.lib.components.TabView;
+
+public class Grouping
+{
+ @Property
+ private MailboxSumUp sumUp;
+
+ @Property
+ @Persist
+ private List mailsOpen;
+
+ @Property
+ @Persist
+ private List mailsReceived;
+
+ @Property
+ private Mail iteMail;
+
+ @Inject
+ private MailboxService service;
+
+ @Component(id = "tabview")
+ private TabView tabView;
+
+ void onActivate()
+ {
+ sumUp = service.getSumUp();
+ }
+
+ @OnEvent(value = EventConstants.ACTION, component = "received")
+ void initReceivedMails()
+ {
+ mailsReceived = service.getMailsReceived();
+ tabView.setSelectedTab("tabReceived");
+ }
+
+ void onActionFromOpen(int mailId)
+ {
+ if (mailsOpen == null)
+ mailsOpen = new LinkedList();
+
+ for (Mail m : mailsReceived)
+ if (m.getId() == mailId)
+ {
+ mailsOpen.add(m);
+ break;
+ }
+ }
+
+ void onActionFromClose(int mailId)
+ {
+ if (mailsOpen == null)
+ return;
+
+ for (Mail m : mailsReceived)
+ if (m.getId() == mailId)
+ {
+ mailsOpen.remove(m);
+ break;
+ }
+ tabView.setSelectedTab("tabReceived");
+ }
+
+ public String getShortenedSubject()
+ {
+ if (iteMail.getSubject().length() > 20)
+ return iteMail.getSubject().substring(0, 20) + "...";
+ return iteMail.getSubject();
+ }
+
+ public String getShortenedContent()
+ {
+ if (iteMail.getContent().length() > 40)
+ return iteMail.getContent().substring(0, 40) + "...";
+ return iteMail.getContent();
+ }
+
+ public String getShortenedFrom()
+ {
+ if (iteMail.getFrom().length() > 20)
+ return iteMail.getFrom().substring(0, 20) + "...";
+ return iteMail.getFrom();
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example1.java
new file mode 100644
index 0000000..ab23787
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example1.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.accordion;
+
+public class Example1 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example2.java
new file mode 100644
index 0000000..0a390e3
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example2.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.accordion;
+
+public class Example2 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example3.java
new file mode 100644
index 0000000..1c5745f
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example3.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.accordion;
+
+public class Example3 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example4.java b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example4.java
new file mode 100644
index 0000000..c2df07e
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example4.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.accordion;
+
+public class Example4 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example5.java b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example5.java
new file mode 100644
index 0000000..9aee724
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/accordion/Example5.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.accordion;
+
+public class Example5 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example1.java
new file mode 100644
index 0000000..1961d25
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example1.java
@@ -0,0 +1,21 @@
+package fr.exanpe.t5.demo.pages.components.ajaxLoader;
+
+public class Example1
+{
+
+ public String getSleep()
+ {
+ try
+ {
+ Thread.currentThread().sleep(2000);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return "";
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example2.java
new file mode 100644
index 0000000..31f7d93
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example2.java
@@ -0,0 +1,21 @@
+package fr.exanpe.t5.demo.pages.components.ajaxLoader;
+
+public class Example2
+{
+
+ public String getSleep()
+ {
+ try
+ {
+ Thread.currentThread().sleep(2000);
+ }
+ catch (InterruptedException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return "";
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example3.java
new file mode 100644
index 0000000..ffda916
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example3.java
@@ -0,0 +1,19 @@
+package fr.exanpe.t5.demo.pages.components.ajaxLoader;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.tapestry5.annotations.Property;
+
+public class Example3
+{
+
+ @Property
+ private String date;
+
+ public void onActivate()
+ {
+ date = new SimpleDateFormat("MM-dd-yyyy HH:mm:ss").format(new Date());
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/border/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/border/Example1.java
new file mode 100644
index 0000000..ff1aa57
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/border/Example1.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.border;
+
+public class Example1 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/colorPicker/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/colorPicker/Example1.java
new file mode 100644
index 0000000..a8a0196
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/colorPicker/Example1.java
@@ -0,0 +1,13 @@
+package fr.exanpe.t5.demo.pages.components.colorPicker;
+
+import java.awt.Color;
+
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example1
+{
+ @Property
+ @Persist
+ private Color color;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example1.java
new file mode 100644
index 0000000..e24255c
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example1.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.dialog;
+
+public class Example1 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example2.java
new file mode 100644
index 0000000..b77ad33
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example2.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.dialog;
+
+public class Example2 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example3.java
new file mode 100644
index 0000000..4a6fe58
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example3.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.dialog;
+
+public class Example3 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example4.java b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example4.java
new file mode 100644
index 0000000..dfba3fe
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/dialog/Example4.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.dialog;
+
+public class Example4 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/exanpeSkin/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/exanpeSkin/Example1.java
new file mode 100644
index 0000000..50e7d4f
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/exanpeSkin/Example1.java
@@ -0,0 +1,68 @@
+package fr.exanpe.t5.demo.pages.components.exanpeSkin;
+
+import java.util.List;
+
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.Import;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.SetupRender;
+import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.util.EnumSelectModel;
+import org.apache.tapestry5.util.EnumValueEncoder;
+
+import fr.exanpe.t5.demo.data.User;
+import fr.exanpe.t5.demo.services.DataService;
+
+@Import(stylesheet = "${exanpe.asset-base}/css/exanpe-t5-lib-skin.css")
+public class Example1
+{
+ @Inject
+ private DataService dataService;
+
+ @Inject
+ private Messages messages;
+
+ /** GRID **/
+ @Property
+ private List users;
+
+ @Property
+ private User iteUser;
+
+ /** Auto Complete **/
+ @Property
+ private String country;
+
+ public List onProvideCompletionsFromCountryName(String partial)
+ {
+ return dataService.getListOfString();
+ }
+
+ /** Palette **/
+
+ @Property
+ private final ValueEncoder encoder = new EnumValueEncoder(PaletteEnum.class);
+
+ @Property
+ private final SelectModel model = new EnumSelectModel(PaletteEnum.class, messages);
+
+ @Property
+ private List selected;
+
+ public enum PaletteEnum
+ {
+ TEST, TEST2, TEST3, TEST4;
+ }
+
+ /** BeanEditor */
+ @Property
+ private User userEdit;
+
+ @SetupRender
+ public void init()
+ {
+ users = dataService.getListUsers();
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/hideablePanel/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/hideablePanel/Example1.java
new file mode 100644
index 0000000..307f2b1
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/hideablePanel/Example1.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.hideablePanel;
+
+public class Example1 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/hideablePanel/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/hideablePanel/Example2.java
new file mode 100644
index 0000000..fd77ac5
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/hideablePanel/Example2.java
@@ -0,0 +1,5 @@
+package fr.exanpe.t5.demo.pages.components.hideablePanel;
+
+public class Example2 {
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example1.java
new file mode 100644
index 0000000..d770a6d
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example1.java
@@ -0,0 +1,21 @@
+package fr.exanpe.t5.demo.pages.components.securePassword;
+
+import org.apache.tapestry5.PersistenceConstants;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example1
+{
+ @Property
+ private String passwordValue;
+
+ @Persist(PersistenceConstants.FLASH)
+ @Property
+ private String val;
+
+ void onSubmit()
+ {
+ val = passwordValue;
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example2.java
new file mode 100644
index 0000000..5347ace
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example2.java
@@ -0,0 +1,21 @@
+package fr.exanpe.t5.demo.pages.components.securePassword;
+
+import org.apache.tapestry5.PersistenceConstants;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example2
+{
+ @Property
+ private String passwordValue;
+
+ @Persist(PersistenceConstants.FLASH)
+ @Property
+ private String val;
+
+ void onSubmit()
+ {
+ val = passwordValue;
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example3.java
new file mode 100644
index 0000000..7407000
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/securePassword/Example3.java
@@ -0,0 +1,17 @@
+package fr.exanpe.t5.demo.pages.components.securePassword;
+
+import org.apache.tapestry5.PersistenceConstants;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example3
+{
+ @Persist(PersistenceConstants.FLASH)
+ @Property
+ private String passwordValue;
+
+ void onSubmit()
+ {
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/selectLoader/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/selectLoader/Example1.java
new file mode 100644
index 0000000..afe6795
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/selectLoader/Example1.java
@@ -0,0 +1,85 @@
+package fr.exanpe.t5.demo.pages.components.selectLoader;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.tapestry5.OptionModel;
+import org.apache.tapestry5.PersistenceConstants;
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.OnEvent;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.SetupRender;
+import org.apache.tapestry5.internal.OptionModelImpl;
+import org.apache.tapestry5.internal.SelectModelImpl;
+import org.apache.tapestry5.internal.services.EnumValueEncoderFactory;
+import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.util.EnumSelectModel;
+
+import fr.exanpe.t5.demo.data.CountryEnum;
+import fr.exanpe.t5.demo.services.DataService;
+import fr.exanpe.t5.lib.constants.ExanpeEventConstants;
+
+public class Example1
+{
+ @Inject
+ private DataService dataService;
+
+ @Inject
+ private Messages messages;
+
+ @Property
+ private ValueEncoder countryEncoder = new EnumValueEncoderFactory().create(CountryEnum.class);
+
+ @Property
+ private SelectModel country;
+
+ @Property
+ @Persist(PersistenceConstants.FLASH)
+ private CountryEnum countryValue;
+
+ @Property
+ private SelectModel city;
+
+ @Property
+ @Persist(PersistenceConstants.FLASH)
+ private String cityValue;
+
+ @SetupRender
+ public void ini()
+ {
+ country = new EnumSelectModel(CountryEnum.class, messages);
+ loadCountrySelect();
+ }
+
+ public void onSubmit()
+ {
+ loadCountrySelect();
+ }
+
+ private void loadCountrySelect()
+ {
+ if (countryValue == null)
+ city = new SelectModelImpl(new OptionModelImpl[0]);
+ else
+ city = populateSelect(countryValue.toString());
+ }
+
+ @OnEvent(value = ExanpeEventConstants.SELECTLOADER_EVENT)
+ public SelectModel populateSelect(String value)
+ {
+ if (StringUtils.isEmpty(value))
+ return null;
+
+ String[] cities = dataService.getCitiesFromCountry(CountryEnum.valueOf(value));
+
+ OptionModel[] om = new OptionModel[cities.length];
+
+ for (int i = 0; i < cities.length; i++)
+ om[i] = new OptionModelImpl(cities[i]);
+
+ city = new SelectModelImpl(om);
+
+ return city;
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/selectLoader/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/selectLoader/Example2.java
new file mode 100644
index 0000000..9bb79fd
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/selectLoader/Example2.java
@@ -0,0 +1,147 @@
+package fr.exanpe.t5.demo.pages.components.selectLoader;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.tapestry5.OptionModel;
+import org.apache.tapestry5.PersistenceConstants;
+import org.apache.tapestry5.SelectModel;
+import org.apache.tapestry5.ValueEncoder;
+import org.apache.tapestry5.annotations.OnEvent;
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.annotations.SetupRender;
+import org.apache.tapestry5.internal.OptionModelImpl;
+import org.apache.tapestry5.internal.SelectModelImpl;
+import org.apache.tapestry5.internal.services.EnumValueEncoderFactory;
+import org.apache.tapestry5.ioc.Messages;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.util.EnumSelectModel;
+
+import fr.exanpe.t5.demo.data.CountryEnum;
+import fr.exanpe.t5.demo.data.ThirdEnum;
+import fr.exanpe.t5.demo.services.DataService;
+import fr.exanpe.t5.lib.constants.ExanpeEventConstants;
+
+public class Example2
+{
+ @Inject
+ private DataService dataService;
+
+ @Inject
+ private Messages messages;
+
+ @Property
+ private ValueEncoder countryEncoder = new EnumValueEncoderFactory().create(CountryEnum.class);
+
+ @Property
+ private SelectModel country;
+
+ @Property
+ private SelectModel city;
+
+ @Property
+ private SelectModel type;
+
+ @Property
+ @Persist(PersistenceConstants.FLASH)
+ private CountryEnum countryValue;
+
+ @Property
+ @Persist(PersistenceConstants.FLASH)
+ private String cityValue;
+
+ @Property
+ @Persist(PersistenceConstants.FLASH)
+ private String typeValue;
+
+ @SetupRender
+ public void ini()
+ {
+ country = new EnumSelectModel(CountryEnum.class, messages);
+ loadCitySelect();
+ loadTypeSelect();
+
+ }
+
+ private void loadCitySelect()
+ {
+ if (countryValue == null)
+ city = new SelectModelImpl(new OptionModelImpl[0]);
+ else
+ {
+ List opts = createCityOpt(countryValue.toString());
+ OptionModel[] om = new OptionModel[opts.size()];
+ city = new SelectModelImpl((OptionModel[]) opts.toArray(om));
+ }
+ }
+
+ private void loadTypeSelect()
+ {
+ if (cityValue == null)
+ type = new SelectModelImpl(new OptionModelImpl[0]);
+ else
+ {
+ List opts = createTypeOpt(cityValue.toString());
+ OptionModel[] om = new OptionModel[opts.size()];
+ type = new SelectModelImpl((OptionModel[]) opts.toArray(om));
+ }
+ }
+
+ public void onSubmit()
+ {
+
+ }
+
+ private List createCityOpt(String value)
+ {
+ if (StringUtils.isEmpty(value))
+ return null;
+
+ List opts = new ArrayList();
+
+ String[] cities = dataService.getCitiesFromCountry(CountryEnum.valueOf(value));
+
+ for (int i = 0; i < cities.length; i++)
+ opts.add(new OptionModelImpl(cities[i]));
+
+ return opts;
+ }
+
+ private List createTypeOpt(String value)
+ {
+ if (StringUtils.isEmpty(value))
+ return null;
+
+ ThirdEnum[] te = ThirdEnum.values();
+
+ List opts = new ArrayList(3);
+
+ for (int i = 0; i < te.length; i++)
+ opts.add(new OptionModelImpl(te[i].toString()));
+
+ return opts;
+ }
+
+ @OnEvent(value = ExanpeEventConstants.SELECTLOADER_EVENT, component = "country")
+ public SelectModel populateSelectCity(String value)
+ {
+ List opts = createCityOpt(value);
+ opts.add(0, new OptionModelImpl(" ", " "));
+
+ OptionModel[] om = new OptionModel[opts.size()];
+
+ return new SelectModelImpl((OptionModel[]) opts.toArray(om));
+ }
+
+ @OnEvent(value = ExanpeEventConstants.SELECTLOADER_EVENT, component = "city")
+ public SelectModel populateSelectType(String value)
+ {
+ List opts = createTypeOpt(value);
+
+ OptionModel[] om = new OptionModel[opts.size()];
+
+ return new SelectModelImpl((OptionModel[]) opts.toArray(om));
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example1.java
new file mode 100644
index 0000000..ee6576f
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example1.java
@@ -0,0 +1,11 @@
+package fr.exanpe.t5.demo.pages.components.slider;
+
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example1
+{
+ @Property
+ @Persist
+ private int sliderValue;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example2.java
new file mode 100644
index 0000000..e628ac4
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example2.java
@@ -0,0 +1,11 @@
+package fr.exanpe.t5.demo.pages.components.slider;
+
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example2
+{
+ @Property
+ @Persist
+ private float sliderValue;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example3.java
new file mode 100644
index 0000000..cf74a86
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example3.java
@@ -0,0 +1,11 @@
+package fr.exanpe.t5.demo.pages.components.slider;
+
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example3
+{
+ @Property
+ @Persist
+ private int sliderValue;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example4.java b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example4.java
new file mode 100644
index 0000000..b176bfa
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/slider/Example4.java
@@ -0,0 +1,11 @@
+package fr.exanpe.t5.demo.pages.components.slider;
+
+import org.apache.tapestry5.annotations.Persist;
+import org.apache.tapestry5.annotations.Property;
+
+public class Example4
+{
+ @Property
+ @Persist
+ private int sliderValue;
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example1.java
new file mode 100644
index 0000000..deb6e99
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example1.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages.components.tabview;
+
+public class Example1
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example2.java
new file mode 100644
index 0000000..5538f4e
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example2.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages.components.tabview;
+
+public class Example2
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example3.java
new file mode 100644
index 0000000..814bb78
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example3.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages.components.tabview;
+
+public class Example3
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example4.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example4.java
new file mode 100644
index 0000000..fccb891
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tabview/Example4.java
@@ -0,0 +1,20 @@
+package fr.exanpe.t5.demo.pages.components.tabview;
+
+import org.apache.tapestry5.annotations.Component;
+import org.apache.tapestry5.annotations.Property;
+
+import fr.exanpe.t5.lib.components.TabView;
+
+public class Example4
+{
+ @Component(id = "tabv")
+ private TabView tabView;
+
+ @Property
+ private String defaultTab = "tab2";
+
+ public void onActionFromSetThird()
+ {
+ tabView.setSelectedTab("tab3");
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example1.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example1.java
new file mode 100644
index 0000000..e75459d
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example1.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages.components.tooltip;
+
+public class Example1
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example2.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example2.java
new file mode 100644
index 0000000..6598224
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example2.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages.components.tooltip;
+
+public class Example2
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example3.java b/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example3.java
new file mode 100644
index 0000000..b8c55a9
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/pages/components/tooltip/Example3.java
@@ -0,0 +1,6 @@
+package fr.exanpe.t5.demo.pages.components.tooltip;
+
+public class Example3
+{
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/services/AppModule.java b/src/main/java/fr/exanpe/t5/demo/services/AppModule.java
new file mode 100644
index 0000000..b43e0f9
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/services/AppModule.java
@@ -0,0 +1,148 @@
+package fr.exanpe.t5.demo.services;
+
+import java.io.IOException;
+
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.ioc.Configuration;
+import org.apache.tapestry5.ioc.MappedConfiguration;
+import org.apache.tapestry5.ioc.OrderedConfiguration;
+import org.apache.tapestry5.ioc.ServiceBinder;
+import org.apache.tapestry5.ioc.annotations.Local;
+import org.apache.tapestry5.ioc.annotations.SubModule;
+import org.apache.tapestry5.ioc.services.Coercion;
+import org.apache.tapestry5.ioc.services.CoercionTuple;
+import org.apache.tapestry5.services.Request;
+import org.apache.tapestry5.services.RequestFilter;
+import org.apache.tapestry5.services.RequestHandler;
+import org.apache.tapestry5.services.Response;
+import org.apache.tapestry5.util.StringToEnumCoercion;
+import org.slf4j.Logger;
+
+import fr.exanpe.t5.demo.data.CountryEnum;
+import fr.exanpe.t5.demo.data.FranceCityEnum;
+import fr.exanpe.t5.demo.data.ThirdEnum;
+import fr.exanpe.t5.lib.services.ExanpeLibraryModule;
+
+/**
+ * This module is automatically included as part of the Tapestry IoC Registry, it's a good place to
+ * configure and extend Tapestry, or to place your own service definitions.
+ */
+@SubModule(ExanpeLibraryModule.class)
+public class AppModule
+{
+ public static void bind(ServiceBinder binder)
+ {
+ // binder.bind(MyServiceInterface.class, MyServiceImpl.class);
+
+ // Make bind() calls on the binder object to define most IoC services.
+ // Use service builder methods (example below) when the implementation
+ // is provided inline, or requires more initialization than simply
+ // invoking the constructor.
+ binder.bind(DataService.class, DataService.class);
+ binder.bind(MailboxService.class, MailboxService.class);
+ }
+
+ public static void contributeApplicationDefaults(MappedConfiguration configuration)
+ {
+ // Contributions to ApplicationDefaults will override any contributions to
+ // FactoryDefaults (with the same key). Here we're restricting the supported
+ // locales to just "en" (English). As you add localised message catalogs and other assets,
+ // you can extend this list of locales (it's a comma separated series of locale names;
+ // the first locale name is the default when there's no reasonable match).
+
+ configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en");
+
+ // The factory default is true but during the early stages of an application
+ // overriding to false is a good idea. In addition, this is often overridden
+ // on the command line as -Dtapestry.production-mode=false
+ configuration.add(SymbolConstants.PRODUCTION_MODE, "true");
+
+ // The application version number is incorprated into URLs for some
+ // assets. Web browsers will cache assets because of the far future expires
+ // header. If existing assets are changed, the version number should also
+ // change, to force the browser to download new versions.
+ configuration.add(SymbolConstants.APPLICATION_VERSION, "1.0.0-SNAPSHOT");
+ }
+
+ /**
+ * This is a service definition, the service will be named "TimingFilter". The interface,
+ * RequestFilter, is used within the RequestHandler service pipeline, which is built from the
+ * RequestHandler service configuration. Tapestry IoC is responsible for passing in an
+ * appropriate Logger instance. Requests for static resources are handled at a higher level, so
+ * this filter will only be invoked for Tapestry related requests.
+ *
+ * Service builder methods are useful when the implementation is inline as an inner class (as
+ * here) or require some other kind of special initialization. In most cases, use the static
+ * bind() method instead.
+ *
+ * If this method was named "build", then the service id would be taken from the service
+ * interface and would be "RequestFilter". Since Tapestry already defines a service named
+ * "RequestFilter" we use an explicit service id that we can reference inside the contribution
+ * method.
+ */
+ public RequestFilter buildTimingFilter(final Logger log)
+ {
+ return new RequestFilter()
+ {
+ public boolean service(Request request, Response response, RequestHandler handler) throws IOException
+ {
+ long startTime = System.currentTimeMillis();
+
+ try
+ {
+ // The responsibility of a filter is to invoke the corresponding method
+ // in the handler. When you chain multiple filters together, each filter
+ // received a handler that is a bridge to the next filter.
+
+ return handler.service(request, response);
+ }
+ finally
+ {
+ long elapsed = System.currentTimeMillis() - startTime;
+
+ log.info(String.format("Request time: %d ms", elapsed));
+ }
+ }
+ };
+ }
+
+ /**
+ * This is a contribution to the RequestHandler service configuration. This is how we extend
+ * Tapestry using the timing filter. A common use for this kind of filter is transaction
+ * management or security. The @Local annotation selects the desired service by type, but only
+ * from the same module. Without @Local, there would be an error due to the other service(s)
+ * that implement RequestFilter (defined in other modules).
+ */
+ public void contributeRequestHandler(OrderedConfiguration configuration, @Local
+ RequestFilter filter)
+ {
+ // Each contribution to an ordered configuration has a name, When necessary, you may
+ // set constraints to precisely control the invocation order of the contributed filter
+ // within the pipeline.
+
+ configuration.add("Timing", filter);
+ }
+
+ public static void contributeTypeCoercer(@SuppressWarnings("rawtypes")
+ Configuration configuration)
+ {
+ configuration.add(CoercionTuple.create(String.class, CountryEnum.class, StringToEnumCoercion.create(CountryEnum.class)));
+ configuration.add(CoercionTuple.create(String.class, FranceCityEnum.class, StringToEnumCoercion.create(FranceCityEnum.class)));
+ configuration.add(CoercionTuple.create(String.class, ThirdEnum.class, StringToEnumCoercion.create(ThirdEnum.class)));
+ // configuration.add(CoercionTuple.create(String.class, CountryEnum.class,
+ // StringToEnumCoercion.create(CountryEnum.class)));
+ // configuration.add(CoercionTuple.create(String.class, CountryEnum.class,
+ // StringToEnumCoercion.create(CountryEnum.class)));
+
+ Coercion countryEnum = new Coercion()
+ {
+ public String coerce(CountryEnum input)
+ {
+ return input.toString();
+ }
+ };
+
+ configuration.add(new CoercionTuple(CountryEnum.class, String.class, countryEnum));
+ }
+
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/services/DataService.java b/src/main/java/fr/exanpe/t5/demo/services/DataService.java
new file mode 100644
index 0000000..b5acb07
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/services/DataService.java
@@ -0,0 +1,46 @@
+package fr.exanpe.t5.demo.services;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import fr.exanpe.t5.demo.data.CountryEnum;
+import fr.exanpe.t5.demo.data.User;
+
+public class DataService
+{
+
+ private User createUser(int id, String name, String firstName, int age)
+ {
+ User u = new User();
+ u.setId(id);
+ u.setLastName(name);
+ u.setFirstName(firstName);
+ u.setAge(age);
+ return u;
+ }
+
+ public List getListUsers()
+ {
+ List users = new ArrayList();
+
+ for (int i = 0; i < 50; i++)
+ users.add(createUser(i, "Name " + i, "First Name " + i, 20 + i));
+
+ return users;
+ }
+
+ public List getListOfString()
+ {
+ List list = new ArrayList();
+
+ for (int i = 0; i < 30; i++)
+ list.add("Hello World " + i);
+
+ return list;
+ }
+
+ public String[] getCitiesFromCountry(CountryEnum e)
+ {
+ return e.getCities();
+ }
+}
diff --git a/src/main/java/fr/exanpe/t5/demo/services/MailboxService.java b/src/main/java/fr/exanpe/t5/demo/services/MailboxService.java
new file mode 100644
index 0000000..5a256fb
--- /dev/null
+++ b/src/main/java/fr/exanpe/t5/demo/services/MailboxService.java
@@ -0,0 +1,30 @@
+package fr.exanpe.t5.demo.services;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import fr.exanpe.t5.demo.grouping.Mail;
+import fr.exanpe.t5.demo.grouping.MailboxSumUp;
+
+public class MailboxService
+{
+ private static final int NB_MAIL_RECEIVED = 32;
+
+ public MailboxSumUp getSumUp()
+ {
+ return new MailboxSumUp(NB_MAIL_RECEIVED, 4, 12, 120);
+ }
+
+ public List getMailsReceived()
+ {
+ List list = new ArrayList(NB_MAIL_RECEIVED);
+
+ for (int i = 1; i < NB_MAIL_RECEIVED + 1; i++)
+ list.add(new Mail(i, "Subject " + i,
+ "Hey what's up ! \n This representents a mail content. No real interest writing a new one everytime ! Just to notice this is the mail number "
+ + i, new Date(), "sender" + i + "@mail.com"));
+
+ return list;
+ }
+}
diff --git a/src/main/resources/fr/exanpe/t5/demo/components/ComponentDemoLayout.tml b/src/main/resources/fr/exanpe/t5/demo/components/ComponentDemoLayout.tml
new file mode 100644
index 0000000..e154fbf
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/components/ComponentDemoLayout.tml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/Grouping.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/Grouping.properties
new file mode 100644
index 0000000..4dc3cf5
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/Grouping.properties
@@ -0,0 +1,22 @@
+cat-title=Webmail
+
+mail-title=Mailbox
+calendar-title=Calendar
+calendar-content=Not implemented
+tasks-title=Tasks
+tasks-content=Not implemented
+
+receivedLink=Received
+sentLink=Sent
+deletedLink=Deleted
+
+tabpres-title=Presentation
+tabpres-icon=context:/img/grouping/information.png
+
+tabReceived-title=Received
+tabReceived-icon=context:/img/grouping/emails.png
+
+showInTab-label=Show in new tab
+
+not-implemented=This action is not implemented
+not-implemented-title=Sorry !
\ No newline at end of file
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/accordion/Example2.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/accordion/Example2.properties
new file mode 100644
index 0000000..7cd8e09
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/accordion/Example2.properties
@@ -0,0 +1,6 @@
+item1-title=Title of item 1
+item2-title=Title of item 2
+
+item1-content=Content of item 1
+item2-content=Content of item 2
+
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example2.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example2.properties
new file mode 100644
index 0000000..9f05d0b
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/ajaxLoader/Example2.properties
@@ -0,0 +1 @@
+please-wait=Please wait...
\ No newline at end of file
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/dialog/Example3.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/dialog/Example3.properties
new file mode 100644
index 0000000..965a895
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/dialog/Example3.properties
@@ -0,0 +1,2 @@
+dialogtitle=Information
+dialogmessage=This link is currently not active
\ No newline at end of file
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/dialog/Example4.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/dialog/Example4.properties
new file mode 100644
index 0000000..95ad247
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/dialog/Example4.properties
@@ -0,0 +1,2 @@
+link1-title=Information
+link1-message=This link is currently not active
\ No newline at end of file
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/tabview/Example3.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/tabview/Example3.properties
new file mode 100644
index 0000000..14e86e4
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/tabview/Example3.properties
@@ -0,0 +1,5 @@
+tab1-title=Title of tab 1
+tab1-icon=context:/img/tab/application.png
+
+tab2-title=Title of tab 2
+tab2-icon=context:/img/tab/comments.png
\ No newline at end of file
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/tooltip/Example1.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/tooltip/Example1.properties
new file mode 100644
index 0000000..4f98108
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/tooltip/Example1.properties
@@ -0,0 +1 @@
+tooltip-message-example=Do you see me ?
\ No newline at end of file
diff --git a/src/main/resources/fr/exanpe/t5/demo/pages/components/tooltip/Example2.properties b/src/main/resources/fr/exanpe/t5/demo/pages/components/tooltip/Example2.properties
new file mode 100644
index 0000000..193ee93
--- /dev/null
+++ b/src/main/resources/fr/exanpe/t5/demo/pages/components/tooltip/Example2.properties
@@ -0,0 +1 @@
+tooltip-tooltip=This is the tooltip content
\ No newline at end of file
diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties
new file mode 100644
index 0000000..6e42abd
--- /dev/null
+++ b/src/main/resources/log4j.properties
@@ -0,0 +1,45 @@
+# Default to info level output; this is very handy if you eventually use Hibernate as well.
+log4j.rootCategory=info, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+
+# A1 uses PatternLayout.
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=[%p] %c{2} %m%n
+
+# Service category names are the name of the defining module class
+# and then the service id.
+log4j.category.fr.exanpe.t5.demo.services.AppModule.TimingFilter=info
+
+# Outputs a list of pages, components and mixins at startup.
+log4j.category.org.apache.tapestry5.services.TapestryModule.ComponentClassResolver=info
+
+# Outputs startup statistics; elapsed time to setup and initialize the registry, and a list of
+# available services.
+log4j.category.org.apache.tapestry5.TapestryFilter=info
+#log4j.category.fr.exanpe.t5.lib=debug
+
+
+# Turning on debug mode for a page's or component's transformer logger
+# will show all of the code changes that occur when the
+# class is loaded.
+
+# log4j.category.tapestry.transformer.fr.exanpe.t5.demo.pages.Index=debug
+
+# Turning on debug mode for a component's events logger will show all the events triggered on the
+# component, and which component methods are invoked as a result.
+
+# log4j.category.tapestry.events.fr.exanpe.t5.demo.pages.Index=debug
+
+# Turning on trace mode for a page's render logger provides extended information about every step
+# in rendering (this is not generally helpful). Turning on debug mode will add a one-line
+# summary that includes the elapsed render time, which can be useful in tracking down
+# performance issues.
+
+# log4j.category.tapestry.render.fr.exanpe.t5.demo.pages.Index=debug
+
+# Turn on some verbose debugging about everything in the application. This is nice initially,
+# while getting everything set up. You'll probably want to remove this once you are
+# up and running, replacing it with more selective debugging output.
+log4j.category.fr.exanpe.t5.demo=debug
\ No newline at end of file
diff --git a/src/main/webapp/About.tml b/src/main/webapp/About.tml
new file mode 100644
index 0000000..cdf4434
--- /dev/null
+++ b/src/main/webapp/About.tml
@@ -0,0 +1,7 @@
+
+
+
+ Welcome to the Exanpe T5 lib Demo !
+ This application have been created to show the components in action and help you get on with them by displaying some samples of code for every component's use case.
+ Here are the components in action:
+
+
+
+ Have a look to our showcase page grouping many components
+
+
+ See our Tapestry core components skinned by Exanpe
+
+
+
+
+
+
+
Accordion
+
+
Standard Accordion
+
Accordion built from resources file
+
Accordion event on mouseover
+
Accordion with a single item open allowed
+
Accordion and JavaScript interaction
+
+
+
AjaxLoader
+
+
Basic AjaxLoader
+
AjaxLoader with text customized
+
AjaxLoader loaded on demand, without panel
+
+
+
Border
+
+
A simple Border
+
+
+
ColorPicker
+
+
The Color Picker component in action
+
+
+
Dialog
+
+
A Dialog presentation displaying an information
+
A Dialog displaying a confirmation
+
A Dialog with title and message customized
+
A Dialog with title and message consolidated through injected id
+
+
+
Hideable Panel
+
+
A basic Hideable Panel
+
A Hideable Panel with some customing and JavaScript interaction
+
+
+
+
+
+
Secure Password
+
+
A basic Secure Password
+
A Secure Password with some hover recording and maxlength customised
+
Secure Password with character set and grid size redefined
+
+
+
SelectLoader
+
+
SelectLoader mixin demonstration
+
Chain 3 selects
+
+
+
Slider
+
+
Basic Slider example
+
Slider with selection customized : min, max, and gap value
+
Slider displaying the real time value in a custom html element
+
Slider vertically oriented
+
+
+
TabView
+
+
A basic TabView
+
A "client side" TabView
+
Load the tabs attributes (text + icon) from a resources file
+
A tabView with full control over the selected tab
+
+
+
Tooltip
+
+
A basic Tooltip
+
Tooltip built from resources file
+
Tooltip displaying a rich content defined in the page
+
+
+
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/app.properties b/src/main/webapp/WEB-INF/app.properties
new file mode 100644
index 0000000..1c29931
--- /dev/null
+++ b/src/main/webapp/WEB-INF/app.properties
@@ -0,0 +1,4 @@
+# This is where global application properties go.
+# You can also have individual message catalogs for each page and each
+# component that override these defaults.
+# The name of this file is based on the element in web.
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/appengine-web.xml b/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 0000000..7864cd6
--- /dev/null
+++ b/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,7 @@
+
+
+ exanpe-t5-lib
+
+ 1-0-0-snapshot
+ true
+
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..f1dfb4f
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,22 @@
+
+
+
+ exanpe-t5-demo Tapestry 5 Application
+
+
+ tapestry.app-package
+ fr.exanpe.t5.demo
+
+
+ app
+ org.apache.tapestry5.TapestryFilter
+
+
+ app
+ /*
+
+
+
diff --git a/src/main/webapp/components/Grouping.tml b/src/main/webapp/components/Grouping.tml
new file mode 100644
index 0000000..d77e801
--- /dev/null
+++ b/src/main/webapp/components/Grouping.tml
@@ -0,0 +1,101 @@
+
+
+
+
+ This page displays a webmail including the Exanpe components.
+
+
+
+
+
+
+
+
+ ${message:receivedLink}
+
+
+
+ ${message:sentLink}
+
+
+
+
+ ${message:deletedLink}
+
+
+
+
+
+
+
+
+
+
+
+ This page presents many components of Exanpe library and Tapestry core grouped together to render a "real" view.
+ Here is a case that demonstrate the Exanpe library :
+
+
On the left site, an Accordion groups some actions.
+
The layout is built over a HideablePanel, allowing the right zone to be increased.
+
The right side is structured over a TabView
+
On the left site, hover Received. A Tooltip appears.
+
Click Received.
+
A skinned Tapestry Grid appears on the right side, into a new Tab.
+
For a mail :
+
+
If you click Open Mail, the mail will open in a new Tab.
+
If you click Delete Mail, a Dialog component appear, informing that we did not implement that functionality.
+
+
+
+
+
+
+
+
+
+
+
+ ${shortenedSubject }
+
+
+ ${shortenedContent }
+
+
+ ${shortenedFrom }
+
+
+ Open mail
+
+
+ Delete mail
+
+
+
+
+
+
+
+
+
+ ${iteMail.content}
+
+ Close mail
+
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/accordion/Example1.tml b/src/main/webapp/components/accordion/Example1.tml
new file mode 100644
index 0000000..8095096
--- /dev/null
+++ b/src/main/webapp/components/accordion/Example1.tml
@@ -0,0 +1,19 @@
+
+
+
+ This page shows a standard accordion, with a title and the first item opened.
+
+
+
+
+
+
+ Content coded in body
+
+
+
+
+
diff --git a/src/main/webapp/components/accordion/Example2.tml b/src/main/webapp/components/accordion/Example2.tml
new file mode 100644
index 0000000..030f094
--- /dev/null
+++ b/src/main/webapp/components/accordion/Example2.tml
@@ -0,0 +1,30 @@
+
+
+
+ This page shows an accordion built entirely from data located in a resources file.
+ Mainly useful for short contents.
+
+
+
+
+
+
+
+
+
+
+ These keys are defined in the property file of the current page :
+
+
+ item1-title=Title of item 1
+ item2-title=Title of item 2
+
+ item1-content=Content of item 1
+ item2-content=Content of item 2
+
+
+
+
diff --git a/src/main/webapp/components/accordion/Example3.tml b/src/main/webapp/components/accordion/Example3.tml
new file mode 100644
index 0000000..bb97793
--- /dev/null
+++ b/src/main/webapp/components/accordion/Example3.tml
@@ -0,0 +1,21 @@
+
+
+
+ This page shows an accordion expanded when title are hovered. No click required.
+
+
+
+
+
+ Content coded in body
+
+
+ Content 2 coded in body
+
+
+
+
+
diff --git a/src/main/webapp/components/accordion/Example4.tml b/src/main/webapp/components/accordion/Example4.tml
new file mode 100644
index 0000000..62815fd
--- /dev/null
+++ b/src/main/webapp/components/accordion/Example4.tml
@@ -0,0 +1,21 @@
+
+
+
+ This page shows an accordion allowing a single content to be opened at once.
+
+
+
+
+
+ Content coded in body
+
+
+ Content 2 coded in body
+
+
+
+
+
diff --git a/src/main/webapp/components/accordion/Example5.tml b/src/main/webapp/components/accordion/Example5.tml
new file mode 100644
index 0000000..09f16c0
--- /dev/null
+++ b/src/main/webapp/components/accordion/Example5.tml
@@ -0,0 +1,27 @@
+
+
+
+ This page shows the way to interact with the accordion with JavaScript.
+ It also boots the duration of the accordion animation
+
+
+
+
+
+ Content coded in body
+
+
+ Content 2 coded in body
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/ajaxLoader/Example1.tml b/src/main/webapp/components/ajaxLoader/Example1.tml
new file mode 100644
index 0000000..f2fabc7
--- /dev/null
+++ b/src/main/webapp/components/ajaxLoader/Example1.tml
@@ -0,0 +1,18 @@
+
+
+
+ This page shows a standard AjaxLoader, with content loaded on page load.
+
+
+
+
+ This text is loaded on demand.
+ A sleep timer has been set server side on getSleep() method to see the Ajax loading.
+ ${sleep}
+
+
+
+
diff --git a/src/main/webapp/components/ajaxLoader/Example2.tml b/src/main/webapp/components/ajaxLoader/Example2.tml
new file mode 100644
index 0000000..a514cc5
--- /dev/null
+++ b/src/main/webapp/components/ajaxLoader/Example2.tml
@@ -0,0 +1,25 @@
+
+
+
+ This page shows an AjaxLoader with loading text customized from resources file.
+ Notice the property key please-wait added to the current page resource file.
+
+
+
+
+ This text is loaded on demand.
+ A sleep timer has been set server side on getSleep() method to see the Ajax loading.
+ ${sleep}
+
+
+
+
+
+ item1-title=Title of item 1
+
+
+
+
diff --git a/src/main/webapp/components/ajaxLoader/Example3.tml b/src/main/webapp/components/ajaxLoader/Example3.tml
new file mode 100644
index 0000000..8eafcac
--- /dev/null
+++ b/src/main/webapp/components/ajaxLoader/Example3.tml
@@ -0,0 +1,31 @@
+
+
+
+ This page shows an AjaxLoader loaded on demand, and disabling the loading panel.
+ Notice the attribute autoLoad set to false, as the showPanel one.
+ Also, a button allow the content reloading on demand.
+
+
+
+
+ This text is loaded on demand.
+ No time server side.
+ Curent Datetime : ${date}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/border/Example1.tml b/src/main/webapp/components/border/Example1.tml
new file mode 100644
index 0000000..5863d92
--- /dev/null
+++ b/src/main/webapp/components/border/Example1.tml
@@ -0,0 +1,17 @@
+
+
+
+ This page displays a simple border.
+ Nothing special provided by the component.
+
+
+
+
+ This text is wrapped inside a border.
+
+
+
+
diff --git a/src/main/webapp/components/colorPicker/Example1.tml b/src/main/webapp/components/colorPicker/Example1.tml
new file mode 100644
index 0000000..0f50ef9
--- /dev/null
+++ b/src/main/webapp/components/colorPicker/Example1.tml
@@ -0,0 +1,29 @@
+
+
+
+ This page displays a color picker.
+ It is bound to a value into the page.
+ A coercer have been implemented between String and java.awt.Color.
+ It has to be enclosed inside a form.
+
+
+
+
+
+
+
+
+
+ Color submitted : ${color}
+
+
+
+
+
diff --git a/src/main/webapp/components/dialog/Example1.tml b/src/main/webapp/components/dialog/Example1.tml
new file mode 100644
index 0000000..dee2c8e
--- /dev/null
+++ b/src/main/webapp/components/dialog/Example1.tml
@@ -0,0 +1,18 @@
+
+
+
+ This page displays a simple dialog component.
+ This components acts like a proxy to confirm a user action or display information.
+ The dialog gets bound into an other components through a t:mixins="exanpe/dialog" attribute.
+ Notice the t:renderMode and t:message attribute, coming along with the mixin.
+
+
+
+ Go to index
+
+
+
diff --git a/src/main/webapp/components/dialog/Example2.tml b/src/main/webapp/components/dialog/Example2.tml
new file mode 100644
index 0000000..c0dd5bf
--- /dev/null
+++ b/src/main/webapp/components/dialog/Example2.tml
@@ -0,0 +1,17 @@
+
+
+
+ This page displays a dialog component with a confirmation required.
+ Activation takes place on Ok click.
+ Notice the t:renderMode to confirm.
+
+
+
+ Go to index
+
+
+
diff --git a/src/main/webapp/components/dialog/Example3.tml b/src/main/webapp/components/dialog/Example3.tml
new file mode 100644
index 0000000..34939e4
--- /dev/null
+++ b/src/main/webapp/components/dialog/Example3.tml
@@ -0,0 +1,24 @@
+
+
+
+ This page displays a dialog component with its title and message customized.
+ Keys have been declared into this page's resources file.
+
+
+
+ Go to index
+
+
+
+ These keys are defined in the property file of the current page :
+
+ dialogtitle=Information
+ dialogmessage=This link is currently not active
+
+
+
+
diff --git a/src/main/webapp/components/dialog/Example4.tml b/src/main/webapp/components/dialog/Example4.tml
new file mode 100644
index 0000000..422f5bd
--- /dev/null
+++ b/src/main/webapp/components/dialog/Example4.tml
@@ -0,0 +1,25 @@
+
+
+
+ This page displays a dialog component with its title and message customized.
+ Keys have been declared into this page's resources file and automatically get from the injected component's id.
+ Notice the t:id="link1" attribute.
+
+
+
+ Go to index
+
+
+
+ These keys are defined in the property file of the current page :
+
+ link1-title=Information
+ link1-message=This link is currently not active
+
+
+
+
diff --git a/src/main/webapp/components/exanpeSkin/Example1.tml b/src/main/webapp/components/exanpeSkin/Example1.tml
new file mode 100644
index 0000000..9834149
--- /dev/null
+++ b/src/main/webapp/components/exanpeSkin/Example1.tml
@@ -0,0 +1,59 @@
+
+
+
+
+
+ This page displays the core Tapestry components skinned with the Exanpe graphic style.
+ These components are not working properly. Just here to show their look.
+ So easy to set up :
+
+
Add a HTML tag with class="exanpe-skin" anywhere around the component to skin
+
Import our CSS stylesheet in the Page you want to reskin : @Import(stylesheet = "$ {exanpe.asset-base}/css/exanpe-t5-lib-skin.css")
+
No conflict ! Skin only what you want to skin
+
+
+
+
+
+ ...
+
+
+
+
+ Grid :
+
+
+
+
+
+
+ Autocomplete :
+
+ Type in a country name:
+
+
+
+
+ Palette :
+
+
+
+
+
+ Bean Editform :
+
+
+
+
diff --git a/src/main/webapp/components/hideablePanel/Example1.tml b/src/main/webapp/components/hideablePanel/Example1.tml
new file mode 100644
index 0000000..c3f14aa
--- /dev/null
+++ b/src/main/webapp/components/hideablePanel/Example1.tml
@@ -0,0 +1,32 @@
+
+
+
+ This page displays a basic HideablePanel.
+ The width of the left side hideable panel is required.
+
+
+
+
+
+
+ This
+ content
+ is
+ hideable
+
+
+
+ This
+ content
+ is
+ always
+ visible
+
+
+
+
+
+
diff --git a/src/main/webapp/components/hideablePanel/Example2.tml b/src/main/webapp/components/hideablePanel/Example2.tml
new file mode 100644
index 0000000..466dfca
--- /dev/null
+++ b/src/main/webapp/components/hideablePanel/Example2.tml
@@ -0,0 +1,34 @@
+
+
+
+ This page displays a HideablePanel customized.
+ Here are defined the duration of the animation and allow some JavaScript interaction.
+
+
+
+
+
+
+ This
+ content
+ is
+ hideable
+
+
+
+ This
+ content
+ is
+ always
+ visible
+
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/securePassword/Example1.tml b/src/main/webapp/components/securePassword/Example1.tml
new file mode 100644
index 0000000..6d56800
--- /dev/null
+++ b/src/main/webapp/components/securePassword/Example1.tml
@@ -0,0 +1,35 @@
+
+
+
+ This page displays a basic SecurePassword.
+ Click a number to record it.
+ It is bound to a Page variable to submit the value (parameter value).
+ It has to be enclosed inside a t:form component.
+
+
+
+
+
+ Value sent : ${prop:val}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/securePassword/Example2.tml b/src/main/webapp/components/securePassword/Example2.tml
new file mode 100644
index 0000000..19b018d
--- /dev/null
+++ b/src/main/webapp/components/securePassword/Example2.tml
@@ -0,0 +1,20 @@
+
+
+
+ This page displays a SecurePassword triggered on hover, with eventType attribute.
+ Hover a number to record it.
+ The maxlength has been reduced on force a maximum of 6 characters to be entered.
+
+
+
+
+
+ Value sent : ${prop:val}
+
+
+
+
+
diff --git a/src/main/webapp/components/securePassword/Example3.tml b/src/main/webapp/components/securePassword/Example3.tml
new file mode 100644
index 0000000..8c3e02b
--- /dev/null
+++ b/src/main/webapp/components/securePassword/Example3.tml
@@ -0,0 +1,30 @@
+
+
+
+ This page displays a SecurePassword with a custom character set to select.
+ Its size has been adapted.
+ Note that when submitting, the value entered stay recorded in the component.
+
+
+
+
+
+ Value sent : ${prop:passwordValue}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/selectLoader/Example1.tml b/src/main/webapp/components/selectLoader/Example1.tml
new file mode 100644
index 0000000..8c93836
--- /dev/null
+++ b/src/main/webapp/components/selectLoader/Example1.tml
@@ -0,0 +1,74 @@
+
+
+
+ This page displays the SelectLoader mixin.
+ Notice the t:mixins associated to the t:targetId attribute.
+
+
+
+
+
+
+
+
+
+
+ Submitted country : ${countryValue }
+ Submitted city : ${cityValue }
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/selectLoader/Example2.tml b/src/main/webapp/components/selectLoader/Example2.tml
new file mode 100644
index 0000000..b6ea19a
--- /dev/null
+++ b/src/main/webapp/components/selectLoader/Example2.tml
@@ -0,0 +1,33 @@
+
+
+
+ This page displays the SelectLoader mixin, chaining 3 selects.
+
+
+
+
+
+
+
+
+
+
+
+
+ Submitted country : ${countryValue }
+ Submitted city : ${cityValue }
+ Submitted type : ${typeValue }
+
+
+
+
+
diff --git a/src/main/webapp/components/slider/Example1.tml b/src/main/webapp/components/slider/Example1.tml
new file mode 100644
index 0000000..43649a6
--- /dev/null
+++ b/src/main/webapp/components/slider/Example1.tml
@@ -0,0 +1,29 @@
+
+
+
+ This example shows a basic Slider component.
+ This component has to be enclosed inside a form.
+ It is bound to a page @Property sliderValue
+
+
+
+
+
+
+
+
+ Submitted value : ${sliderValue}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/slider/Example2.tml b/src/main/webapp/components/slider/Example2.tml
new file mode 100644
index 0000000..90f58ef
--- /dev/null
+++ b/src/main/webapp/components/slider/Example2.tml
@@ -0,0 +1,29 @@
+
+
+
+ This example shows a Slider component with imposed values to choose, chosen from an interval.
+ The min and max values have been specified.
+ Notice the interval, min and max attributes.
+
+
+
+
+
+
+
+
+ Submitted value : ${sliderValue}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/slider/Example3.tml b/src/main/webapp/components/slider/Example3.tml
new file mode 100644
index 0000000..5cfe8a8
--- /dev/null
+++ b/src/main/webapp/components/slider/Example3.tml
@@ -0,0 +1,29 @@
+
+
+
+ This example shows a Slider component that displays its value in a custom element.
+ Notice here the displayId attribute.
+
+
+
+ You are about to select the value , just press submit.
+
+
+
+
+
+ Submitted value : ${sliderValue}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/slider/Example4.tml b/src/main/webapp/components/slider/Example4.tml
new file mode 100644
index 0000000..8035512
--- /dev/null
+++ b/src/main/webapp/components/slider/Example4.tml
@@ -0,0 +1,28 @@
+
+
+
+ This example shows a vertical oriented Slider.
+ Every horizontal customization can be applied to a vertical slider.
+
+
+
+
+
+
+
+
+ Submitted value : ${sliderValue}
+
+
+
+
+
+
+
diff --git a/src/main/webapp/components/tabview/Example1.tml b/src/main/webapp/components/tabview/Example1.tml
new file mode 100644
index 0000000..d5c38a7
--- /dev/null
+++ b/src/main/webapp/components/tabview/Example1.tml
@@ -0,0 +1,30 @@
+
+
+
+ This page displays a basic Tab View.
+ This TabView is said as "server side", meaning all the tabs content are not loaded on page load.
+ It does keep its state on page refresh.
+
+
+
+
+
+ This is my tab 1 1 1
+ content 1
+
+
+ This is my tab 2 2 2
+ content 2
+
+
+ This is my tab 3 3 3
+ content 3
+
+
+
+
+
+
diff --git a/src/main/webapp/components/tabview/Example2.tml b/src/main/webapp/components/tabview/Example2.tml
new file mode 100644
index 0000000..0dd971c
--- /dev/null
+++ b/src/main/webapp/components/tabview/Example2.tml
@@ -0,0 +1,31 @@
+
+
+
+ This page displays a basic Tab View.
+ This TabView is said as "client side", meaning all the tabs are loaded on page load.
+ Notice the loadAll attribute.
+ It does NOT keep its state on page refresh.
+
+
+
+
+
+ This is my tab 1 1 1
+ content 1
+
+
+ This is my tab 2 2 2
+ content 2
+
+
+ This is my tab 3 3 3
+ content 3
+
+
+
+
+
+
diff --git a/src/main/webapp/components/tabview/Example3.tml b/src/main/webapp/components/tabview/Example3.tml
new file mode 100644
index 0000000..78cfdb9
--- /dev/null
+++ b/src/main/webapp/components/tabview/Example3.tml
@@ -0,0 +1,36 @@
+
+
+
+ This page displays Tab View with data loaded from resources file.
+ Note that only tab 1 and 2 load from resources file, whereas tab3 is declared inline (not recommended in a real application code =))
+
+
+
+
+
+ This is my tab 1 1 1
+ content 1
+
+
+ This is my tab 2 2 2
+ content 2
+
+
+ This is my tab 3 3 3
+ content 3
+
+
+
+
+
+ tab1-title=Title of tab 1
+ tab1-icon=context:/img/tab/application.png
+
+ tab2-title=Title of tab 2
+ tab2-icon=context:/img/tab/comments.png
+
+
+
diff --git a/src/main/webapp/components/tabview/Example4.tml b/src/main/webapp/components/tabview/Example4.tml
new file mode 100644
index 0000000..1b0547f
--- /dev/null
+++ b/src/main/webapp/components/tabview/Example4.tml
@@ -0,0 +1,44 @@
+
+
+
+ This page displays a Tab View controlled server side.
+ The default one is specified on server (second tab), and a click on the link Activate Third set the third tab active.
+
+
+
+
+
+ This is my tab 1 1 1
+ content 1
+
+
+ This is my tab 2 2 2
+ content 2
+
+
+ This is my tab 3 3 3
+ content 3
+
+
+
+ Activate third
+
+
+
+
+
+
diff --git a/src/main/webapp/components/tooltip/Example1.tml b/src/main/webapp/components/tooltip/Example1.tml
new file mode 100644
index 0000000..3649ce5
--- /dev/null
+++ b/src/main/webapp/components/tooltip/Example1.tml
@@ -0,0 +1,30 @@
+
+
+
+ This page displays a basic Tooltip.
+ Set the tooltip component around the one you want to display the tooltip.
+ The message is gathered from the page's resources file.
+
+
+
+
+ Mouseover this text
+
+
+
+ Mouseover this other text
+
+
+
+
+ Property file :
+
+ tooltip-message-example=Do you see me ?
+
+
+
+
+
diff --git a/src/main/webapp/components/tooltip/Example2.tml b/src/main/webapp/components/tooltip/Example2.tml
new file mode 100644
index 0000000..4912172
--- /dev/null
+++ b/src/main/webapp/components/tooltip/Example2.tml
@@ -0,0 +1,25 @@
+
+
+
+ This page displays a Tooltip automatically configured through its id.
+ Notice the page's resources file containing a well formed key.
+
+
+
+
+ Mouseover this text
+
+
+
+
+ Property file :
+
+ tooltip-tooltip=This is the tooltip content
+
+
+
+
+
diff --git a/src/main/webapp/components/tooltip/Example3.tml b/src/main/webapp/components/tooltip/Example3.tml
new file mode 100644
index 0000000..4d2358f
--- /dev/null
+++ b/src/main/webapp/components/tooltip/Example3.tml
@@ -0,0 +1,26 @@
+
+
+
+ This page displays a Tooltip containing some rich content declared in the page.
+ Notice the block tooltipBlock in the page. It will automatically loaded in the tooltip.
+ This block is reusable among several tooltips.
+
+
+
+
+ Mouseover this text
+
+
+
+ Mouseover this other text
+
+
+
+ Thats a tooltip said RICH
+
+
+
+
diff --git a/src/main/webapp/css/github.css b/src/main/webapp/css/github.css
new file mode 100644
index 0000000..bd778a7
--- /dev/null
+++ b/src/main/webapp/css/github.css
@@ -0,0 +1,129 @@
+/*
+
+github.com style (c) Vasily Polovnyov
+
+*/
+
+pre code {
+ display: block; padding: 0.5em;
+ color: #000;
+ background: #f8f8ff
+}
+
+pre .comment,
+pre .template_comment,
+pre .diff .header,
+pre .javadoc {
+ color: #998;
+ font-style: italic
+}
+
+pre .keyword,
+pre .css .rule .keyword,
+pre .winutils,
+pre .javascript .title,
+pre .lisp .title,
+pre .subst {
+ color: #000;
+ font-weight: bold
+}
+
+pre .number,
+pre .hexcolor {
+ color: #40a070
+}
+
+pre .string,
+pre .tag .value,
+pre .phpdoc,
+pre .tex .formula {
+ color: #d14
+}
+
+pre .title,
+pre .id {
+ color: #900;
+ font-weight: bold
+}
+
+pre .javascript .title,
+pre .lisp .title,
+pre .subst {
+ font-weight: normal
+}
+
+pre .class .title,
+pre .haskell .label,
+pre .tex .command {
+ color: #458;
+ font-weight: bold
+}
+
+pre .tag,
+pre .tag .title,
+pre .rules .property,
+pre .django .tag .keyword {
+ color: #000080;
+ font-weight: normal
+}
+
+pre .attribute,
+pre .variable,
+pre .instancevar,
+pre .lisp .body {
+ color: #008080
+}
+
+pre .regexp {
+ color: #009926
+}
+
+pre .class {
+ color: #458;
+ font-weight: bold
+}
+
+pre .symbol,
+pre .ruby .symbol .string,
+pre .ruby .symbol .keyword,
+pre .ruby .symbol .keymethods,
+pre .lisp .keyword,
+pre .tex .special,
+pre .input_number {
+ color: #990073
+}
+
+pre .builtin,
+pre .built_in,
+pre .lisp .title {
+ color: #0086b3
+}
+
+pre .preprocessor,
+pre .pi,
+pre .doctype,
+pre .shebang,
+pre .cdata {
+ color: #999;
+ font-weight: bold
+}
+
+pre .deletion {
+ background: #fdd
+}
+
+pre .addition {
+ background: #dfd
+}
+
+pre .diff .change {
+ background: #0086b3
+}
+
+pre .chunk {
+ color: #aaa
+}
+
+pre .tex .formula {
+ opacity: 0.5;
+}
diff --git a/src/main/webapp/favicon.ico b/src/main/webapp/favicon.ico
new file mode 100644
index 0000000..ffd53d6
Binary files /dev/null and b/src/main/webapp/favicon.ico differ
diff --git a/src/main/webapp/img/grouping/email_open.png b/src/main/webapp/img/grouping/email_open.png
new file mode 100644
index 0000000..7b6f981
Binary files /dev/null and b/src/main/webapp/img/grouping/email_open.png differ
diff --git a/src/main/webapp/img/grouping/emails.png b/src/main/webapp/img/grouping/emails.png
new file mode 100644
index 0000000..7348aed
Binary files /dev/null and b/src/main/webapp/img/grouping/emails.png differ
diff --git a/src/main/webapp/img/grouping/information.png b/src/main/webapp/img/grouping/information.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/src/main/webapp/img/grouping/information.png differ
diff --git a/src/main/webapp/img/tab/application.png b/src/main/webapp/img/tab/application.png
new file mode 100644
index 0000000..1dee9e3
Binary files /dev/null and b/src/main/webapp/img/tab/application.png differ
diff --git a/src/main/webapp/img/tab/comments.png b/src/main/webapp/img/tab/comments.png
new file mode 100644
index 0000000..39433cf
Binary files /dev/null and b/src/main/webapp/img/tab/comments.png differ
diff --git a/src/main/webapp/img/tab/email.png b/src/main/webapp/img/tab/email.png
new file mode 100644
index 0000000..7348aed
Binary files /dev/null and b/src/main/webapp/img/tab/email.png differ
diff --git a/src/main/webapp/js/exanpe-demo.js b/src/main/webapp/js/exanpe-demo.js
new file mode 100644
index 0000000..cdb8686
--- /dev/null
+++ b/src/main/webapp/js/exanpe-demo.js
@@ -0,0 +1,2 @@
+hljs.tabReplace = ' ';
+hljs.initHighlightingOnLoad();
\ No newline at end of file
diff --git a/src/main/webapp/js/highlight.js b/src/main/webapp/js/highlight.js
new file mode 100644
index 0000000..12f65dc
--- /dev/null
+++ b/src/main/webapp/js/highlight.js
@@ -0,0 +1 @@
+var hljs=new function(){function l(o){return o.replace(/&/gm,"&").replace(/"}while(x.length||y.length){var u=t().splice(0,1)[0];v+=l(w.substr(q,u.offset-q));q=u.offset;if(u.event=="start"){v+=r(u.node);s.push(u.node)}else{if(u.event=="stop"){var p=s.length;do{p--;var o=s[p];v+=(""+o.nodeName.toLowerCase()+">")}while(o!=u.node);s.splice(p,1);while(p'+l(K[0])+""}else{M+=l(K[0])}O=N.lR.lastIndex;K=N.lR.exec(L)}M+=l(L.substr(O,L.length-O));return M}function J(r,L){if(L.sL&&d[L.sL]){var K=f(L.sL,r);s+=K.keyword_count;return K.value}else{return E(r,L)}}function H(L,r){var K=L.cN?'':"";if(L.rB){p+=K;L.buffer=""}else{if(L.eB){p+=l(r)+K;L.buffer=""}else{p+=K;L.buffer=r}}B.push(L);A+=L.r}function D(N,K,P){var Q=B[B.length-1];if(P){p+=J(Q.buffer+N,Q);return false}var L=y(K,Q);if(L){p+=J(Q.buffer+N,Q);H(L,K);return L.rB}var r=v(B.length-1,K);if(r){var M=Q.cN?"":"";if(Q.rE){p+=J(Q.buffer+N,Q)+M}else{if(Q.eE){p+=J(Q.buffer+N,Q)+M+l(K)}else{p+=J(Q.buffer+N+K,Q)+M}}while(r>1){M=B[B.length-2].cN?"":"";p+=M;r--;B.length--}var O=B[B.length-1];B.length--;B[B.length-1].buffer="";if(O.starts){H(O.starts,"")}return Q.rE}if(w(K,Q)){throw"Illegal"}}var G=d[I];var B=[G.dM];var A=0;var s=0;var p="";try{var u=0;G.dM.buffer="";do{var x=q(C,u);var t=D(x[0],x[1],x[2]);u+=x[0].length;if(!t){u+=x[1].length}}while(!x[2]);if(B.length>1){throw"Illegal"}return{language:I,r:A,keyword_count:s,value:p}}catch(F){if(F=="Illegal"){return{language:null,r:0,keyword_count:0,value:l(C)}}else{throw F}}}function h(){function o(t,s,u){if(t.compiled){return}if(!u){t.bR=c(s,t.b?t.b:"\\B|\\b");if(!t.e&&!t.eW){t.e="\\B|\\b"}if(t.e){t.eR=c(s,t.e)}}if(t.i){t.iR=c(s,t.i)}if(t.r==undefined){t.r=1}if(t.k){t.lR=c(s,t.l||hljs.IR,true)}for(var r in t.k){if(!t.k.hasOwnProperty(r)){continue}if(t.k[r] instanceof Object){t.kG=t.k}else{t.kG={keyword:t.k}}break}if(!t.c){t.c=[]}t.compiled=true;for(var q=0;qx.keyword_count+x.r){x=u}if(u.keyword_count+u.r>w.keyword_count+w.r){x=w;w=u}}}var s=t.className;if(!s.match(w.language)){s=s?(s+" "+w.language):w.language}var o=b(t);if(o.length){var q=document.createElement("pre");q.innerHTML=w.value;w.value=k(o,b(q),A)}if(y){w.value=w.value.replace(/^((<[^>]+>|\t)+)/gm,function(B,E,D,C){return E.replace(/\t/g,y)})}if(p){w.value=w.value.replace(/\n/g," ")}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName=="CODE"&&t.parentNode.tagName=="PRE"){var q=t.parentNode;var v=document.createElement("div");v.innerHTML="
"+w.value+"
";t=v.firstChild.firstChild;v.firstChild.cN=q.cN;q.parentNode.replaceChild(v.firstChild,q)}else{t.innerHTML=w.value}t.className=s;t.dataset={};t.dataset.result={language:w.language,kw:w.keyword_count,re:w.r};if(x&&x.language){t.dataset.second_best={language:x.language,kw:x.keyword_count,re:x.r}}}function j(){if(j.called){return}j.called=true;e();var q=document.getElementsByTagName("pre");for(var o=0;o|>=|>>|>>=|>>>|>>>=|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~";this.BE={b:"\\\\.",r:0};this.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[this.BE],r:0};this.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[this.BE],r:0};this.CLCM={cN:"comment",b:"//",e:"$"};this.CBLCLM={cN:"comment",b:"/\\*",e:"\\*/"};this.HCM={cN:"comment",b:"#",e:"$"};this.NM={cN:"number",b:this.NR,r:0};this.CNM={cN:"number",b:this.CNR,r:0};this.inherit=function(o,r){var q={};for(var p in o){q[p]=o[p]}if(r){for(var p in r){q[p]=r[p]}}return q}}();hljs.LANGUAGES.javascript={dM:{k:{keyword:{"in":1,"if":1,"for":1,"while":1,"finally":1,"var":1,"new":1,"function":1,"do":1,"return":1,"void":1,"else":1,"break":1,"catch":1,"instanceof":1,"with":1,"throw":1,"case":1,"default":1,"try":1,"this":1,"switch":1,"continue":1,"typeof":1,"delete":1},literal:{"true":1,"false":1,"null":1}},c:[hljs.ASM,hljs.QSM,hljs.CLCM,hljs.CBLCLM,hljs.CNM,{b:"("+hljs.RSR+"|case|return|throw)\\s*",k:{"return":1,"throw":1,"case":1},c:[hljs.CLCM,hljs.CBLCLM,{cN:"regexp",b:"/.*?[^\\\\/]/[gim]*"}],r:0},{cN:"function",b:"\\bfunction\\b",e:"{",k:{"function":1},c:[{cN:"title",b:"[A-Za-z$_][0-9A-Za-z$_]*"},{cN:"params",b:"\\(",e:"\\)",c:[hljs.ASM,hljs.QSM,hljs.CLCM,hljs.CBLCLM]}]}]}};hljs.LANGUAGES.css=function(){var a={cN:"function",b:hljs.IR+"\\(",e:"\\)",c:[{eW:true,eE:true,c:[hljs.NM,hljs.ASM,hljs.QSM]}]};return{cI:true,dM:{i:"[=/|']",c:[hljs.CBLCLM,{cN:"id",b:"\\#[A-Za-z0-9_-]+"},{cN:"class",b:"\\.[A-Za-z0-9_-]+",r:0},{cN:"attr_selector",b:"\\[",e:"\\]",i:"$"},{cN:"pseudo",b:":(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\\\"\\']+"},{cN:"at_rule",b:"@font-face",l:"[a-z-]+",k:{"font-face":1}},{cN:"at_rule",b:"@",e:"[{;]",eE:true,k:{"import":1,page:1,media:1,charset:1},c:[a,hljs.ASM,hljs.QSM,hljs.NM]},{cN:"tag",b:hljs.IR,r:0},{cN:"rules",b:"{",e:"}",i:"[^\\s]",r:0,c:[hljs.CBLCLM,{cN:"rule",b:"[^\\s]",rB:true,e:";",eW:true,c:[{cN:"attribute",b:"[A-Z\\_\\.\\-]+",e:":",eE:true,i:"[^\\s]",starts:{cN:"value",eW:true,eE:true,c:[a,hljs.NM,hljs.QSM,hljs.ASM,hljs.CBLCLM,{cN:"hexcolor",b:"\\#[0-9A-F]+"},{cN:"important",b:"!important"}]}}]}]}]}}}();hljs.LANGUAGES.xml=function(){var b="[A-Za-z0-9\\._:-]+";var a={eW:true,c:[{cN:"attribute",b:b,r:0},{b:'="',rB:true,e:'"',c:[{cN:"value",b:'"',eW:true}]},{b:"='",rB:true,e:"'",c:[{cN:"value",b:"'",eW:true}]},{b:"=",c:[{cN:"value",b:"[^\\s/>]+"}]}]};return{cI:true,dM:{c:[{cN:"pi",b:"<\\?",e:"\\?>",r:10},{cN:"doctype",b:"",r:10},{cN:"comment",b:"",r:10},{cN:"cdata",b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{cN:"tag",b:"",rE:true,sL:"css"}},{cN:"tag",b:"