Thursday, January 12, 2012

Custom Tags

Our code for showing the date picker (calendar) was terse, but... cryptic.
Javascript in JSP always makes things hard to read and difficult to maintain.

One solution to this is to create Custom Tags.

A Custom Tag allows you to put javascript (or anything else - let us not worry about that for now) inside a Java classe, to create 'tag libraries'.

By referring to these tags, it is possible to simplify the JSP.

For example, we could create a custom tag to encapsulate the javascript we put in for the datepicker, and our JSP would then reduce to this:

 <html>   
<head>
<link type="text/css" rel="Stylesheet" href="../css/jquery-ui-1.8.17.custom.css"/>
<script src="../js/jquery-1.7.1.min.js"></script>
<script src="../js/jquery-ui-1.8.16.custom.min.js"></script>
<script src="../js/jquery.ui.core.js"></script>
<script src="../js/jquery.ui.datepicker.js"></script>
<%@ taglib uri="/WEB-INF/tlds/ConfuciusTags.tld" prefix="confucius" %>
</head>
<body>
<confucius:datetag id="birthdate" label="Enter your birthday"/>
</body>
</html>


Compare this <body> with the JSP in the previous blog.
This one is Cleaner, Readable and Reusable.

Wednesday, January 11, 2012

JQuery UI - Adding CSS

JQuery-UI comes with several stylesheets (themes). Let us add one for 'datepicker'.

Create a folder called 'css' in your web-content folder.

From the JQuery-UI zip, extract the jquery-ui-1.8.17.css (your version number may be different) to the css folder.

Extract the 'images' folder to 'web-content'

In your HelloWorld.jsp, refer to this CSS, so your HelloWorld.jsp will look like this:

 <html>   
        <head>   
           <link type="text/css" rel="Stylesheet" href="../css/jquery-ui-1.8.17.custom.css"/>  
         <script src="../js/jquery-1.7.1.min.js"></script>                  
         <script src="../js/jquery-ui-1.8.16.custom.min.js"></script>                  
         <script src="../js/jquery.ui.core.js"></script>                  
         <script src="../js/jquery.ui.datepicker.js"></script>                  
        </head>   
        <body>   
          <p>Enter your birthday: <input id="datepicker" type="text"></p>  
           <script>  
                $(function() {  
                     $( "#datepicker" ).datepicker();  
                });  
           </script>  
    </body>   
 </html>   


If you rebuild HelloWorld and deploy, the click on the field to enter your birthday, you will see a nicely styled calendar popup.

Note: I had some issues with the CSS because for this example we do not have all the JQuery-UI components, just the datepicker.

So I deleted all the sections in the CSS that referred to other components (if you look at the comments in the CSS you will recognize which section is for which component).

My CSS looks like this:

 /* Component containers  
 ----------------------------------*/  
 .ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }  
 .ui-widget .ui-widget { font-size: 1em; }  
 .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }  
 .ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }  
 .ui-widget-content a { color: #333333; }  
 .ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }  
 .ui-widget-header a { color: #ffffff; }  
   
 /* Interaction states  
 ----------------------------------*/  
 .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }  
 .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }  
 .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }  
 .ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }  
 .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }  
 .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }  
 .ui-widget :active { outline: none; }  
   
 /* Interaction Cues  
 ----------------------------------*/  
 .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }  
 .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }  
 .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }  
 .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }  
 .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }  
 .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }  
 .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }  
 .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }  
   
 /* Icons  
 ----------------------------------*/  
   
 /* states and images */  
 .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }  
 .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }  
 .ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }  
 .ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }  
 .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }  
 .ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }  
 .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }  
 .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }  
   
 /* positioning */  
 .ui-icon-carat-1-n { background-position: 0 0; }  
 .ui-icon-carat-1-ne { background-position: -16px 0; }  
 .ui-icon-carat-1-e { background-position: -32px 0; }  
 .ui-icon-carat-1-se { background-position: -48px 0; }  
 .ui-icon-carat-1-s { background-position: -64px 0; }  
 .ui-icon-carat-1-sw { background-position: -80px 0; }  
 .ui-icon-carat-1-w { background-position: -96px 0; }  
 .ui-icon-carat-1-nw { background-position: -112px 0; }  
 .ui-icon-carat-2-n-s { background-position: -128px 0; }  
 .ui-icon-carat-2-e-w { background-position: -144px 0; }  
 .ui-icon-triangle-1-n { background-position: 0 -16px; }  
 .ui-icon-triangle-1-ne { background-position: -16px -16px; }  
 .ui-icon-triangle-1-e { background-position: -32px -16px; }  
 .ui-icon-triangle-1-se { background-position: -48px -16px; }  
 .ui-icon-triangle-1-s { background-position: -64px -16px; }  
 .ui-icon-triangle-1-sw { background-position: -80px -16px; }  
 .ui-icon-triangle-1-w { background-position: -96px -16px; }  
 .ui-icon-triangle-1-nw { background-position: -112px -16px; }  
 .ui-icon-triangle-2-n-s { background-position: -128px -16px; }  
 .ui-icon-triangle-2-e-w { background-position: -144px -16px; }  
 .ui-icon-arrow-1-n { background-position: 0 -32px; }  
 .ui-icon-arrow-1-ne { background-position: -16px -32px; }  
 .ui-icon-arrow-1-e { background-position: -32px -32px; }  
 .ui-icon-arrow-1-se { background-position: -48px -32px; }  
 .ui-icon-arrow-1-s { background-position: -64px -32px; }  
 .ui-icon-arrow-1-sw { background-position: -80px -32px; }  
 .ui-icon-arrow-1-w { background-position: -96px -32px; }  
 .ui-icon-arrow-1-nw { background-position: -112px -32px; }  
 .ui-icon-arrow-2-n-s { background-position: -128px -32px; }  
 .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }  
 .ui-icon-arrow-2-e-w { background-position: -160px -32px; }  
 .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }  
 .ui-icon-arrowstop-1-n { background-position: -192px -32px; }  
 .ui-icon-arrowstop-1-e { background-position: -208px -32px; }  
 .ui-icon-arrowstop-1-s { background-position: -224px -32px; }  
 .ui-icon-arrowstop-1-w { background-position: -240px -32px; }  
 .ui-icon-arrowthick-1-n { background-position: 0 -48px; }  
 .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }  
 .ui-icon-arrowthick-1-e { background-position: -32px -48px; }  
 .ui-icon-arrowthick-1-se { background-position: -48px -48px; }  
 .ui-icon-arrowthick-1-s { background-position: -64px -48px; }  
 .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }  
 .ui-icon-arrowthick-1-w { background-position: -96px -48px; }  
 .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }  
 .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }  
 .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }  
 .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }  
 .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }  
 .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }  
 .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }  
 .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }  
 .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }  
 .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }  
 .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }  
 .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }  
 .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }  
 .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }  
 .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }  
 .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }  
 .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }  
 .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }  
 .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }  
 .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }  
 .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }  
 .ui-icon-arrow-4 { background-position: 0 -80px; }  
 .ui-icon-arrow-4-diag { background-position: -16px -80px; }  
 .ui-icon-extlink { background-position: -32px -80px; }  
 .ui-icon-newwin { background-position: -48px -80px; }  
 .ui-icon-refresh { background-position: -64px -80px; }  
 .ui-icon-shuffle { background-position: -80px -80px; }  
 .ui-icon-transfer-e-w { background-position: -96px -80px; }  
 .ui-icon-transferthick-e-w { background-position: -112px -80px; }  
 .ui-icon-folder-collapsed { background-position: 0 -96px; }  
 .ui-icon-folder-open { background-position: -16px -96px; }  
 .ui-icon-document { background-position: -32px -96px; }  
 .ui-icon-document-b { background-position: -48px -96px; }  
 .ui-icon-note { background-position: -64px -96px; }  
 .ui-icon-mail-closed { background-position: -80px -96px; }  
 .ui-icon-mail-open { background-position: -96px -96px; }  
 .ui-icon-suitcase { background-position: -112px -96px; }  
 .ui-icon-comment { background-position: -128px -96px; }  
 .ui-icon-person { background-position: -144px -96px; }  
 .ui-icon-print { background-position: -160px -96px; }  
 .ui-icon-trash { background-position: -176px -96px; }  
 .ui-icon-locked { background-position: -192px -96px; }  
 .ui-icon-unlocked { background-position: -208px -96px; }  
 .ui-icon-bookmark { background-position: -224px -96px; }  
 .ui-icon-tag { background-position: -240px -96px; }  
 .ui-icon-home { background-position: 0 -112px; }  
 .ui-icon-flag { background-position: -16px -112px; }  
 .ui-icon-calendar { background-position: -32px -112px; }  
 .ui-icon-cart { background-position: -48px -112px; }  
 .ui-icon-pencil { background-position: -64px -112px; }  
 .ui-icon-clock { background-position: -80px -112px; }  
 .ui-icon-disk { background-position: -96px -112px; }  
 .ui-icon-calculator { background-position: -112px -112px; }  
 .ui-icon-zoomin { background-position: -128px -112px; }  
 .ui-icon-zoomout { background-position: -144px -112px; }  
 .ui-icon-search { background-position: -160px -112px; }  
 .ui-icon-wrench { background-position: -176px -112px; }  
 .ui-icon-gear { background-position: -192px -112px; }  
 .ui-icon-heart { background-position: -208px -112px; }  
 .ui-icon-star { background-position: -224px -112px; }  
 .ui-icon-link { background-position: -240px -112px; }  
 .ui-icon-cancel { background-position: 0 -128px; }  
 .ui-icon-plus { background-position: -16px -128px; }  
 .ui-icon-plusthick { background-position: -32px -128px; }  
 .ui-icon-minus { background-position: -48px -128px; }  
 .ui-icon-minusthick { background-position: -64px -128px; }  
 .ui-icon-close { background-position: -80px -128px; }  
 .ui-icon-closethick { background-position: -96px -128px; }  
 .ui-icon-key { background-position: -112px -128px; }  
 .ui-icon-lightbulb { background-position: -128px -128px; }  
 .ui-icon-scissors { background-position: -144px -128px; }  
 .ui-icon-clipboard { background-position: -160px -128px; }  
 .ui-icon-copy { background-position: -176px -128px; }  
 .ui-icon-contact { background-position: -192px -128px; }  
 .ui-icon-image { background-position: -208px -128px; }  
 .ui-icon-video { background-position: -224px -128px; }  
 .ui-icon-script { background-position: -240px -128px; }  
 .ui-icon-alert { background-position: 0 -144px; }  
 .ui-icon-info { background-position: -16px -144px; }  
 .ui-icon-notice { background-position: -32px -144px; }  
 .ui-icon-help { background-position: -48px -144px; }  
 .ui-icon-check { background-position: -64px -144px; }  
 .ui-icon-bullet { background-position: -80px -144px; }  
 .ui-icon-radio-off { background-position: -96px -144px; }  
 .ui-icon-radio-on { background-position: -112px -144px; }  
 .ui-icon-pin-w { background-position: -128px -144px; }  
 .ui-icon-pin-s { background-position: -144px -144px; }  
 .ui-icon-play { background-position: 0 -160px; }  
 .ui-icon-pause { background-position: -16px -160px; }  
 .ui-icon-seek-next { background-position: -32px -160px; }  
 .ui-icon-seek-prev { background-position: -48px -160px; }  
 .ui-icon-seek-end { background-position: -64px -160px; }  
 .ui-icon-seek-start { background-position: -80px -160px; }  
 /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */  
 .ui-icon-seek-first { background-position: -80px -160px; }  
 .ui-icon-stop { background-position: -96px -160px; }  
 .ui-icon-eject { background-position: -112px -160px; }  
 .ui-icon-volume-off { background-position: -128px -160px; }  
 .ui-icon-volume-on { background-position: -144px -160px; }  
 .ui-icon-power { background-position: 0 -176px; }  
 .ui-icon-signal-diag { background-position: -16px -176px; }  
 .ui-icon-signal { background-position: -32px -176px; }  
 .ui-icon-battery-0 { background-position: -48px -176px; }  
 .ui-icon-battery-1 { background-position: -64px -176px; }  
 .ui-icon-battery-2 { background-position: -80px -176px; }  
 .ui-icon-battery-3 { background-position: -96px -176px; }  
 .ui-icon-circle-plus { background-position: 0 -192px; }  
 .ui-icon-circle-minus { background-position: -16px -192px; }  
 .ui-icon-circle-close { background-position: -32px -192px; }  
 .ui-icon-circle-triangle-e { background-position: -48px -192px; }  
 .ui-icon-circle-triangle-s { background-position: -64px -192px; }  
 .ui-icon-circle-triangle-w { background-position: -80px -192px; }  
 .ui-icon-circle-triangle-n { background-position: -96px -192px; }  
 .ui-icon-circle-arrow-e { background-position: -112px -192px; }  
 .ui-icon-circle-arrow-s { background-position: -128px -192px; }  
 .ui-icon-circle-arrow-w { background-position: -144px -192px; }  
 .ui-icon-circle-arrow-n { background-position: -160px -192px; }  
 .ui-icon-circle-zoomin { background-position: -176px -192px; }  
 .ui-icon-circle-zoomout { background-position: -192px -192px; }  
 .ui-icon-circle-check { background-position: -208px -192px; }  
 .ui-icon-circlesmall-plus { background-position: 0 -208px; }  
 .ui-icon-circlesmall-minus { background-position: -16px -208px; }  
 .ui-icon-circlesmall-close { background-position: -32px -208px; }  
 .ui-icon-squaresmall-plus { background-position: -48px -208px; }  
 .ui-icon-squaresmall-minus { background-position: -64px -208px; }  
 .ui-icon-squaresmall-close { background-position: -80px -208px; }  
 .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }  
 .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }  
 .ui-icon-grip-solid-vertical { background-position: -32px -224px; }  
 .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }  
 .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }  
 .ui-icon-grip-diagonal-se { background-position: -80px -224px; }  
   
   
 /* Misc visuals  
 ----------------------------------*/  
   
 /* Corner radius */  
 .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }  
 .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }  
 .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }  
 .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }  
   
 /* Overlays */  
 .ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }  
 .ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }  
 /*  
  * jQuery UI Datepicker 1.8.17  
  *  
  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)  
  * Dual licensed under the MIT or GPL Version 2 licenses.  
  * http://jquery.org/license  
  *  
  * http://docs.jquery.com/UI/Datepicker#theming  
  */  
 .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }  
 .ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }  
 .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }  
 .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }  
 .ui-datepicker .ui-datepicker-prev { left:2px; }  
 .ui-datepicker .ui-datepicker-next { right:2px; }  
 .ui-datepicker .ui-datepicker-prev-hover { left:1px; }  
 .ui-datepicker .ui-datepicker-next-hover { right:1px; }  
 .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }  
 .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }  
 .ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }  
 .ui-datepicker select.ui-datepicker-month-year {width: 100%;}  
 .ui-datepicker select.ui-datepicker-month,   
 .ui-datepicker select.ui-datepicker-year { width: 49%;}  
 .ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }  
 .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }  
 .ui-datepicker td { border: 0; padding: 1px; }  
 .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }  
 .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }  
 .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }  
 .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }  
   
 /* with multiple calendars */  
 .ui-datepicker.ui-datepicker-multi { width:auto; }  
 .ui-datepicker-multi .ui-datepicker-group { float:left; }  
 .ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }  
 .ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }  
 .ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }  
 .ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }  
 .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }  
 .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }  
 .ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }  
 .ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }  
   
 /* RTL support */  
 .ui-datepicker-rtl { direction: rtl; }  
 .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }  
 .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }  
 .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }  
 .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }  
 .ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }  
 .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }  
 .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }  
 .ui-datepicker-rtl .ui-datepicker-group { float:right; }  
 .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }  
 .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }  
   
 /* IE6 IFRAME FIX (taken from datepicker 1.5.3 */  
 .ui-datepicker-cover {  
   display: none; /*sorry for IE5*/  
   display/**/: block; /*sorry for IE5*/  
   position: absolute; /*must have*/  
   z-index: -1; /*must have*/  
   filter: mask(); /*must have*/  
   top: -4px; /*must have*/  
   left: -4px; /*must have*/  
   width: 200px; /*must have*/  
   height: 200px; /*must have*/  
 }/*  
   

Friday, January 6, 2012

JQuery UI - popup Calendar

We will use JQuery-UI to create a simple popup calendar for picking dates.

Download JQuery-UI from their website. It comes as a zip with lots of things.
All we needs are the following .js files:
jquery-1.7.1.min.js
jquery-ui-1.8.16.custom.min.js
jquery.ui.core.js
jquery.ui.datepicker.js

Copy these files to the /web-content/js folder in your HelloWorld project.

Type (or copy-paste) the following in your HelloWorld.jsp:

 <html>   
        <head>   
         <script src="../js/jquery-1.7.1.min.js"></script>                  
         <script src="../js/jquery-ui-1.8.16.custom.min.js"></script>                  
         <script src="../js/jquery.ui.core.js"></script>                  
         <script src="../js/jquery.ui.datepicker.js"></script>                  
        </head>   
        <body>   
          Enter your birthday: <input id="datepicker" type="text">  
           <script>  
                $(function() {  
                     $( "#datepicker" ).datepicker();  
                });  
           </script>  
    </body>   
 </html>   


Now if you build and deploy HelloWorld and point your browser to:
http://localhost:8080/HelloWorld/jsp/HelloWorld.jsp

You will see a calendar popup when you click on the date field.

JQuery-UI made it possible to create a complex UI effect with a single line of code!

Note that you can easily associate fancy skins with the calendar - we have demonstrated just the bare-bones version.

JQuery - Download

JQuery comes as a single javascript file (jquery.min.js) which you can download from their website. You can include this file in your jsp's head section:
 <script src="jquery-1.7.1.min.js"></script>  

And you are good to go!

JQuery

Writing javascript to create complex UI effects (fading dialog boxes, sliding panels, calendar popups, drag and drops, etc) requires serious coding. And lots of experience with javascript.

Luckily, people have make it easier by creating libraries of javascript methods which allow you to work at a higher level. One of the most popular ones is JQuery.

JQuery has APIs which let you do a lot of DOM manipulation and effects without having to write too much low level code.

More interestingly, people have written even higher level libraries on top of JQuery which create amazing UI effects almost out-of-the-box. For example JQuery-UI comes with dozens of UI controls. Another library called Flot provides interactive charts.

Friday, December 2, 2011

What is a HTTP Session?

From the time you fire the first request from a browser to a server, to the time you shut down the browser - is a single HTTP Session to this server.

All the requests the server received from this browser during this period belong to the same HTTP Session.

If you restart the browser, and send a new request to the server - that would start a new HTTP Session on the server.

If 10 (or n) people are sending requests to the server, then there are 10 (or n) simultaneous HTTP Sessions.

If you have multiple tabs open in your browser, each pointing to a different server, then you have that many HTTP Sessions open on your client side. Each server sees a single HTTP Session from you.

If you have a single tab open in your browser and send requests to multiple servers, you have that many HTTP Sessions open. Each server you sent a request to sees a single HTTP Session from you.

Note that a Login Session is different from a HTTP Session. Suppose I open a browser, login to my bank website, then logout, again login and then logout - and then shut down the browser. I had 2 Login Sessions within a single HTTP Session.

HTTP Sessions are timed out by the server if the administrator has configured an idle period timeout. Login Sessions are timed out by the application. Some internet email and news services allow you to maintain your Login Session over several days, even if you reboot your computer. HTTP Sessions will always end when you close your browser, regardless of the idle timeout set by the administrator.

Stateful HelloWorld

Let us make HellowWorld 'stateful' - i.e. make it maintain some data ("state") between requests.

We will store the exact time a request is received. If the next request is received later than a certain threshold, we can potentially timeout the session. Many websites do this for security.

In this example, we will not actually timeout - we just want to demonstrate how to maintain 'state'.

We will maintain a simple Hashtable which maps the user ID (that we get from the cookie) to the time the request is received.

Here is what HelloWorld looks like now:
 package org.confucius;  

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorld extends HttpServlet {
private static int nextUserId = 0;
private static HashMap<String, Date> requestsTracker = new HashMap<String, Date>();

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String cookieValue = getCookieValue(request.getCookies(), "userId");

if (cookieValue == null) {
cookieValue = String.valueOf(nextUserId);
Cookie userCookie = new Cookie("userId", cookieValue);
response.addCookie(userCookie);
nextUserId++;
}

Date now = new Date();
response.getWriter().write(
"Your last request was received on: "
+ requestsTracker.get(cookieValue) + ", updating to: "
+ now);
requestsTracker.put(cookieValue, now);
}

private String getCookieValue(Cookie[] cookies, String cookieName) {
if (cookies == null)
return null;

for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookieName.equals(cookie.getName()))
return (cookie.getValue());
}
return null;
}
}


Build HelloWorld.war, deploy it, then point your browser to:
http://localhost:8080/HelloWorld/home

Each time you refresh the browser, you will see the time that the last request was received.