two aspects of Web development: Assets management (js, css): organization in bundles, HTML injection, soon asset minification and merging Integration of powerful Javascript librairies thanks to a set of components Licensed under BSD 3-Clause Hosted on Github Current version: 0.10.0 3 / 101
{ " b u n d l e " : " j q u e r y " , " a s s e t s " : [ { " n a m e " : " j q u e r y " , " v e r s i o n " : " 1 . 1 1 . 1 " , " t y p e " : " j s " , " l o c a t i o n s " : { " w e b a p p " : " / a s s e t s / j s / j q u e r y - 1 . 1 1 . 1 . j s " } } ] } Several locations are allowed for each asset: webapp, classpath, CDN, JAR, WebJar and API! See the docs 9 / 101
as dependencies { " b u n d l e " : " s e l e c t 2 " , " d e p e n d e n c i e s " : [ " j q u e r y " ] , " a s s e t s " : [ { " n a m e " : " s e l e c t 2 " , " v e r s i o n " : " 3 . 4 . 8 " , " t y p e " : " j s " , " l o c a t i o n s " : { " w e b a p p " : " / a s s e t s / j s / s e l e c t 2 . j s " } } , { " n a m e " : " s e l e c t 2 " , " v e r s i o n " : " 3 . 4 . 8 " , " t y p e " : " c s s " , " l o c a t i o n s " : { " w e b a p p " : " / a s s e t s / c s s / s e l e c t 2 . c s s " } } ] } 10 / 101
" : " m y - b u n d l e " , " a s s e t s " : [ { " n a m e " : " m y - a p p l i c a t i o n " , " v e r s i o n " : " 1 . 0 . 0 " , " t y p e " : " j s " , " l o c a t i o n s " : { " w e b a p p " : " / a s s e t s / j s / a p p . j s " } } ] } Asset locators — webapp 13 / 101
" : " m y - b u n d l e " , " a s s e t s " : [ { " n a m e " : " m y - a p p l i c a t i o n " , " v e r s i o n " : " 1 . 0 . 0 " , " t y p e " : " j s " , " l o c a t i o n s " : { " c l a s s p a t h " : " j s / a p p . j s " } } ] } Asset locators — classpath 16 / 101
s r c = " / [ c o n t e x t P a t h ] / d a n d e l i o n - a s s e t s / [ c a c h e K e y ] / a p p . j s " > < / s c r i p t > Asset locators — classpath 17 / 101
: " j q u e r y " , " a s s e t s " : [ { " n a m e " : " j q u e r y " , " v e r s i o n " : " 1 . 1 1 . 0 " , " t y p e " : " j s " , " l o c a t i o n s " : { " c d n " : " / / c d n j s . c l o u d f l a r e . c o m / . . . / j q u e r y . j s " } } ] } Asset locators — cdn 18 / 101
s - c o r e | _ _ s r c | _ _ m a i n | _ _ r e s o u r c e s | _ _ M E T A - I N F | _ _ r e s o u r c e s | _ _ f o l d e r | _ _ j s | _ _ a p p . j s Asset locators — jar 20 / 101
" : " m y - b u n d l e " , " a s s e t s " : [ { " n a m e " : " m y - a p p " , " v e r s i o n " : " 1 . 0 . 0 " , " t y p e " : " j s " , " l o c a t i o n s " : { " j a r " : " f o l d e r / j s / a p p . j s " } } ] } Asset locators — jar 21 / 101
c r i p t s r c = " / [ c o n t e x t P a t h ] / d a n d e l i o n - a s s e t s / [ c a c h e K e y ] / a p p . j s " > < / s c r i p t > Inside a Servlet 3.0+ container: < s c r i p t s r c = " / [ c o n t e x t P a t h ] / f o l d e r / j s / a p p . j s " > < / s c r i p t > Dandelion automatically detects whether the running server is using the Servlet 3.x API or lower Asset locators — jar 22 / 101
n c y > < g r o u p I d > c o m . g i t h u b . d a n d e l i o n < / g r o u p I d > < a r t i f a c t I d > d a n d e l i o n - w e b j a r s < / a r t i f a c t I d > < v e r s i o n > 0 . 1 0 . 0 < / v e r s i o n > < / d e p e n d e n c y > This artifact brings a new dependency to the webjars- locator project, which is internally used by the locator to locate assets inside WebJars Asset locators — webjar 23 / 101
e n c y > < g r o u p I d > o r g . w e b j a r s < / g r o u p I d > < a r t i f a c t I d > b o o t s t r a p < / a r t i f a c t I d > < v e r s i o n > 3 . 2 . 0 < / v e r s i o n > < / d e p e n d e n c y > Asset locators — webjar 24 / 101
l e " : " m y - b u n d l e " , " a s s e t s " : [ { " n a m e " : " b o o t s t r a p " , " v e r s i o n " : " 3 . 2 . 0 " , " t y p e " : " c s s " , " l o c a t i o n s " : { " w e b j a r " : " b o o t s t r a p . c s s " } } ] } Asset locators — webjar 25 / 101
< l i n k r e l = " s t y l e s h e e t " h r e f = " / [ c o n t e x t P a t h ] / d a n d e l i o n - a s s e t s / [ c a c h e K e y ] / b o o t s t r a p . c s s " / > Inside a Servlet 3.0+ container: < l i n k r e l = " s t y l e s h e e t " h r e f = " / [ c o n t e x t P a t h ] / w e b j a r s / b o o t s t r a p / 3 . 2 . 0 / c s s / b o o t s t r a p . c s s " / > Dandelion automatically detects whether the running server is using the Servlet 3.x API or lower Asset locators — webjar 26 / 101
from a special parameter stored inside the A s s e t R e q u e s t C o n t e x t This special parameter: must be stored under the D e l e g a t e L o c a t o r . D E L E G A T E D _ C O N T E N T _ P A R A M key must be a class that implements D e l e g a t e d C o n t e n t and where the g e t C o n t e n t ( ) method must return the asset content to be injected ] 27 / 101
: " m y - b u n d l e " , " a s s e t s " : [ { " n a m e " : " m y - g e n e r a t e d - a s s e t " , " v e r s i o n " : " 1 . 0 . 0 " , " t y p e " : " j s " , " l o c a t i o n s " : { " d e l e g a t e " : " a p p . j s " } } ] } Asset locators — delegate 28 / 101
a s s S o m e J a v a s c r i p t G e n e r a t o r i m p l e m e n t s D e l e g a t e d C o n t e n t { @ O v e r r i d e p u b l i c S t r i n g g e t C o n t e n t ( H t t p S e r v l e t R e q u e s t r e q u e s t ) { r e t u r n " a l e r t ( ' H e y ! ' ) ; " ; } } Asset locators — delegate 29 / 101
q u e s t C o n t e x t . g e t ( r e q u e s t ) . a d d P a r a m e t e r ( " m y - g e n e r a t e d - a s s e t " , D e l e g a t e L o c a t o r . D E L E G A T E D _ C O N T E N T _ P A R A M , n e w S o m e J a v a s c r i p t G e n e r a t o r ( ) ) ; Asset locators — delegate 30 / 101
t s r c = " / [ c o n t e x t P a t h ] / d a n d e l i o n - a s s e t s / [ c a c h e K e y ] / a p p . j s " > < / s c r i p t > Where a p p . j s : a l e r t ( ' H e y ! ' ) ; Asset locators — delegate 31 / 101
following order: VendorBundleLoader: intended to load vendor bundles (e.g. jquery.json) ComponentBundleLoader: intended to load components bundles (e.g. ddl- dt.json) DandelionBundleLoader: intended to load user bundles (e.g. custom- bundle.json) See the docs 32 / 101
o n t e x t that will be injected into each request. This C o n t e x t provide several information: all configuration options (coming from the properties files) a bundle graph (DAG), built from all scanned bundles Example: s r c | _ _ m a i n | _ _ r e s o u r c e s | _ _ d a n d e l i o n | _ _ j q u e r y . j s o n | _ _ s e l e c t 2 . j s o n See the docs 33 / 101
< % @ t a g l i b p r e f i x = " d a n d e l i o n " u r i = " h t t p : / / g i t h u b . c o m / d a n d e l i o n " % > < d a n d e l i o n : b u n d l e i n c l u d e s = " s e l e c t 2 " / > 2/4) Using the Thymeleaf dialect < ! D O C T Y P E h t m l > < h t m l x m l n s : t h = " h t t p : / / w w w . t h y m e l e a f . o r g " x m l n s : d d l = " h t t p : / / g i t h u b . c o m / d a n d e l i o n " d d l : b u n d l e - i n c l u d e s = " s e l e c t 2 " > . . . < / h t m l > See the docs 34 / 101
A s s e t R e q u e s t C o n t e x t . g e t ( ( H t t p S e r v l e t R e q u e s t ) r e q u e s t ) . a d d B u n d l e ( " s e l e c t 2 " ) ; 4/4) Using the configuration file ("permanent" bundles) b u n d l e . i n c l u d e s = s e l e c t 2 See the docs 35 / 101
automatically injects all requested assets into the HTML code: in the right order in the configured position, by default CSS in < h e a d > and JS just before < / b o d y > and (soon) applies the right HTTP headers, therefore optimizing browser caching < h t m l > < h e a d > < l i n k h r e f = " / c o n t e x t / a s s e t s / c s s / s e l e c t 2 . c s s " / > < / h e a d > < b o d y > . . . < s c r i p t s r c = " / c o n t e x t / a s s e t s / j s / j q u e r y - 1 . 1 1 . 1 . j s " > < / s c r i p t > < s c r i p t s r c = " / c o n t e x t / a s s e t s / j s / s e l e c t 2 . j s " > < / s c r i p t > < / b o d y > < / h t m l > 36 / 101
processors: jsMinYui:JS minification based on Yahoo's YUI Compressor cssMinYui:CSS minification based on Yahoo's YUI Compressor cssMin:CSS minification based on a fork of YUI jsMin:JS minification based on a fork of YUI cssUrlRewriting:Image URLs rewriting in CSS Soon: cssLess: Convert Less resources to CSS cssSass: Convert Sass resources to CSS cssImport: Processes @import coffeeScript: Convert CoffeeScript to JavaScript ... See the docs 37 / 101
how Dandelion-Core handles assets, in the current request h t t p : / / e x a m p l e . c o m / c o n t e x t / s o m e / u r i ? s h o w G r a p h Available in development mode only See the docs 39 / 101
server-side and client-side caching are disabled. Client-side, Dandelion-Core applies the following HTTP headers: Cache-Control = n o - c a c h e , n o - s t o r e , m u s t - r e v a l i d a t e (HTTP 1.1) Pragma = n o - c a c h e (HTTP 1.0) Expires = 0 (Proxies) 40 / 101
development, all changes made in asset bundles can be reflected. Just manually append a new r e l o a d B u n d l e s request parameter to the current URL to perform a full bundle reloading. h t t p : / / e x a m p l e . c o m / c o n t e x t / s o m e / u r i ? r e l o a d B u n d l e s Available in development mode only 41 / 101
f i l t e r > < f i l t e r - n a m e > d a n d e l i o n < / f i l t e r - n a m e > < f i l t e r - c l a s s > . . . D a n d e l i o n F i l t e r < / f i l t e r - c l a s s > < i n i t - p a r a m > < p a r a m - n a m e > d a n d e l i o n . m o d e < p a r a m - n a m e > < p a r a m - v a l u e > p r o d u c t i o n < / p a r a m - v a l u e > < / i n i t - p a r a m > < / f i l t e r > Configuration options 43 / 101
framework Facilitates the integration of DataTables, an awesome jQuery plugin which will add advanced interaction controls to any HTML table Easy to use Easy to extend Inspired by the excellent DisplayTag library 46 / 101
paging, filtering and sorting DOM sources, AJAX sources and server-side processing Responsive design Export in multiple formats Several themes available: Bootstrap 2, Bootstrap 3, jQueryUI I18n Integration with Spring/Spring MVC and other projects 47 / 101
a g l i b p r e f i x = " d a t a t a b l e s " u r i = " h t t p : / / g i t h u b . c o m / d a n d e l i o n / d a t a t a b l e s " % > < d a t a t a b l e s : t a b l e i d = " m y T a b l e I d " d a t a = " $ { p e r s o n s } " > < d a t a t a b l e s : c o l u m n t i t l e = " I d " p r o p e r t y = " i d " / > < d a t a t a b l e s : c o l u m n t i t l e = " L a s t N a m e " p r o p e r t y = " l a s t N a m e " / > < d a t a t a b l e s : c o l u m n t i t l e = " F i r s t N a m e " p r o p e r t y = " f i r s t N a m e " / > < d a t a t a b l e s : c o l u m n t i t l e = " C i t y " p r o p e r t y = " a d d r e s s . t o w n . n a m e " / > < d a t a t a b l e s : c o l u m n t i t l e = " M a i l " p r o p e r t y = " m a i l " / > < / d a t a t a b l e s : t a b l e > i d : HTML pass-through attribute d a t a : DOM source, collection of POJOs t i t l e : sets the content of the column header p r o p e r t y : name of the object's attribute of the collection being iterated on 48 / 101
l e i d = " m y T a b l e I d " d t : t a b l e = " t r u e " > < t h e a d > < t r > < t h > I d < / t h > < t h > F i r s t n a m e < / t h > < t h > L a s t n a m e < / t h > < t h > C i t y < / t h > < t h > M a i l < / t h > < / t r > < / t h e a d > < t b o d y > < t r t h : e a c h = " p e r s o n : $ { p e r s o n s } " > < t d t h : t e x t = " $ { p e r s o n . i d } " > 1 < / t d > < t d t h : t e x t = " $ { p e r s o n . f i r s t N a m e } " > J o h n < / t d > < t d t h : t e x t = " $ { p e r s o n . l a s t N a m e } " > D o e < / t d > < t d t h : t e x t = " $ { p e r s o n ? . a d d r e s s ? . t o w n ? . n a m e } " > N o b o d y k n o w s ! < / t d > < t d t h : t e x t = " $ { p e r s o n . m a i l } " > j o h n @ d o e . c o m < / t d > < / t r > < / t b o d y > < / t a b l e > d t : t a b l e : enables the Dandelion-Datatables dialect in the current table 49 / 101
directly by Thymeleaf < t a b l e i d = " m y T a b l e I d " > < t h e a d > < t r > < t h > I d < / t h > < t h > F i r s t n a m e < / t h > < t h > L a s t n a m e < / t h > < t h > C i t y < / t h > < t h > M a i l < / t h > < / t r > < / t h e a d > < t b o d y > < t r > < t d > 1 < / t d > < t d > W i n g < / t d > < t d > C u n n i n g h a m < / t d > < t d > < / t d > < t d > o r n a r e . l i b e r o @ m a i l . e d u < / t d > < / t r > . . . < / t b o d y > < / t a b l e > How it works? 50 / 101
DataTables v a r o T a b l e _ m y T a b l e I d = $ ( ' # m y T a b l e I d ' ) ; v a r o T a b l e _ m y T a b l e I d _ p a r a m s = { " a o C o l u m n s " : [ { " m D a t a " : " i d " , " s D e f a u l t C o n t e n t " : " " } , { " m D a t a " : " l a s t N a m e " , " s D e f a u l t C o n t e n t " : " " } , { " m D a t a " : " f i r s t N a m e " , " s D e f a u l t C o n t e n t " : " " } , { " m D a t a " : " a d d r e s s . t o w n . n a m e " , " s D e f a u l t C o n t e n t " : " " } , { " m D a t a " : " m a i l " , " s D e f a u l t C o n t e n t " : " " } ] } $ ( d o c u m e n t ) . r e a d y ( f u n c t i o n ( ) { o T a b l e _ m y T a b l e I d . d a t a T a b l e ( o T a b l e _ m y T a b l e I d _ p a r a m s ) ; } ) ; How it works? 51 / 101
R e q u e s t C o n t e x t is filled with the required assets, either by the JSP taglib or by the Thymeleaf dialect... A s s e t R e q u e s t C o n t e x t . g e t ( r e q u e s t ) . a d d B u n d l e ( " d a t a t a b l e s " ) . a d d B u n d l e ( " d d l - d t " ) . . . ; ... so that they will be injected by Dandelion-Core into the response < l i n k h r e f = " / / c d n / j q u e r y . d a t a T a b l e s . c s s " / > . . . < s c r i p t s r c = " / / c d n / j q u e r y . j s " > < / s c r i p t > < s c r i p t s r c = " / / c d n / j q u e r y . d a t a T a b l e s . j s " > < / s c r i p t > < s c r i p t s r c = " / [ c o n t e x t P a t h ] / d a n d e l i o n - a s s e t s / [ S H A ] / d a n d e l i o n - d a t a t a b l e s - 0 . 1 0 . 0 . j s " > < / s c r i p t > How it works? 52 / 101
n t r o l l e r p u b l i c c l a s s C o n t r o l l e r { @ M o d e l A t t r i b u t e ( " p e r s o n s " ) p u b l i c L i s t < P e r s o n > p o p u l a t e T a b l e ( ) { r e t u r n p e r s o n S e r v i c e . f i n d A l l ( ) ; } } HTML sources — example 55 / 101
l e s : t a b l e i d = " m y T a b l e I d " d a t a = " $ { p e r s o n s } " > < d a t a t a b l e s : c o l u m n t i t l e = " I d " p r o p e r t y = " i d " / > . . . < / d a t a t a b l e s : t a b l e > HTML sources — example 56 / 101
d = " m y T a b l e I d " d t : t a b l e = " t r u e " > . . . < t b o d y > < t r t h : e a c h = " p e r s o n : $ { p e r s o n s } " > < t d t h : t e x t = " $ { p e r s o n . i d } " > 1 < / t d > . . . < / t r > < / t b o d y > < t a b l e > HTML sources — example 57 / 101
n t r o l l e r p u b l i c c l a s s A j a x C o n t r o l l e r { @ R e q u e s t M a p p i n g ( v a l u e = " / p e r s o n s " ) p u b l i c @ R e s p o n s e B o d y L i s t < P e r s o n > f i n d A l l ( ) { r e t u r n p e r s o n S e r v i c e . f i n d A l l ( ) ; } } AJAX sources 59 / 101
l e s : t a b l e i d = " m y T a b l e I d " u r l = " / p e r s o n s " > < d a t a t a b l e s : c o l u m n t i t l e = " I d " p r o p e r t y = " i d " / > . . . < / d a t a t a b l e s : t a b l e > Dandelion-Datatables rewrites URLs by appending the context path, if needed. AJAX sources 60 / 101
d = " m y T a b l e I d " d t : t a b l e = " t r u e " d t : u r l = " @ { / p e r s o n s } " > . . . < t b o d y > < t r t h : e a c h = " p e r s o n : $ { p e r s o n s } " > < t d t h : t e x t = " $ { p e r s o n . i d } " > 1 < / t d > . . . < / t r > < / t b o d y > < t a b l e > AJAX sources 61 / 101
JSON data source that can be obtained by AJAX Server-side processing Each draw of the table will result in a new AJAX request being made to get the required data Works well with small/medium/large data sources 62 / 101
D a t a t a b l e s C r i t e r i a s Stores all DataTables parameters (current page, entries to display, sorted columns, ...) @ R e q u e s t M a p p i n g ( v a l u e = " / p e r s o n s " ) p u b l i c @ R e s p o n s e B o d y D a t a t a b l e s R e s p o n s e < P e r s o n > f i l t e r ( H t t p S e r v l e t R e q u e s t r e q u e s t ) { / / M a p s r e q u e s t p a r a m e t e r t o a D a t a t a b l e s C r i t e r i a s i n s t a n c e D a t a t a b l e s C r i t e r i a s c r i t e r i a s = D a t a t a b l e s C r i t e r i a s . g e t F r o m R e q u e s t ( r e q u e s t ) ; . . . 63 / 101
D a t a S e t All entries returned by the data access layer should be wrapped in this class in order to build a D a t a T a b l e s R e s p o n s e . . . / / G e t f i l t e r e d a n d p a g e d d a t a D a t a S e t < P e r s o n > p e r s o n s = p e r s o n S e r v i c e . f i n d P e r s o n s ( c r i t e r i a s ) ; . . . 64 / 101
D a t a T a b l e s R e s p o n s e Contains a builder that helps to return the data in the format required by DataTables Must be converted into JSON . . . / / B u i l d t h e r e s p o n s e t h a t w i l l b e c o n v e r t e d t o J S O N r e t u r n D a t a t a b l e s R e s p o n s e . b u i l d ( p e r s o n s , c r i t e r i a s ) ; } 65 / 101
e q u e s t M a p p i n g ( v a l u e = " / p e r s o n s " ) p u b l i c @ R e s p o n s e B o d y D a t a t a b l e s R e s p o n s e < P e r s o n > f i l t e r ( H t t p S e r v l e t R e q u e s t r e q u e s t ) { / / M a p s r e q u e s t p a r a m e t e r t o a D a t a t a b l e s C r i t e r i a s i n s t a n c e D a t a t a b l e s C r i t e r i a s c r i t e r i a s = D a t a t a b l e s C r i t e r i a s . g e t F r o m R e q u e s t ( r e q u e s t ) ; / / G e t f i l t e r e d a n d p a g e d d a t a D a t a S e t < P e r s o n > p e r s o n s = p e r s o n S e r v i c e . f i n d P e r s o n s ( c r i t e r i a s ) ; / / B u i l d t h e r e s p o n s e t h a t w i l l b e c o n v e r t e d t o J S O N r e t u r n D a t a t a b l e s R e s p o n s e . b u i l d ( p e r s o n s , c r i t e r i a s ) ; } AJAX sources + server-side processing 66 / 101
l e s : t a b l e . . . u r l = " / p e r s o n s " s e r v e r S i d e = " t r u e " > < d a t a t a b l e s : c o l u m n p r o p e r t y = " i d " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " f i r s t N a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " l a s t N a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " a d d r e s s . t o w n . n a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " m a i l " / > < / d a t a t a b l e s : t a b l e > AJAX sources + server-side processing 67 / 101
. . d t : u r l = " @ { / p e r s o n s } " d t : s e r v e r S i d e = " t r u e " > < t h e a d > < t r > < t h d t : p r o p e r t y = " i d " > I d < / t h > < t h d t : p r o p e r t y = " f i r s t N a m e " > F i r s t n a m e < / t h > < t h d t : p r o p e r t y = " l a s t N a m e " > L a s t n a m e < / t h > < t h d t : p r o p e r t y = " a d d r e s s . t o w n . n a m e " > C i t y < / t h > < t h d t : p r o p e r t y = " m a i l " > M a i l < / t h > < / t r > < / t h e a d > < / t a b l e > AJAX sources + server-side processing 68 / 101
e s : t a b l e . . . p a g e a b l e = " f a l s e " > < d a t a t a b l e s : c o l u m n . . . s o r t a b l e = " f a l s e " / > < d a t a t a b l e s : c o l u m n . . . f i l t e r a b l e = " t r u e " / > . . . < / d a t a t a b l e s : t a b l e > Paging, sorting, filtering 69 / 101
. d t : p a g e a b l e = " f a l s e " > < t h e a d > < t h d t : s o r t a b l e = " f a l s e " > I d < / t h > < t h d t : f i l t e r a b l e = " t r u e " > L a s t N a m e < / t h > . . . < / t h e a d > . . . < t a b l e > Paging, sorting, filtering 70 / 101
extras already exist and provide: an export class that is used by default if the corresponding export format is enabled the corresponding library in compile scope (e.g. Apache POI for the XLS format) Available extras: PDF: datatables-export-itext XLS: datatables-export-poi XLSX: datatables-export-poi-ooxml 72 / 101
export full data source Only compatible with DOM sources Controller-based Requires a bit more work to set up WYSIWYE => What You See Is What You ... Export! Compatible with DOM and AJAX sources 73 / 101
n c y > < g r o u p I d > c o m . g i t h u b . d a n d e l i o n < / g r o u p I d > < a r t i f a c t I d > d a t a t a b l e s - e x p o r t - i t e x t < / a r t i f a c t I d > < v e r s i o n > 0 . 1 0 . 0 < / v e r s i o n > < / d e p e n d e n c y > Export — filter-based 74 / 101
d e l i o n - D a t a t a b l e s f i l t e r u s e d f o r b a s i c e x p o r t - - > < f i l t e r > < f i l t e r - n a m e > d a t a t a b l e s < / f i l t e r - n a m e > < f i l t e r - c l a s s > . . . D a t a t a b l e s F i l t e r < / f i l t e r - c l a s s > < / f i l t e r > < f i l t e r - m a p p i n g > < f i l t e r - n a m e > d a t a t a b l e s < / f i l t e r - n a m e > < u r l - p a t t e r n > / * < / u r l - p a t t e r n > < / f i l t e r - m a p p i n g > Export — filter-based 75 / 101
a b l e s : t a b l e . . . e x p o r t = " p d f " > < d a t a t a b l e s : c o l u m n p r o p e r t y = " i d " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " f i r s t N a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " l a s t N a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " a d d r e s s . t o w n . n a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " m a i l " / > < / d a t a t a b l e s : t a b l e > Export — filter-based 76 / 101
e i d = " m y T a b l e " d t : t a b l e = " t r u e " d t : e x p o r t = " p d f " > < t h e a d > < t r > < t h > I d < / t h > < t h > F i r s t n a m e < / t h > < t h > L a s t n a m e < / t h > < t h > C i t y < / t h > < t h > M a i l < / t h > < / t r > < / t h e a d > < t b o d y > < t r t h : e a c h = " p e r s o n : $ { p e r s o n s } " > < t d t h : t e x t = " $ { p e r s o n . i d } " > 1 < / t d > < t d t h : t e x t = " $ { p e r s o n . f i r s t N a m e } " > J o h n < / t d > < t d t h : t e x t = " $ { p e r s o n . l a s t N a m e } " > D o e < / t d > < t d t h : t e x t = " $ { p e r s o n . a d d r e s s . t o w n . n a m e } " > N o b o d y k n o w s ! < / t d > < t d t h : t e x t = " $ { p e r s o n . m a i l } " > j o h n @ d o e . c o m < / t d > < / t r > < / t b o d y > < / t a b l e > Export — filter-based 77 / 101
n c y > < g r o u p I d > c o m . g i t h u b . d a n d e l i o n < / g r o u p I d > < a r t i f a c t I d > d a t a t a b l e s - e x p o r t - i t e x t < / a r t i f a c t I d > < v e r s i o n > 0 . 1 0 . 0 < / v e r s i o n > < / d e p e n d e n c y > Export — controller-based 78 / 101
b l e s : t a b l e i d = " m y T a b l e I d " u r l = " / p e r s o n s " e x p o r t = " p d f " > < d a t a t a b l e s : c o l u m n p r o p e r t y = " i d " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " f i r s t N a m e " / > . . . < d a t a t a b l e s : e x p o r t t y p e = " c s v " u r l = " / e x p o r t . p d f " / > < / d a t a t a b l e s : t a b l e > Export — controller-based 79 / 101
: c o n f = " m y T a b l e I d " > < d i v d t : c o n f T y p e = " e x p o r t " d t : t y p e = " p d f " d t : u r l = " @ { / e x p o r t . p d f } " > < / d i v > < / d i v > < t a b l e . . . d t : u r l = " @ { / p e r s o n s } " d t : e x p o r t = " p d f " > < t h e a d > < t r > < t h d t : p r o p e r t y = " i d " > I d < / t h > < t h d t : p r o p e r t y = " f i r s t N a m e " > F i r s t n a m e < / t h > < t h d t : p r o p e r t y = " l a s t N a m e " > L a s t n a m e < / t h > < t h d t : p r o p e r t y = " a d d r e s s . t o w n . n a m e " > C i t y < / t h > < t h d t : p r o p e r t y = " m a i l " > M a i l < / t h > < / t r > < / t h e a d > < / t a b l e > Export — controller-based 80 / 101
u e s t M a p p i n g ( v a l u e = " / e x p o r t " , p r o d u c e s = " a p p l i c a t i o n / p d f " ) p u b l i c v o i d p d f ( @ D a t a t a b l e s P a r a m s D a t a t a b l e s C r i t e r i a s c r i t e r i a s , H t t p S e r v l e t R e q u e s t r e q u e s t , H t t p S e r v l e t R e s p o n s e r e s p o n s e ) { / / G e t d a t a t o e x p o r t u s i n g t h e p r o v i d e d c r i t e r i a L i s t < P e r s o n > p e r s o n s = p e r s o n S e r v i c e . f i n d P e r s o n s ( c r i t e r i a s ) ; . . . Export — controller-based 81 / 101
/ B u i l d t h e e x p o r t c o n f i g u r a t i o n E x p o r t C o n f e x p o r t P d f C o n f = n e w E x p o r t C o n f . B u i l d e r ( " p d f " ) . h e a d e r ( t r u e ) . e x p o r t C l a s s ( n e w P d f E x p o r t ( ) ) . b u i l d ( ) ; . . . Export — controller-based 82 / 101
/ B u i l d t h e t a b l e t o e x p o r t u s i n g t h e a b o v e d a t a / / a n d t h e e x p o r t c o n f i g u r a t i o n H t m l T a b l e t a b l e = n e w H t m l T a b l e B u i l d e r < P e r s o n > ( ) . n e w B u i l d e r ( " t a b l e I d " , p e r s o n s , r e q u e s t , e x p o r t P d f C o n f ) . c o l u m n ( ) . f i l l W i t h P r o p e r t y ( " i d " ) . t i t l e ( " I d " ) . c o l u m n ( ) . f i l l W i t h P r o p e r t y ( " f i r s t N a m e " ) . t i t l e ( " F i r t n a m e " ) . c o l u m n ( ) . f i l l W i t h P r o p e r t y ( " l a s t N a m e " ) . t i t l e ( " L a s t n a m e " ) . c o l u m n ( ) . f i l l W i t h P r o p e r t y ( " a d d r e s s . t o w n . n a m e " ) . t i t l e ( " C i t y " ) . c o l u m n ( ) . f i l l W i t h P r o p e r t y ( " m a i l " ) . t i t l e ( " M a i l " ) . c o l u m n ( ) . f i l l W i t h P r o p e r t y ( " b i r t h D a t e " , " { 0 , d a t e , d d - M M - y y y y } " ) . t i t l e ( " B i r t h D a t e " ) . b u i l d ( ) ; . . . Export — controller-based 83 / 101
/ R e n d e r t h e e x p o r t f i l e i n t h e b r o w s e r E x p o r t U t i l s . r e n d e r E x p o r t ( t a b l e , e x p o r t P d f C o n f , r e s p o n s e ) ; } Export — controller-based 84 / 101
a l . c s s . c l a s s = t a b l e t a b l e - s t r i p e d t a b l e - b o r d e r e d t a b l e - c o n d e n s e d g l o b a l . e x t r a . t h e m e = b o o t s t r a p 2 datatables_EN.properties: all EN translations g l o b a l . i 1 8 n . m s g . p r o c e s s i n g = P r o c e s s i n g . . . g l o b a l . i 1 8 n . m s g . s e a r c h = S e a r c h : g l o b a l . i 1 8 n . m s g . i n f o = S h o w i n g _ S T A R T _ t o _ E N D _ o f _ T O T A L _ e n t r i e s datatables_FR.properties: all FR translations g l o b a l . i 1 8 n . m s g . p r o c e s s i n g = T r a i t e m e n t e n c o u r s . . . g l o b a l . i 1 8 n . m s g . s e a r c h = R e c h e r c h e r : g l o b a l . i 1 8 n . m s g . i n f o = A f f i c h a g e d e l ' é l é m e n t _ S T A R T _ à _ E N D _ s u r _ T O T A L _ é l é m e n t s 85 / 101
e R e s o l v e r and M e s s a g e R e s o l v e r interfaces Built-in implementations: S p r i n g L o c a l e R e s o l v e r / S p r i n g M e s s a g e R e s o l v e r J s t l L o c a l e R e s o l v e r / J s t l M e s s a g e R e s o l v e r S t r u t s 1 L o c a l e R e s o l v e r / S t r u t s 1 M e s s a g e R e s o l v e r S t r u t s 2 L o c a l e R e s o l v e r / S t r u t s 2 M e s s a g e R e s o l v e r Possible to plug-in custom locale and message resolvers 86 / 101
" m e s s a g e S o u r c e " c l a s s = " . . . " > < p r o p e r t y n a m e = " b a s e n a m e " v a l u e = " c l a s s p a t h : m e s s a g e s " / > < / b e a n > I18n: example with Spring 87 / 101
_ m a i n | _ _ r e s o u r c e s | _ _ m e s s a g e s . p r o p e r t i e s | _ _ m e s s a g e s _ F R . p r o p e r t i e s messages.properties: t a b l e . h e a d e r . l a s t n a m e = L a s t n a m e t a b l e . h e a d e r . f i r s t n a m e = F i r s t n a m e messages_FR.properties: t a b l e . h e a d e r . l a s t n a m e = N o m t a b l e . h e a d e r . f i r s t n a m e = P r é n o m I18n: example with Spring 88 / 101
t a b l e s : t a b l e i d = " m y T a b l e I d " d a t a = " $ { p e r s o n s } " > . . . < d a t a t a b l e s : c o l u m n t i t l e K e y = " t a b l e . h e a d e r . f i r s t n a m e " . . . / > < d a t a t a b l e s : c o l u m n t i t l e K e y = " t a b l e . h e a d e r . l a s t n a m e " . . . / > . . . < / d a t a t a b l e s : t a b l e > I18n: example with Spring 89 / 101
l e i d = " m y T a b l e I d " d t : t a b l e = " t r u e " > < t h e a d > < t r > . . . < t h t h : t e x t = " # { t a b l e . h e a d e r . f i r s t n a m e } " > F i r s t n a m e < / t h > < t h t h : t e x t = " # { t a b l e . h e a d e r . l a s t n a m e } " > L a s t n a m e < / t h > . . . < / t r > < / t h e a d > . . . < / t a b l e > I18n: example with Spring 90 / 101
e s : t a b l e . . . t h e m e = " b o o t s t r a p 3 " c s s C l a s s = " t a b l e " > < d a t a t a b l e s : c o l u m n p r o p e r t y = " i d " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " f i r s t N a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " l a s t N a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " a d d r e s s . t o w n . n a m e " / > < d a t a t a b l e s : c o l u m n p r o p e r t y = " m a i l " / > < / d a t a t a b l e s : t a b l e > Theming 92 / 101
. d t : t h e m e = " b o o t s t r a p 3 " c l a s s = " t a b l e " > < t h e a d > < t r > < t h > I d < / t h > < t h > F i r s t n a m e < / t h > < t h > L a s t n a m e < / t h > < t h > S t r e e t < / t h > < t h > M a i l < / t h > < / t r > < / t h e a d > < t b o d y > < t r t h : e a c h = " p e r s o n : $ { p e r s o n s } " > < t d t h : t e x t = " $ { p e r s o n ? . i d } " > 1 < / t d > < t d t h : t e x t = " $ { p e r s o n ? . f i r s t N a m e } " > J o h n < / t d > < t d t h : t e x t = " $ { p e r s o n ? . l a s t N a m e } " > D o e < / t d > < t d t h : t e x t = " $ { p e r s o n ? . a d d r e s s ? . t o w n ? . n a m e } " > N o b o d y k n o w s ! < / t d > < t d t h : t e x t = " $ { p e r s o n ? . m a i l } " > j o h n @ d o e . c o m < / t d > < / t r > < / t b o d y > < / t a b l e > Theming 93 / 101
on asset bundles: externalization, configuration via XML, JavaConfig Add new processors for meta-frameworks (CoffeeScript, Less, ...) Add support for conditionnal assets (e.g. IE8+, IE9+) Add support for CSS sprites New A s s e t C a c h e implementation based on Hazelcast JBoss Forge plugin allowing to scaffold a project based on Dandelion Add support for RequireJS Bower integration Future 97 / 101
jEditable, ...) Add support for more DataTables' extensions Add support for DataTables 1.10.0 New theme for Foundation Add WebSocket support for continously-updating tables (Atmosphere, Spring MVC 4) Add support for Spring Data REST Future 98 / 101