add register template; improved message feedback
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 13 Oct 2011 19:02:32 +0000 (13:02 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Thu, 13 Oct 2011 19:02:32 +0000 (13:02 -0600)
12 files changed:
db/schema.sql
lib/Chatty/Controller/Root.pm
root/static/css/common.css
root/static/css/validationEngine.jquery.css [new file with mode: 0755]
root/static/img/info.png [new file with mode: 0644]
root/static/img/warning.png [new file with mode: 0644]
root/static/js/jquery.validationEngine-2.2.1.min.js [new file with mode: 0644]
root/static/js/jquery.validationEngine-en.js [new file with mode: 0644]
root/tt/index.tt
root/tt/login.tt
root/tt/register.tt [new file with mode: 0644]
root/tt/wrapper.tt

index 0b8a7104b91534d25e9344df343a33fbd7f166c5..7fd9824cf3e213289c8d5858dcc24ca041ae5e73 100644 (file)
@@ -2,14 +2,15 @@
 PRAGMA foreign_keys = ON;
 
 CREATE TABLE account (
-       id                              INTEGER PRIMARY KEY,
-       username        TEXT,
-       password        TEXT,
+       id              INTEGER PRIMARY KEY,
+       email           TEXT,
+       username        TEXT UNIQUE,
+       password        TEXT NOT NULL,
        status          TEXT DEFAULT 'active'
 );
 
 CREATE TABLE message (
-       id                              INTEGER PRIMARY KEY,
+       id              INTEGER PRIMARY KEY,
        posted          TIMESTAMP,
        author          INTEGER REFERENCES account(id),
        content         TEXT
index f3e5030b2a82b34e825482da718b92d6eecc8f2a..14aef8799fc1ae8628c54dffd5818b414654e5b6 100644 (file)
@@ -72,6 +72,15 @@ sub logout :Local :Args(0) {
        $c->response->redirect($c->uri_for('/'));
 }
 
+=head2 register
+
+Register a new account.
+
+=cut
+
+sub register :Local :Args(0) {
+}
+
 =head2 default
 
 Standard 404 error page
index dec13c438a48bb275922f9d30eb449b19f4b78d7..ff89b5b6774fbf8ac726a2936b43eb29ad32de8f 100644 (file)
@@ -22,6 +22,11 @@ a:hover {
        border-bottom: 1px dotted blue;
 }
 
+label {
+       width: 100px;
+       float: left;
+}
+
 
 .left {
        float: left;
@@ -52,6 +57,10 @@ a:hover {
        font-size: 1.3em;
 }
 
+#inner h2 {
+       font-size: 1.2em;
+}
+
 #footer {
        padding: 0;
        height: 31px;
@@ -60,18 +69,48 @@ a:hover {
 }
 
 #error {
+       line-height: 24px;
        margin: 5px;
-       padding: 10px;
+       padding: 10px 0 10px 44px;
        border: 2px solid black;
-       background: white;
+       background: white url('../img/warning.png') 10px 50% no-repeat;
+       display: none;
+       cursor: pointer;
        color: red;
        font-weight: bold;
 }
 
 #message {
+       line-height: 24px;
        margin: 5px;
-       padding: 10px;
+       padding: 10px 0 10px 44px;
        border: 2px solid black;
-       background: white;
+       background: white url('../img/info.png') 10px 50% no-repeat;
+       display: none;
+       cursor: pointer;
+}
+
+/* error message */
+.error {
+       /* supply height to ensure consistent positioning for every browser */
+       height:15px;
+       background-color:#FFFE36;
+       border:1px solid #E1E16D;
+       font-size:11px;
+       color:#000;
+       padding:3px 10px;
+       margin-left:-2px;
+
+
+       /* CSS3 spicing for mozilla and webkit */
+       -moz-border-radius:4px;
+       -webkit-border-radius:4px;
+       -moz-border-radius-bottomleft:0;
+       -moz-border-radius-topleft:0;
+       -webkit-border-bottom-left-radius:0;
+       -webkit-border-top-left-radius:0;
+
+       -moz-box-shadow:0 0 6px #ddd;
+       -webkit-box-shadow:0 0 6px #ddd;
 }
 
diff --git a/root/static/css/validationEngine.jquery.css b/root/static/css/validationEngine.jquery.css
new file mode 100755 (executable)
index 0000000..5500bee
--- /dev/null
@@ -0,0 +1,142 @@
+.inputContainer {\r
+       position: relative;\r
+       float: left;\r
+}\r
+\r
+.formError {\r
+       position: absolute;\r
+       top: 300px;\r
+       left: 300px;\r
+       display: block;\r
+       z-index: 5000;\r
+       cursor: pointer;\r
+}\r
+\r
+.ajaxSubmit {\r
+       padding: 20px;\r
+       background: #55ea55;\r
+       border: 1px solid #999;\r
+       display: none\r
+}\r
+\r
+.formError .formErrorContent {\r
+       width: 100%;\r
+       background: #ee0101;\r
+       position:relative;\r
+       z-index:5001;\r
+       color: #fff;\r
+       width: 150px;\r
+       font-family: tahoma;\r
+       font-size: 11px;\r
+       border: 2px solid #ddd;\r
+       box-shadow: 0 0 6px #000;\r
+       -moz-box-shadow: 0 0 6px #000;\r
+       -webkit-box-shadow: 0 0 6px #000;\r
+       padding: 4px 10px 4px 10px;\r
+       border-radius: 6px;\r
+       -moz-border-radius: 6px;\r
+       -webkit-border-radius: 6px;\r
+}\r
+\r
+.greenPopup .formErrorContent {\r
+       background: #33be40;\r
+}\r
+\r
+.blackPopup .formErrorContent {\r
+       background: #393939;\r
+       color: #FFF;\r
+}\r
+\r
+.formError .formErrorArrow {\r
+       width: 15px;\r
+       margin: -2px 0 0 13px;\r
+  position:relative;\r
+  z-index: 5006;\r
+}\r
+\r
+.formError .formErrorArrowBottom {\r
+  box-shadow: none;\r
+  -moz-box-shadow: none;\r
+  -webkit-box-shadow: none;\r
+       margin: 0px 0 0 12px;\r
+  top:2px;\r
+}\r
+\r
+.formError .formErrorArrow div {\r
+       border-left: 2px solid #ddd;\r
+       border-right: 2px solid #ddd;\r
+       box-shadow: 0 2px 3px #444;\r
+       -moz-box-shadow: 0 2px 3px #444;\r
+       -webkit-box-shadow: 0 2px 3px #444;\r
+       font-size: 0px;\r
+       height: 1px;\r
+       background: #ee0101;\r
+       margin: 0 auto;\r
+       line-height: 0;\r
+       font-size: 0;\r
+       display: block;\r
+}\r
+\r
+.formError .formErrorArrowBottom div {\r
+  box-shadow: none;\r
+  -moz-box-shadow: none;\r
+  -webkit-box-shadow: none;\r
+}\r
+\r
+.greenPopup .formErrorArrow div {\r
+       background: #33be40;\r
+}\r
+\r
+.blackPopup .formErrorArrow div {\r
+       background: #393939;\r
+       color: #FFF;\r
+}\r
+\r
+.formError .formErrorArrow .line10 {\r
+       width: 15px;\r
+       border: none;\r
+}\r
+\r
+.formError .formErrorArrow .line9 {\r
+       width: 13px;\r
+       border: none;\r
+}\r
+\r
+.formError .formErrorArrow .line8 {\r
+       width: 11px;\r
+}\r
+\r
+.formError .formErrorArrow .line7 {\r
+       width: 9px;\r
+}\r
+\r
+.formError .formErrorArrow .line6 {\r
+       width: 7px;\r
+}\r
+\r
+.formError .formErrorArrow .line5 {\r
+       width: 5px;\r
+}\r
+\r
+.formError .formErrorArrow .line4 {\r
+       width: 3px;\r
+}\r
+\r
+.formError .formErrorArrow .line3 {\r
+       width: 1px;\r
+       border-left: 2px solid #ddd;\r
+       border-right: 2px solid #ddd;\r
+       border-bottom: 0 solid #ddd;\r
+}\r
+\r
+.formError .formErrorArrow .line2 {\r
+       width: 3px;\r
+       border: none;\r
+       background: #ddd;\r
+}\r
+\r
+.formError .formErrorArrow .line1 {\r
+       width: 1px;\r
+       border: none;\r
+       background: #ddd;\r
+}
diff --git a/root/static/img/info.png b/root/static/img/info.png
new file mode 100644 (file)
index 0000000..5c34bf7
Binary files /dev/null and b/root/static/img/info.png differ
diff --git a/root/static/img/warning.png b/root/static/img/warning.png
new file mode 100644 (file)
index 0000000..7f6e44a
Binary files /dev/null and b/root/static/img/warning.png differ
diff --git a/root/static/js/jquery.validationEngine-2.2.1.min.js b/root/static/js/jquery.validationEngine-2.2.1.min.js
new file mode 100644 (file)
index 0000000..4a2a9c9
--- /dev/null
@@ -0,0 +1 @@
+(function(b){var a={init:function(c){var d=this;if(!d.data("jqv")||d.data("jqv")==null){a._saveOptions(d,c);b(".formError").live("click",function(){b(this).fadeOut(150,function(){b(this).remove()})})}},attach:function(f){var e=this;var d;if(f){d=a._saveOptions(e,f)}else{d=e.data("jqv")}var c=(e.find("[data-validation-engine*=validate]"))?"data-validation-engine":"class";if(!d.binded){if(d.bindMethod=="bind"){e.find("[class*=validate]").not("[type=checkbox]").not("[type=radio]").not(".datepicker").bind(d.validationEventTrigger,a._onFieldEvent);e.find("[class*=validate][type=checkbox],[class*=validate][type=radio]").bind("click",a._onFieldEvent);e.find("[class*=validate][class*=datepicker]").bind(d.validationEventTrigger,{delay:300},a._onFieldEvent);e.bind("submit",a._onSubmitEvent)}else{if(d.bindMethod=="live"){e.find("[class*=validate]").not("[type=checkbox]").not(".datepicker").live(d.validationEventTrigger,a._onFieldEvent);e.find("[class*=validate][type=checkbox]").live("click",a._onFieldEvent);e.find("[class*=validate][class*=datepicker]").live(d.validationEventTrigger,{delay:300},a._onFieldEvent);e.live("submit",a._onSubmitEvent)}}d.binded=true}return this},detach:function(){var d=this;var c=d.data("jqv");if(c.binded){d.find("[class*=validate]").not("[type=checkbox]").unbind(c.validationEventTrigger,a._onFieldEvent);d.find("[class*=validate][type=checkbox],[class*=validate][type=radio]").unbind("click",a._onFieldEvent);d.unbind("submit",a.onAjaxFormComplete);d.find("[class*=validate]").not("[type=checkbox]").die(c.validationEventTrigger,a._onFieldEvent);d.find("[class*=validate][type=checkbox]").die("click",a._onFieldEvent);d.die("submit",a.onAjaxFormComplete);d.removeData("jqv")}},validate:function(){return a._validateFields(this)},validateField:function(d){var c=b(this).data("jqv");return a._validateField(b(d),c)},validateform:function(){return a._onSubmitEvent.call(this)},updatePromptsPosition:function(){var d=this.closest("form");var c=d.data("jqv");d.find("[class*=validate]").not(":hidden").not(":disabled").each(function(){var g=b(this);var e=a._getPrompt(g);var f=b(e).find(".formErrorContent").html();if(e){a._updatePrompt(g,b(e),f,undefined,false,c)}})},showPrompt:function(d,f,h,e){var g=this.closest("form");var c=g.data("jqv");if(!c){c=a._saveOptions(this,c)}if(h){c.promptPosition=h}c.showArrow=e==true;a._showPrompt(this,d,f,false,c)},hidePrompt:function(){var c="."+a._getClassName(b(this).attr("id"))+"formError";b(c).fadeTo("fast",0.3,function(){b(this).remove()})},hide:function(){var c;if(b(this).is("form")){c="parentForm"+b(this).attr("id")}else{c=b(this).attr("id")+"formError"}b("."+c).fadeTo("fast",0.3,function(){b(this).remove()})},hideAll:function(){b(".formError").fadeTo("fast",0.3,function(){b(this).remove()})},_onFieldEvent:function(e){var f=b(this);var d=f.closest("form");var c=d.data("jqv");window.setTimeout(function(){a._validateField(f,c)},(e.data)?e.data.delay:0)},_onSubmitEvent:function(){var e=b(this);var c=e.data("jqv");var d=a._validateFields(e,true);if(d&&c.ajaxFormValidation){a._validateFormWithAjax(e,c);return false}if(c.onValidationComplete){c.onValidationComplete(e,d);return false}return d},_checkAjaxStatus:function(d){var c=true;b.each(d.ajaxValidCache,function(e,f){if(!f){c=false;return false}});return c},_validateFields:function(f,p){var q=f.data("jqv");var g=false;f.trigger("jqv.form.validating");f.find("[class*=validate]").not(":hidden").not(":disabled").each(function(){var d=b(this);g|=a._validateField(d,q,p)});f.trigger("jqv.form.result",[g]);if(g){if(q.scroll){var o=Number.MAX_VALUE;var j=0;var l=b(".formError:not('.greenPopup')");for(var k=0;k<l.length;k++){var m=b(l[k]).offset().top;if(m<o){o=m;j=b(l[k]).offset().left}}if(!q.isOverflown){b("html:not(:animated),body:not(:animated)").animate({scrollTop:o,scrollLeft:j},1100)}else{var c=b(q.overflownDIV);var e=c.scrollTop();var h=-parseInt(c.offset().top);o+=e+h-5;var n=b(q.overflownDIV+":not(:animated)");n.animate({scrollTop:o},1100);b("html:not(:animated),body:not(:animated)").animate({scrollTop:c.offset().top,scrollLeft:j},1100)}}return false}return true},_validateFormWithAjax:function(e,d){var f=e.serialize();var c=(d.ajaxFormValidationURL)?d.ajaxFormValidationURL:e.attr("action");b.ajax({type:"GET",url:c,cache:false,dataType:"json",data:f,form:e,methods:a,options:d,beforeSend:function(){return d.onBeforeAjaxFormValidation(e,d)},error:function(g,h){a._ajaxError(g,h)},success:function(l){if(l!==true){var j=false;for(var k=0;k<l.length;k++){var m=l[k];var o=m[0];var h=b(b("#"+o)[0]);if(h.length==1){var n=m[2];if(m[1]==true){if(n==""||!n){a._closePrompt(h)}else{if(d.allrules[n]){var g=d.allrules[n].alertTextOk;if(g){n=g}}a._showPrompt(h,n,"pass",false,d,true)}}else{j|=true;if(d.allrules[n]){var g=d.allrules[n].alertText;if(g){n=g}}a._showPrompt(h,n,"",false,d,true)}}}d.onAjaxFormComplete(!j,e,l,d)}else{d.onAjaxFormComplete(true,e,"",d)}}})},_validateField:function(o,t,p){if(!o.attr("id")){b.error("jQueryValidate: an ID attribute is required for this field: "+o.attr("name")+" class:"+o.attr("class"))}var s=o.attr("class");var j=/validate\[(.*)\]/.exec(s);if(!j){return false}var n=j[1];var r=n.split(/\[|,|\]/);var e=false;var q=o.attr("name");var c="";var m=false;t.isError=false;t.showArrow=true;for(var h=0;h<r.length;h++){var l=undefined;switch(r[h]){case"required":m=true;l=a._required(o,r,h,t);break;case"custom":l=a._customRegex(o,r,h,t);break;case"groupRequired":var d="[class*="+r[h+1]+"]";var g=o.closest("form").find(d).eq(0);if(g[0]!=o[0]){a._validateField(g,t,p);t.showArrow=true;continue}l=a._groupRequired(o,r,h,t);if(l){m=true}t.showArrow=false;break;case"ajax":if(!p){a._ajax(o,r,h,t);e=true}break;case"minSize":l=a._minSize(o,r,h,t);break;case"maxSize":l=a._maxSize(o,r,h,t);break;case"min":l=a._min(o,r,h,t);break;case"max":l=a._max(o,r,h,t);break;case"past":l=a._past(o,r,h,t);break;case"future":l=a._future(o,r,h,t);break;case"dateRange":var d="[class*="+r[h+1]+"]";var g=o.closest("form").find(d).eq(0);var f=o.closest("form").find(d).eq(1);if(g[0].value||f[0].value){l=a._dateRange(g,f,r,h,t)}if(l){m=true}t.showArrow=false;break;case"dateTimeRange":var d="[class*="+r[h+1]+"]";var g=o.closest("form").find(d).eq(0);var f=o.closest("form").find(d).eq(1);if(g[0].value||f[0].value){l=a._dateTimeRange(g,f,r,h,t)}if(l){m=true}t.showArrow=false;break;case"maxCheckbox":l=a._maxCheckbox(o,r,h,t);o=b(b("input[name='"+q+"']"));break;case"minCheckbox":l=a._minCheckbox(o,r,h,t);o=b(b("input[name='"+q+"']"));break;case"equals":l=a._equals(o,r,h,t);break;case"funcCall":l=a._funcCall(o,r,h,t);break;default:}if(l!==undefined){c+=l+"<br/>";t.isError=true}}if(!m){if(o.val()==""){t.isError=false}}var k=o.attr("type");if((k=="radio"||k=="checkbox")&&b("input[name='"+q+"']").size()>1){o=b(b("input[name='"+q+"'][type!=hidden]:first"));t.showArrow=false}if(k=="text"&&b("input[name='"+q+"']").size()>1){o=b(b("input[name='"+q+"'][type!=hidden]:first"));t.showArrow=false}if(t.isError){a._showPrompt(o,c,"",false,t)}else{if(!e){a._closePrompt(o)}}o.trigger("jqv.field.result",[o,t.isError,c]);return t.isError},_required:function(f,g,e,d){switch(f.attr("type")){case"text":case"password":case"textarea":case"file":default:if(!f.val()){return d.allrules[g[e]].alertText}break;case"radio":case"checkbox":var c=f.attr("name");if(b("input[name='"+c+"']:checked").size()==0){if(b("input[name='"+c+"']").size()==1){return d.allrules[g[e]].alertTextCheckboxe}else{return d.allrules[g[e]].alertTextCheckboxMultiple}}break;case"select-one":if(!f.val()){return d.allrules[g[e]].alertText}break;case"select-multiple":if(!f.find("option:selected").val()){return d.allrules[g[e]].alertText}break}},_groupRequired:function(f,h,d,c){var g="[class*="+h[d+1]+"]";var e=false;f.closest("form").find(g).each(function(){if(!a._required(b(this),h,d,c)){e=true;return false}});if(!e){return c.allrules[h[d]].alertText}},_customRegex:function(j,k,f,d){var c=k[f+1];var h=d.allrules[c];if(!h){alert("jqv:custom rule not found "+c);return}var e=h.regex;if(!e){alert("jqv:custom regex not found "+c);return}var g=new RegExp(e);if(!g.test(j.val())){return d.allrules[c].alertText}},_funcCall:function(g,h,d,c){var f=h[d+1];var e=window[f];if(typeof(e)=="function"){return e(g,h,d,c)}},_equals:function(f,g,e,d){var c=g[e+1];if(f.val()!=b("#"+c).val()){return d.allrules.equals.alertText}},_maxSize:function(h,j,f,e){var d=j[f+1];var c=h.val().length;if(c>d){var g=e.allrules.maxSize;return g.alertText+d+g.alertText2}},_minSize:function(h,j,f,d){var e=j[f+1];var c=h.val().length;if(c<e){var g=d.allrules.minSize;return g.alertText+e+g.alertText2}},_min:function(h,j,f,d){var e=parseFloat(j[f+1]);var c=parseFloat(h.val());if(c<e){var g=d.allrules.min;if(g.alertText2){return g.alertText+e+g.alertText2}return g.alertText+e}},_max:function(h,j,f,e){var d=parseFloat(j[f+1]);var c=parseFloat(h.val());if(c>d){var g=e.allrules.max;if(g.alertText2){return g.alertText+d+g.alertText2}return g.alertText+d}},_past:function(j,k,e,c){var h=k[e+1];var d=(h.toLowerCase()=="now")?new Date():a._parseDate(h);var f=a._parseDate(j.val());if(f<d){var g=c.allrules.past;if(g.alertText2){return g.alertText+a._dateToString(d)+g.alertText2}return g.alertText+a._dateToString(d)}},_future:function(j,k,e,c){var h=k[e+1];var d=(h.toLowerCase()=="now")?new Date():a._parseDate(h);var f=a._parseDate(j.val());if(f>d){var g=c.allrules.future;if(g.alertText2){return g.alertText+a._dateToString(d)+g.alertText2}return g.alertText+a._dateToString(d)}},_isDate:function(d){var c=new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/);if(c.test(d)){return true}return false},_isDateTime:function(d){var c=new RegExp(/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/);if(c.test(d)){return true}return false},_dateCompare:function(d,c){return(new Date(d.toString())<new Date(c.toString()))},_dateRange:function(g,d,f,e,c){if((!g[0].value&&d[0].value)||(g[0].value&&!d[0].value)){return c.allrules[f[e]].alertText+c.allrules[f[e]].alertText2}if(!a._isDate(g[0].value)||!a._isDate(d[0].value)){return c.allrules[f[e]].alertText+c.allrules[f[e]].alertText2}if(!a._dateCompare(g[0].value,d[0].value)){return c.allrules[f[e]].alertText+c.allrules[f[e]].alertText2}},_dateTimeRange:function(g,d,f,e,c){if((!g[0].value&&d[0].value)||(g[0].value&&!d[0].value)){return c.allrules[f[e]].alertText+c.allrules[f[e]].alertText2}if(!a._isDateTime(g[0].value)||!a._isDateTime(d[0].value)){return c.allrules[f[e]].alertText+c.allrules[f[e]].alertText2}if(!a._dateCompare(g[0].value,d[0].value)){return c.allrules[f[e]].alertText+c.allrules[f[e]].alertText2}},_maxCheckbox:function(h,j,g,f){var d=j[g+1];var e=h.attr("name");var c=b("input[name='"+e+"']:checked").size();if(c>d){f.showArrow=false;if(f.allrules.maxCheckbox.alertText2){return f.allrules.maxCheckbox.alertText+" "+d+" "+f.allrules.maxCheckbox.alertText2}return f.allrules.maxCheckbox.alertText}},_minCheckbox:function(h,j,g,f){var d=j[g+1];var e=h.attr("name");var c=b("input[name='"+e+"']:checked").size();if(c<d){f.showArrow=false;return f.allrules.minCheckbox.alertText+" "+d+" "+f.allrules.minCheckbox.alertText2}},_ajax:function(m,o,h,p){var n=o[h+1];var l=p.allrules[n];var e=l.extraData;var j=l.extraDataDynamic;if(!e){e=""}if(j){var g=[];var k=String(j).split(",");for(var h=0;h<k.length;h++){var c=k[h];if(b(c).length){var d=m.closest("form").find(c).val();var f=c.replace("#","")+"="+escape(d);g.push(f)}}j=g.join("&")}else{j=""}if(!p.isError){b.ajax({type:"GET",url:l.url,cache:false,dataType:"json",data:"fieldId="+m.attr("id")+"&fieldValue="+m.val()+"&extraData="+e+"&"+j,field:m,rule:l,methods:a,options:p,beforeSend:function(){var i=l.alertTextLoad;if(i){a._showPrompt(m,i,"load",true,p)}},error:function(i,q){a._ajaxError(i,q)},success:function(s){var u=s[0];var r=b(b("#"+u)[0]);if(r.length==1){var q=s[1];var t=s[2];if(!q){p.ajaxValidCache[u]=false;p.isError=true;if(t){if(p.allrules[t]){var i=p.allrules[t].alertText;if(i){t=i}}}else{t=l.alertText}a._showPrompt(r,t,"",true,p)}else{if(p.ajaxValidCache[u]!==undefined){p.ajaxValidCache[u]=true}if(t){if(p.allrules[t]){var i=p.allrules[t].alertTextOk;if(i){t=i}}}else{t=l.alertTextOk}if(t){a._showPrompt(r,t,"pass",true,p)}else{a._closePrompt(r)}}}}})}},_ajaxError:function(c,d){if(c.status==0&&d==null){alert("The page is not served from a server! ajax call failed")}else{if(typeof console!="undefined"){console.log("Ajax error: "+c.status+" "+d)}}},_dateToString:function(c){return c.getFullYear()+"-"+(c.getMonth()+1)+"-"+c.getDate()},_parseDate:function(e){var c=e.split("-");if(c==e){c=e.split("/")}return new Date(c[0],(c[1]-1),c[2])},_showPrompt:function(i,g,h,f,e,d){var c=a._getPrompt(i);if(d){c=false}if(c){a._updatePrompt(i,c,g,h,f,e)}else{a._buildPrompt(i,g,h,f,e)}},_buildPrompt:function(g,c,e,i,j){var d=b("<div>");d.addClass(a._getClassName(g.attr("id"))+"formError");if(g.is(":input")){d.addClass("parentForm"+a._getClassName(g.parents("form").attr("id")))}d.addClass("formError");switch(e){case"pass":d.addClass("greenPopup");break;case"load":d.addClass("blackPopup")}if(i){d.addClass("ajaxed")}var k=b("<div>").addClass("formErrorContent").html(c).appendTo(d);if(j.showArrow){var h=b("<div>").addClass("formErrorArrow");switch(j.promptPosition){case"bottomLeft":case"bottomRight":d.find(".formErrorContent").before(h);h.addClass("formErrorArrowBottom").html('<div class="line1"><!-- --></div><div class="line2"><!-- --></div><div class="line3"><!-- --></div><div class="line4"><!-- --></div><div class="line5"><!-- --></div><div class="line6"><!-- --></div><div class="line7"><!-- --></div><div class="line8"><!-- --></div><div class="line9"><!-- --></div><div class="line10"><!-- --></div>');break;case"topLeft":case"topRight":h.html('<div class="line10"><!-- --></div><div class="line9"><!-- --></div><div class="line8"><!-- --></div><div class="line7"><!-- --></div><div class="line6"><!-- --></div><div class="line5"><!-- --></div><div class="line4"><!-- --></div><div class="line3"><!-- --></div><div class="line2"><!-- --></div><div class="line1"><!-- --></div>');d.append(h);break}}if(j.isOverflown){g.before(d)}else{b("body").append(d)}var f=a._calculatePosition(g,d,j);d.css({top:f.callerTopPosition,left:f.callerleftPosition,marginTop:f.marginTopSize,opacity:0});return d.animate({opacity:0.87})},_updatePrompt:function(h,c,f,g,e,d){if(c){if(g=="pass"){c.addClass("greenPopup")}else{c.removeClass("greenPopup")}if(g=="load"){c.addClass("blackPopup")}else{c.removeClass("blackPopup")}if(e){c.addClass("ajaxed")}else{c.removeClass("ajaxed")}c.find(".formErrorContent").html(f);var i=a._calculatePosition(h,c,d);c.animate({top:i.callerTopPosition,left:i.callerleftPosition,marginTop:i.marginTopSize})}},_closePrompt:function(d){var c=a._getPrompt(d);if(c){c.fadeTo("fast",0,function(){c.remove()})}},closePrompt:function(c){return a._closePrompt(c)},_getPrompt:function(e){var d=e.attr("id").replace(":","_")+"formError";var c=b("."+a._escapeExpression(d))[0];if(c){return b(c)}},_escapeExpression:function(c){return c.replace(/([#;&,\.\+\*\~':"\!\^$\[\]\(\)=>\|])/g,"\\$1")},_calculatePosition:function(i,e,l){var c,j,h;var g=i.width();var k=e.height();var d=l.isOverflown;if(d){c=j=0;h=-k}else{var f=i.offset();c=f.top;j=f.left;h=0}switch(l.promptPosition){default:case"topRight":if(d){j+=g-30}else{j+=g-30;c+=-k-2}break;case"topLeft":c+=-k-10;break;case"centerRight":j+=g+13;break;case"bottomLeft":c=c+i.height()+15;break;case"bottomRight":j+=g-30;c+=i.height()+5}return{callerTopPosition:c+"px",callerleftPosition:j+"px",marginTopSize:h+"px"}},_saveOptions:function(e,d){if(b.validationEngineLanguage){var c=b.validationEngineLanguage.allRules}else{b.error("jQuery.validationEngine rules are not loaded, plz add localization files to the page")}b.validationEngine.defaults.allrules=c;var f=b.extend({},b.validationEngine.defaults,d);e.data("jqv",f);return f},_getClassName:function(c){return c.replace(":","_").replace(".","_")}};b.fn.validationEngine=function(d){var c=b(this);if(!c[0]){return false}if(typeof(d)=="string"&&d.charAt(0)!="_"&&a[d]){if(d!="showPrompt"&&d!="hidePrompt"&&d!="hide"&&d!="hideAll"){a.init.apply(c)}return a[d].apply(c,Array.prototype.slice.call(arguments,1))}else{if(typeof d=="object"||!d){a.init.apply(c,arguments);return a.attach.apply(c)}else{b.error("Method "+d+" does not exist in jQuery.validationEngine")}}};b.validationEngine={defaults:{validationEventTrigger:"blur",scroll:true,promptPosition:"topRight",bindMethod:"bind",inlineAjax:false,ajaxFormValidation:false,ajaxFormValidationURL:false,onAjaxFormComplete:b.noop,onBeforeAjaxFormValidation:b.noop,onValidationComplete:false,isOverflown:false,overflownDIV:"",binded:false,showArrow:true,isError:false,ajaxValidCache:{}}}})(jQuery);
\ No newline at end of file
diff --git a/root/static/js/jquery.validationEngine-en.js b/root/static/js/jquery.validationEngine-en.js
new file mode 100644 (file)
index 0000000..2a2b70f
--- /dev/null
@@ -0,0 +1,167 @@
+(function($){\r
+    $.fn.validationEngineLanguage = function(){\r
+    };\r
+    $.validationEngineLanguage = {\r
+        newLang: function(){\r
+            $.validationEngineLanguage.allRules = {\r
+                "required": { // Add your regex rules here, you can take telephone as an example\r
+                    "regex": "none",\r
+                    "alertText": "* This field is required",\r
+                    "alertTextCheckboxMultiple": "* Please select an option",\r
+                    "alertTextCheckboxe": "* This checkbox is required",\r
+                    "alertTextDateRange": "* Both date range fields are required"\r
+                },\r
+                "dateRange": {\r
+                    "regex": "none",\r
+                    "alertText": "* Invalid ",\r
+                    "alertText2": "Date Range"\r
+                },\r
+                "dateTimeRange": {\r
+                    "regex": "none",\r
+                    "alertText": "* Invalid ",\r
+                    "alertText2": "Date Time Range"\r
+                },\r
+                "minSize": {\r
+                    "regex": "none",\r
+                    "alertText": "* Minimum ",\r
+                    "alertText2": " characters allowed"\r
+                },\r
+                "maxSize": {\r
+                    "regex": "none",\r
+                    "alertText": "* Maximum ",\r
+                    "alertText2": " characters allowed"\r
+                },\r
+                               "groupRequired": {\r
+                    "regex": "none",\r
+                    "alertText": "* You must fill one of the following fields"\r
+                },\r
+                "min": {\r
+                    "regex": "none",\r
+                    "alertText": "* Minimum value is "\r
+                },\r
+                "max": {\r
+                    "regex": "none",\r
+                    "alertText": "* Maximum value is "\r
+                },\r
+                "past": {\r
+                    "regex": "none",\r
+                    "alertText": "* Date prior to "\r
+                },\r
+                "future": {\r
+                    "regex": "none",\r
+                    "alertText": "* Date past "\r
+                },     \r
+                "maxCheckbox": {\r
+                    "regex": "none",\r
+                    "alertText": "* Maximum ",\r
+                    "alertText2": " options allowed"\r
+                },\r
+                "minCheckbox": {\r
+                    "regex": "none",\r
+                    "alertText": "* Please select ",\r
+                    "alertText2": " options"\r
+                },\r
+                "equals": {\r
+                    "regex": "none",\r
+                    "alertText": "* Fields do not match"\r
+                },\r
+                "phone": {\r
+                    // credit: jquery.h5validate.js / orefalo\r
+                    "regex": /^([\+][0-9]{1,3}[ \.\-])?([\(]{1}[0-9]{2,6}[\)])?([0-9 \.\-\/]{3,20})((x|ext|extension)[ ]?[0-9]{1,4})?$/,\r
+                    "alertText": "* Invalid phone number"\r
+                },\r
+                "email": {\r
+                    // Shamelessly lifted from Scott Gonzalez via the Bassistance Validation plugin http://projects.scottsplayground.com/email_address_validation/\r
+                    "regex": /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i,\r
+                    "alertText": "* Invalid email address"\r
+                },\r
+                "integer": {\r
+                    "regex": /^[\-\+]?\d+$/,\r
+                    "alertText": "* Not a valid integer"\r
+                },\r
+                "number": {\r
+                    // Number, including positive, negative, and floating decimal. credit: orefalo\r
+                    "regex": /^[\-\+]?(([0-9]+)([\.,]([0-9]+))?|([\.,]([0-9]+))?)$/,\r
+                    "alertText": "* Invalid floating decimal number"\r
+                },\r
+                "date": {\r
+                    "regex": /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/,\r
+                    "alertText": "* Invalid date, must be in YYYY-MM-DD format"\r
+                },\r
+                "ipv4": {\r
+                    "regex": /^((([01]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))[.]){3}(([0-1]?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5]))$/,\r
+                    "alertText": "* Invalid IP address"\r
+                },\r
+                "url": {\r
+                    "regex": /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,\r
+                    "alertText": "* Invalid URL"\r
+                },\r
+                "onlyNumberSp": {\r
+                    "regex": /^[0-9\ ]+$/,\r
+                    "alertText": "* Numbers only"\r
+                },\r
+                "onlyLetterSp": {\r
+                    "regex": /^[a-zA-Z\ \']+$/,\r
+                    "alertText": "* Letters only"\r
+                },\r
+                "onlyLetterNumber": {\r
+                    "regex": /^[0-9a-zA-Z]+$/,\r
+                    "alertText": "* No special characters allowed"\r
+                },\r
+                // --- CUSTOM RULES -- Those are specific to the demos, they can be removed or changed to your likings\r
+                "ajaxUserCall": {\r
+                    "url": "ajaxValidateFieldUser",\r
+                    // you may want to pass extra data on the ajax call\r
+                    "extraData": "name=eric",\r
+                    "alertText": "* This user is already taken",\r
+                    "alertTextLoad": "* Validating, please wait"\r
+                },\r
+                               "ajaxUserCallPhp": {\r
+                    "url": "phpajax/ajaxValidateFieldUser.php",\r
+                    // you may want to pass extra data on the ajax call\r
+                    "extraData": "name=eric",\r
+                    // if you provide an "alertTextOk", it will show as a green prompt when the field validates\r
+                    "alertTextOk": "* This username is available",\r
+                    "alertText": "* This user is already taken",\r
+                    "alertTextLoad": "* Validating, please wait"\r
+                },\r
+                "ajaxNameCall": {\r
+                    // remote json service location\r
+                    "url": "ajaxValidateFieldName",\r
+                    // error\r
+                    "alertText": "* This name is already taken",\r
+                    // if you provide an "alertTextOk", it will show as a green prompt when the field validates\r
+                    "alertTextOk": "* This name is available",\r
+                    // speaks by itself\r
+                    "alertTextLoad": "* Validating, please wait"\r
+                },\r
+                                "ajaxNameCallPhp": {\r
+                           // remote json service location\r
+                           "url": "phpajax/ajaxValidateFieldName.php",\r
+                           // error\r
+                           "alertText": "* This name is already taken",\r
+                           // speaks by itself\r
+                           "alertTextLoad": "* Validating, please wait"\r
+                       },\r
+                "validate2fields": {\r
+                    "alertText": "* Please input HELLO"\r
+                },\r
+                   //tls warning:homegrown not fielded \r
+                "dateFormat":{\r
+                    "regex": /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(?:(?:0?[1-9]|1[0-2])(\/|-)(?:0?[1-9]|1\d|2[0-8]))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^(0?2(\/|-)29)(\/|-)(?:(?:0[48]00|[13579][26]00|[2468][048]00)|(?:\d\d)?(?:0[48]|[2468][048]|[13579][26]))$/,\r
+                    "alertText": "* Invalid Date"\r
+                },\r
+                //tls warning:homegrown not fielded \r
+                               "dateTimeFormat": {\r
+                       "regex": /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1}$|^(?:(?:(?:0?[13578]|1[02])(\/|-)31)|(?:(?:0?[1,3-9]|1[0-2])(\/|-)(?:29|30)))(\/|-)(?:[1-9]\d\d\d|\d[1-9]\d\d|\d\d[1-9]\d|\d\d\d[1-9])$|^((1[012]|0?[1-9]){1}\/(0?[1-9]|[12][0-9]|3[01]){1}\/\d{2,4}\s+(1[012]|0?[1-9]){1}:(0?[1-5]|[0-6][0-9]){1}:(0?[0-6]|[0-6][0-9]){1}\s+(am|pm|AM|PM){1})$/,\r
+                    "alertText": "* Invalid Date or Date Format",\r
+                    "alertText2": "Expected Format: ",\r
+                    "alertText3": "mm/dd/yyyy hh:mm:ss AM|PM or ", \r
+                    "alertText4": "yyyy-mm-dd hh:mm:ss AM|PM"\r
+                   }\r
+            };\r
+            \r
+        }\r
+    };\r
+    $.validationEngineLanguage.newLang();\r
+})(jQuery);
\ No newline at end of file
index 51e8ea5d148ae8074c8ef13ae993e506526f6772..06fce92aced9ddbe99c491e2ca572f541ab766fa 100644 (file)
@@ -1 +1,11 @@
 <h1>Chatty - Toy chat app written in Perl/Catalyst</h1>
+<p>
+This app lets you chat with other registered chatters. Cool!  Once you are
+registered and logged-in, you will be allowed to join a chat room and get
+chatty.
+</p>
+[% IF ! c.user_exists -%]
+[% INCLUDE login.tt -%]
+[% ELSE %]
+<a href="[% c.uri_for('logout') %]">Log Out</a>
+[% END -%]
index d2b70e2dceb25c4079e342ddda45e10bbbb77836..d6ad93cecbdd06b4975c35d8f1926c48f3a9b0bb 100644 (file)
@@ -1,13 +1,24 @@
-<h1>Log In</h1>
-[% IF ! c.user_exists %]
+[% META title = 'Log In' -%]
+<h2>Log In</h2>
+[% IF ! c.user_exists -%]
 <form action="[% c.uri_for('login')  %]" method="post">
-       <label for="handle">Username</label>
-       <input type="text" name="handle" id="handle">
-       <label for="password">Password</label>
-       <input type="password" name="password" id="password">
-       <input type="submit" value="Login">
+       <fieldset>
+               <p>
+                       <label for="handle">Username</label>
+                       <input type="text" name="handle" id="handle">
+               </p>
+               <p>
+                       <label for="password">Password</label>
+                       <input type="password" name="password" id="password">
+               </p>
+               <input type="submit" value="Login">
+       </fieldset>
 </form>
-[% ELSE %]
+<h3>Don't have an account?</h3>
+<p>
+If you haven't yet registered, <a href="[% c.uri_for('register') %]">go do that now</a>!
+</p>
+[% ELSE -%]
 <p>You are already logged in.</p>
 <a href="[% c.uri_for('logout') %]">Log Out</a>
-[% END %]
+[% END -%]
diff --git a/root/tt/register.tt b/root/tt/register.tt
new file mode 100644 (file)
index 0000000..9c15f92
--- /dev/null
@@ -0,0 +1,34 @@
+[% META title = 'Register' -%]
+[% BLOCK js -%]
+$('#form').validationEngine();
+$('#form button[type=reset]').click(function() {
+       $('#form').validationEngine('hideAll');
+});
+[% END -%]
+<h2>Register</h2>
+[% IF ! c.user_exists -%]
+<form id="form" action="[% c.uri_for('register') %]" method="post">
+       <fieldset>
+               <p>
+                       <label>Email</label>
+                       <input id="email" class="validate[custom[email]]" type="text" name="email">
+               </p>
+               <p>
+                       <label>Username*</label>
+                       <input id="handle" class="validate[required]" type="text" name="handle">
+               </p>
+               <p>
+                       <label>Password*</label>
+                       <input id="password1" class="validate[required]" type="password" name="password">
+               </p>
+               <p>
+                       <label>Confirm*</label>
+                       <input id="password2" class="validate[required]" type="password" name="password">
+               </p>
+               <button type="submit">Register</button>
+               <button type="reset">Reset</button>
+       </fieldset>
+</form>
+[% ELSE -%]
+<p>You are already registered and logged in.  There is no need to register again.</p>
+[% END -%]
index 7599375496479d2ef5ef3f76523a27faca3f2e14..6fad196f4d97108a65fce37dc85403d6812f773b 100644 (file)
@@ -5,18 +5,23 @@
                <meta name="author" content="Charles McGarvey">
                <meta name="description" content="This is a chat application in Catalyst!">
                <link rel="stylesheet" type="text/css" href="[% c.uri_for('/static/css/common.css') %]">
+               <link rel="stylesheet" type="text/css" href="[% c.uri_for('/static/css/validationEngine.jquery.css') %]">
                <title>Chatty - [% template.title or 'Toy chat application written in Perl/Catalyst' %]</title>
        </head>
        <body>
                <div id="outer">
 [% IF error -%]
-                               <p id="error">[% error %]</p>
+                       <div id="error">
+                               [% error %]
+                       </div>
 [% END -%]
 [% IF message -%]
-                               <p id="message">[% message %]</p>
+                       <div id="message">
+                               [% message %]
+                       </div>
 [% END -%]
                        <div id="inner">
-[% content %]
+[% content -%]
                                <hr>
                                <div id="footer">
                                        Copyright &copy; 2011 Charles McGarvey. Some rights reserved.
                                </div>
                        </div>
                </div>
-               <script type="text/javascript" src="[% c.uri_for('/static/js/jquery.tools-1.2.6.min.js') %]"></script>
+               <script type="text/javascript" src="http://cdn.jquerytools.org/1.2.6/full/jquery.tools.min.js"></script>
+               <script type="text/javascript" src="[% c.uri_for('/static/js/jquery.validationEngine-2.2.1.min.js') %]"></script>
+               <script type="text/javascript" src="[% c.uri_for('/static/js/jquery.validationEngine-en.js') %]"></script>
                <script type="text/javascript">
-[% IF error -%]
                        $(function () {
-                                       $("#error").expose({color: '#999'}).click(function() {
-                                                       $.mask.close();
-                                                       $(this).remove();
-                                               });
-                       });
+[% IF error -%]
+                               $('#error').click(function() {
+                                       $.mask.close();
+                                       $(this).slideUp('fast');
+                               });
+                               $('#error').delay(200).slideDown('fast').fadeOut('fast').fadeIn('fast').fadeOut('fast').fadeIn('fast');
+[% END -%]
+[% IF message -%]
+                               $('#message').click(function() {
+                                       $(this).slideUp('fast');
+                               });
+                               $('#message').delay(200).slideDown('fast');
+                               setTimeout("$('#message').slideUp()", 5000);
 [% END -%]
+$.tools.validator.localize("en", {
+       ':email'                : 'Please enter a valid email address.',
+       '[required]'    : 'This field is required.'
+});
+[% TRY; INCLUDE js; CATCH; ''; END -%]
+                       });
                </script>
        </body>
 </html>
This page took 0.051038 seconds and 4 git commands to generate.