diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..1281aad
Binary files /dev/null and b/.DS_Store differ
diff --git a/.project b/.project
index 8f82ddb..bef8b0e 100644
--- a/.project
+++ b/.project
@@ -1,11 +1,11 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>html5Widgets.old</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-	</buildSpec>
-	<natures>
-	</natures>
-</projectDescription>
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>html5Widgets</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+	</buildSpec>
+	<natures>
+	</natures>
+</projectDescription>
diff --git a/README.txt b/README.txt
index 18e36ca..b61afe8 100644
--- a/README.txt
+++ b/README.txt
@@ -1,12 +1,29 @@
-HTML5Widgets is a JavaScript polyfill that implements a subset of the HTML5
+HTML5Forms.js is a JavaScript polyfill that implements a subset of the HTML5
 Forms module in all browsers.  The script will only add support for the
 different parts of the module when there doesn't exist a native
-implementation - for example, at the time of this writing, it will implement
-the datetime calendar widget in all browser except Opera, which supports it
-natively.
+implementation.  HTML5Forms supports the following HTML5 input types:
+
+* range
+* date
+* datetime
+* datetime-local
+* week
+* color
+
+It also supports:
+
+* form validation (via "required" and "pattern" attributes)
+* the autofocus attribute (i.e. focusing on a particular form element onload)
+* the placeholder attribute (i.e. descriptive text of what should be in an form field)
+* the output tag (solves equations of form elements)
+* CSS styling of form validation states (simulates :invalid and :valid in unsupported 
+  browsers like IE9 and lower)
 
 More information about how this works is available at:
 
 http://www.useragentman.com/blog/2010/07/27/cross-browser-html5-forms-using-modernizr-webforms2-and-html5widgets/
+http://www.useragentman.com/blog/2012/05/14/cross-browser-styling-of-html5-forms-even-in-older-browsers/
 
+Note that this package was originally released in 2010 as html5Widgets, and was renamed 
+to a more accurate and descriptive name.
 
diff --git a/shared/.DS_Store b/shared/.DS_Store
new file mode 100644
index 0000000..36f3b43
Binary files /dev/null and b/shared/.DS_Store differ
diff --git a/shared/css/number.css b/shared/css/number.css
new file mode 100644
index 0000000..e3bf5b9
--- /dev/null
+++ b/shared/css/number.css
@@ -0,0 +1,35 @@
+
+.html5-numberControls {
+	display: block;
+	vertical-align:top;
+	position: absolute;
+	top: 0;
+	right: 0em;
+	height: 1.5em;
+	border: solid 1px #666666;
+	border-radius: 5px;
+	width: 0.8em;
+	color: #666666;
+	margin-top: 0.3em;
+}
+
+.html5-numberWrapper {
+	position: absolute;
+	height: 1em;
+}
+
+ .html5-numberControls a{
+	margin: 0 0 0 0.2em;
+	padding:0;
+	border:0;
+	background-color:transparent;
+	width: 0.9em;
+	cursor:pointer;
+	position:absolute;
+	
+	font-size: 0.6em;
+}
+
+.html5-numberControls .upbutton{top:0px;}
+
+.html5-numberControls .dnbutton{bottom: 0px;}
\ No newline at end of file
diff --git a/shared/js/.DS_Store b/shared/js/.DS_Store
new file mode 100644
index 0000000..92a5116
Binary files /dev/null and b/shared/js/.DS_Store differ
diff --git a/shared/js/autocomplete/CVS/Entries b/shared/js/autocomplete/CVS/Entries
new file mode 100644
index 0000000..137a7d4
--- /dev/null
+++ b/shared/js/autocomplete/CVS/Entries
@@ -0,0 +1,3 @@
+/index.html/1.1/Tue Jun  1 04:46:08 2010//
+D/turnOffInExplorer////
+D/xml////
diff --git a/shared/js/autocomplete/CVS/Repository b/shared/js/autocomplete/CVS/Repository
new file mode 100644
index 0000000..4f38a0f
--- /dev/null
+++ b/shared/js/autocomplete/CVS/Repository
@@ -0,0 +1 @@
+screengenerator/htdocs/tests/autocomplete
diff --git a/shared/js/autocomplete/CVS/Root b/shared/js/autocomplete/CVS/Root
new file mode 100644
index 0000000..6c6a1d0
--- /dev/null
+++ b/shared/js/autocomplete/CVS/Root
@@ -0,0 +1 @@
+:pserver:tv@192.168.2.25:/home/tv/cvs
diff --git a/shared/js/autocomplete/autocomplete.js b/shared/js/autocomplete/autocomplete.js
new file mode 100644
index 0000000..e7e1acd
--- /dev/null
+++ b/shared/js/autocomplete/autocomplete.js
@@ -0,0 +1,387 @@
+var autocomplete = new function () { 
+	var me = this;
+
+	var inputNodes;
+	var listContainerNode;
+	var bodyNode;
+	var minLength;
+	var req;
+	var currentLookupString = "";
+	var currentFocusedInputNode = null;
+	var numberCurrentValues;
+	
+	var lastLookupString ="", lastLookupValues;
+
+	me.values = null;
+	me.x = -1;
+	me.y = -1;
+	
+	me.init = function () {
+		
+		if (EventHelpers.hasPageLoadHappened(arguments)) return;
+		
+		bodyNode = document.getElementsByTagName('body')[0];
+		minLength = config.getIntegerValue('autocomplete.values.minLength', 0);
+		createListContainerNode();
+		setInitialEvents();
+	}
+	
+	function createListContainerNode () {
+		
+			
+		listContainerNode = document.createElement('div');
+		
+		listContainerNode.style.display = 'none';
+		listContainerNode.style.position= 'absolute';
+		listContainerNode.id = 'autocomplete-selection'
+		
+
+		bodyNode.appendChild(listContainerNode);
+		
+	}
+	
+	function setInitialEvents () {
+		inputNodes = CSSHelpers.getElementsByClassName(document, 
+			'autocomplete_input');
+			
+		for (var i=0; i<inputNodes.length; i++) {
+			
+			EventHelpers.addEvent(inputNodes[i], 'keyup', keyUpEvent);
+			EventHelpers.addEvent(inputNodes[i], 'keypress', keyPressEvent);
+			formNode = DOMHelpers.getAncestorByTagName(inputNodes[i], 'form');
+			turnOffNativeAutocomplete(formNode);
+		}
+		
+		EventHelpers.addEvent(bodyNode, 'click', hideAutocompleteBox);
+		EventHelpers.addEvent(document, 'click', hideAutocompleteBox)
+	}
+	
+	function keyUpEvent(e) {
+		var key = EventHelpers.getKey(e);
+		currentFocusedInputNode = EventHelpers.getEventTarget(e);
+		 switch (key) {
+			case CharCode.DOWN:
+				moveFocusOnListEvent(e);
+				break;
+			case CharCode.ESC:
+				break;
+			case CharCode.ENTER:
+				EventHelpers.preventDefault(e);
+				break;
+			default: 
+				getListEvent(e);
+		} 
+		
+		//getListEvent(e);
+	}
+	
+	function keyPressEvent(e) {
+		var key = EventHelpers.getKey(e);
+		switch (key) {
+			case CharCode.DOWN:
+				moveFocusOnListEvent(e);
+				EventHelpers.preventDefault(e);
+				break;
+			case CharCode.ENTER:
+				EventHelpers.preventDefault(e);
+				break;
+		}
+		
+	}
+	
+	function moveFocusOnListEvent(e) {
+		activeInputNode = EventHelpers.getEventTarget(e);
+		
+		activeInputNode.blur();
+		
+		var listNode = getListNode();
+		
+		
+		// jslog.debug(listNode.nodeName)
+		var listItemNodes = getListItemNodes();
+		var firstListItemNode;
+		
+		
+		
+		
+		if (listItemNodes.length > 0) {
+			firstListItemNode = listItemNodes[0]
+		} else  {
+			firstListItemNode = listItemNodes;
+		}
+		
+		jslog.debug('firstListItemNode: ' + firstListItemNode.nodeName)
+		
+		if (firstListItemNode) {
+			
+			switch (firstListItemNode.nodeName) {
+				case "OPTION":
+					
+						//listNode.focus();
+						//jslog.debug(DebugHelpers.getProperties(firstListItemNode));
+						firstListItemNode.selected = 'selected';
+						replaceValue(firstListItemNode);
+						listNode.focus();
+						
+						
+					
+					break;
+			}
+			
+			//firstListItemNode.focus();
+		}
+		
+		
+		
+		
+		
+		//jslog.debug('listNode properties: ' + DebugHelpers.getProperties(listNode))	
+		
+	}
+	
+	
+	
+	function getListEvent(e) {
+		activeInputNode = EventHelpers.getEventTarget(e);
+		currentLookupString=activeInputNode.value;
+		
+		if (currentLookupString.length < minLength) {
+			listContainerNode.innerHTML = "";
+			return;
+		}
+		
+		
+		
+		me.x = CSSHelpers.getAbsoluteLeft(activeInputNode);
+		me.y = CSSHelpers.getAbsoluteTop(activeInputNode) 
+			+ CSSHelpers.getHeight(activeInputNode);
+		
+		
+		var id=activeInputNode.name.replace(/ /g, '_' );
+		
+		
+		var URL = config.getScriptedValue('autocomplete.urls.' + id,
+			{
+				inputID:	id,
+				inputValue:	currentLookupString
+			});
+			
+		listContainerNode.innerHTML = config.getValue('autocomplete.templates.pleaseWait');
+		showAutocompleteBox();
+		
+		
+		/* 
+		 * if this is not the old request with a few letters tacked on, 
+		 * do an httpRequest to this.  Otherwise, do call setValues().
+		 */
+		
+		if (lastLookupString != "" && currentLookupString.toLowerCase().indexOf(lastLookupString.toLowerCase()) == 0) {
+			showDropDown(lastLookupValues);
+		} else {
+			if (req) {
+				req.abort();
+			}
+			req = XMLHelpers.getXMLHttpRequest(URL, getListRequest);
+			
+		}
+		
+	
+	}
+	
+	function getListRequest() {
+		if (!req) {
+			//DebugHelpers.log("XMLHttpRequest was null: exiting");
+			return;
+	    }
+		
+
+
+	    if (req.readyState == ReadyState.COMPLETED) {
+	        // only if "OK"
+
+	        if (req.status == HttpCode.OK) {
+				var values = req.responseText.split('\n');
+				showDropDown(values);
+				lastLookupString=currentLookupString;
+				lastLookupValues=values;
+			}
+		}
+	}
+	
+	function showDropDown(values) {
+				removeAutocompleteBoxEvents();
+				me.setValues(values);
+				jslog.debug(numberCurrentValues)
+				if (numberCurrentValues == 0) {
+					hideAutocompleteBox();
+				} else {
+					jslog.debug('not zeri')
+					setAutocompleteBoxEvents();
+					showAutocompleteBox();
+				} 
+	}
+	
+	me.setValues = function (values) {
+		me.values = values;
+		
+		var lastElement = me.values.pop();
+		
+		if (lastElement.trim() != "") {
+			me.values.push(lastElement)
+		}
+		
+		
+		if (me.values.length == 0) {
+			listContainerNode.innerHTML = "";
+		}
+		else {
+		
+			var valuesHTMLSb = new StringBuffer();
+			numberCurrentValues = 0;
+			for (var i = 0; i < me.values.length; i++) {
+				var value = me.values[i].trim();
+				
+				if (value != "" && value.toLowerCase().indexOf(currentLookupString.toLowerCase()) == 0 ) {
+					numberCurrentValues++;
+					valuesHTMLSb.append(config.getScriptedValue('autocomplete.templates.listItem', {
+						listItem: me.values[i]
+					}))
+				}
+			}
+			
+			listContainerNode.innerHTML = config.getScriptedValue('autocomplete.templates.list', {
+				listItemsHTML: valuesHTMLSb.toString()
+			});
+		}
+	}
+	
+	function selectKeyEvent (e) {
+		var key = EventHelpers.getKey(e);
+		
+		
+		switch(key){
+			case CharCode.ESC:
+			case CharCode.ENTER:
+				hideAutocompleteBox(e);
+				currentFocusedInputNode.focus();
+				
+				break;
+			case CharCode.TAB:
+				focusOnInputField(e);
+				break;
+			case CharCode.BACKSPACE:
+				currentFocusedInputNode.value = "";
+				hideAutocompleteBox(e);
+				currentFocusedInputNode.focus();
+				// prevents browser from going back a page.
+				EventHelpers.preventDefault(e);
+				break;
+		}
+	}
+	
+	function focusOnInputField(e) {
+		currentFocusedInputNode.focus();
+		if (BrowserDetect.browser == "Explorer") {
+			EventHelpers.preventDefault(e);
+		}
+	}
+	
+	function showAutocompleteBox () {
+		CSSHelpers.moveTo(listContainerNode, me.x, me.y)
+		listContainerNode.style.display = 'block';	
+	}
+	
+	function hideAutocompleteBox(e) {
+		listContainerNode.style.display = 'none';
+		removeAutocompleteBoxEvents();
+		listContainerNode.innerHTML = '';
+	}
+	
+	function getListItemNodes () {
+		var valueNodes = cssQuery(
+			config.getValue('autocomplete.selectors.listItem'),
+			listContainerNode
+		); 
+		
+		return valueNodes;
+	}
+	
+	function getListNode () {
+		var listNodes = cssQuery(
+			config.getValue('autocomplete.selectors.list'),
+			listContainerNode
+		); 
+		
+		if (listNodes && listNodes.length > 0) {
+			return listNodes[0];
+		}
+		else {
+			return null;
+		}
+		
+	}
+	
+	function setAutocompleteBoxEvents() {
+		var valueNodes = getListItemNodes();
+			
+		var listNode = getListNode();
+		
+		if (listNode) {
+			EventHelpers.addEvent(listNode, 'change', replaceValueEvent);
+			EventHelpers.addEvent(listNode, 'blur', hideAutocompleteBox);
+			EventHelpers.addEvent(listNode, 'keyup', selectKeyEvent);
+			EventHelpers.addEvent(listNode, 'keydown', selectKeyEvent);
+			EventHelpers.addEvent(listNode, 'blur', focusOnInputField);
+		}
+		
+		if (valueNodes) {
+			for (var i = 0; i < valueNodes.length; i++) {
+				
+				EventHelpers.addEvent(valueNodes[i], 'click', replaceValueEvent);	
+				
+			}
+		}
+	}
+	
+	function removeAutocompleteBoxEvents() {
+		
+		
+		var valueNodes =  getListItemNodes();
+		
+		var listNode = getListNode();
+		
+		if (listNode) {
+			EventHelpers.removeEvent(listNode, 'change', replaceValueEvent);
+			EventHelpers.removeEvent(listNode, 'blur', hideAutocompleteBox);
+		}
+		
+		if (valueNodes) {
+			for (var i = 0; i < valueNodes.length; i++) {
+				EventHelpers.removeEvent(valueNodes[i], 'click', replaceValueEvent);
+				
+			}
+		}
+	}
+	
+	function replaceValueEvent(e){
+		var valueNode = EventHelpers.getEventTarget(e);
+		replaceValue(valueNode)
+	}
+	 
+	function replaceValue(valueNode) {	
+		var value = valueNode.value;
+		jslog.debug(valueNode.value);
+		if (!value) {
+			value = valueNode.innerHTML;
+		} 
+		
+		activeInputNode.value = value;
+		
+	}
+	
+	function turnOffNativeAutocomplete(formNode) {
+        formNode.setAttribute('autocomplete', 'off');
+    }
+}
+
+EventHelpers.addPageLoadEvent('autocomplete.init'); 
diff --git a/shared/js/autocomplete/index.html b/shared/js/autocomplete/index.html
new file mode 100644
index 0000000..4545786
--- /dev/null
+++ b/shared/js/autocomplete/index.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+		<title>Untitled Document</title>
+		<!-- <script type="text/javascript" src="../../shared/js/jslog.js"></script> -->
+		<script type="text/javascript" src="../../shared/js/helpers.js"></script>
+		<script type="text/javascript" src="../../shared/js/config.js"></script>
+		<script type="text/javascript" src="../../shared/js/cssQuery-p.js"></script>
+		<script type="text/javascript" src="../../shared/js/autocomplete.js"></script>
+		
+		<link type="text/css" href="../../shared/css/autocomplete.css" rel="stylesheet" media="all" />
+	</head>
+	<body>
+		<form action="http://www.useragentman.com/testForm.php">
+			<table class="formTable">
+				<tr>
+					<th>Homing City #1:</th>
+					<td><input type="text" id="city" name="city" value="" class="autocomplete_input" /></td>
+				</tr>
+				<tr>
+					<th>Homing City #2:</th>
+					<td><input type="text" id="city" name="city2" value="" class="autocomplete_input" /></td>
+				</tr>
+			</table>
+		</form>	
+			
+			<div id="config">
+			<!--
+				xml=xml/config.xml
+			-->
+			</div>
+	</body>
+</html>
diff --git a/shared/js/autocomplete/turnOffInExplorer/CVS/Entries b/shared/js/autocomplete/turnOffInExplorer/CVS/Entries
new file mode 100644
index 0000000..f2ea187
--- /dev/null
+++ b/shared/js/autocomplete/turnOffInExplorer/CVS/Entries
@@ -0,0 +1 @@
+/index.html/1.1/Tue Jun  1 04:45:15 2010//
diff --git a/shared/js/autocomplete/turnOffInExplorer/CVS/Repository b/shared/js/autocomplete/turnOffInExplorer/CVS/Repository
new file mode 100644
index 0000000..d133da1
--- /dev/null
+++ b/shared/js/autocomplete/turnOffInExplorer/CVS/Repository
@@ -0,0 +1 @@
+screengenerator/htdocs/tests/autocomplete/turnOffInExplorer
diff --git a/shared/js/autocomplete/turnOffInExplorer/CVS/Root b/shared/js/autocomplete/turnOffInExplorer/CVS/Root
new file mode 100644
index 0000000..6c6a1d0
--- /dev/null
+++ b/shared/js/autocomplete/turnOffInExplorer/CVS/Root
@@ -0,0 +1 @@
+:pserver:tv@192.168.2.25:/home/tv/cvs
diff --git a/shared/js/autocomplete/turnOffInExplorer/index.html b/shared/js/autocomplete/turnOffInExplorer/index.html
new file mode 100644
index 0000000..4ab8f72
--- /dev/null
+++ b/shared/js/autocomplete/turnOffInExplorer/index.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+		<title>Untitled Document</title>
+	</head>
+	<body>
+		
+		<form action="http://www.useragentman.com/testForm.php">
+			<table>
+				<tr>
+				<th>Username:</th>
+				<td><input type="text" name="username" /></td>
+				</tr>
+				
+				<tr>
+					<th>Password:</th>
+					<td><input type="password" name="password" /></td>
+				</tr>
+				
+				<tr>
+					<td colspan="2">
+						<input type="submit" />
+					</td>
+				</tr>
+				
+			</table>
+		</form>
+	</body>
+</html>
diff --git a/shared/js/autocomplete/xml/CVS/Entries b/shared/js/autocomplete/xml/CVS/Entries
new file mode 100644
index 0000000..4467fce
--- /dev/null
+++ b/shared/js/autocomplete/xml/CVS/Entries
@@ -0,0 +1 @@
+/config.xml/1.1/Tue Jun  1 04:45:42 2010//
diff --git a/shared/js/autocomplete/xml/CVS/Repository b/shared/js/autocomplete/xml/CVS/Repository
new file mode 100644
index 0000000..8f4188a
--- /dev/null
+++ b/shared/js/autocomplete/xml/CVS/Repository
@@ -0,0 +1 @@
+screengenerator/htdocs/tests/autocomplete/xml
diff --git a/shared/js/autocomplete/xml/CVS/Root b/shared/js/autocomplete/xml/CVS/Root
new file mode 100644
index 0000000..6c6a1d0
--- /dev/null
+++ b/shared/js/autocomplete/xml/CVS/Root
@@ -0,0 +1 @@
+:pserver:tv@192.168.2.25:/home/tv/cvs
diff --git a/shared/js/autocomplete/xml/config.xml b/shared/js/autocomplete/xml/config.xml
new file mode 100644
index 0000000..71623e0
--- /dev/null
+++ b/shared/js/autocomplete/xml/config.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config>
+	<autocomplete>
+		<urls>
+			<city>/bin/getList.cgi?inputValue=@inputValue&amp;inputID=cities</city>
+			<city2>/bin/getList.cgi?inputValue=@inputValue&amp;inputID=cities</city2>
+		</urls>
+		<templates>
+			<list><![CDATA[
+				<select size="10">@listItemsHTML</select>
+			]]></list>
+			<listItem><![CDATA[
+				<option value="@listItem">@listItem</option>
+			]]></listItem>
+			<pleaseWait><![CDATA[
+				<div id="autocomplete-pleaseWait">
+				<strong><img src="../../shared/images/icons/spinner.gif" />Please Wait</strong>
+				</div>
+			]]></pleaseWait>
+		</templates>
+		<selectors>
+			<listItem>option</listItem>
+			<list>select</list>
+		</selectors>
+		<values>
+			<minLength>1</minLength>
+		</values>
+	</autocomplete>
+</config> 
\ No newline at end of file
diff --git a/shared/js/frequency-decoder.com/slider.js b/shared/js/frequency-decoder.com/slider.js
index d1673b6..74886d8 100644
--- a/shared/js/frequency-decoder.com/slider.js
+++ b/shared/js/frequency-decoder.com/slider.js
@@ -199,6 +199,7 @@ var fdSliderController = (function() {
                 /*@end@*/
         };              
         function fdSlider(options) {
+        	
                 var inp         = options.inp,
                     disabled    = false,
                     tagName     = inp.tagName.toLowerCase(),                      
@@ -206,8 +207,10 @@ var fdSliderController = (function() {
                     max         = +options.range[1], 
                     range       = Math.abs(max - min),
                     inc         = tagName == "select" ? 1 : +options.inc||1,
-                    maxInc      = options.maxInc ? options.maxInc : inc * 2,
-                    precision   = options.inc.search(".") != -1 ? options.inc.substr(options.inc.indexOf(".")+1, options.inc.length - 1).length : 0,
+                    maxInc      = options.maxInc && options.maxInc != 'undefined' ? options.maxInc : inc * 2;
+                   // alert(options.maxInc + "," + maxInc) 
+                    
+                    var precision   = options.inc.search(".") != -1 ? options.inc.substr(options.inc.indexOf(".")+1, options.inc.length - 1).length : 0,
                     steps       = Math.ceil(range / inc),
                     useTween    = !!options.tween,
                     fullARIA    = !!options.fullARIA,
@@ -334,6 +337,7 @@ var fdSliderController = (function() {
                                 maxPx     = vertical ? sH - hH : sW - hW;
                                 stepPx    = maxPx / steps;                                                 
                                 deltaPx   = maxPx / Math.ceil(range / maxInc);
+                                console.log(maxInc)
                                 
                                 sliderW = sW;
                                 sliderH = sH;
diff --git a/shared/js/html5Forms.js b/shared/js/html5Forms.js
new file mode 100644
index 0000000..4551be6
--- /dev/null
+++ b/shared/js/html5Forms.js
@@ -0,0 +1,301 @@
+var html5Forms = new function () {
+	var me = this;
+	
+	var scriptNode = null,
+		scriptDir = null,
+		hasBadValidationImplementation = false; //navigator.userAgent.indexOf('WebKit') > 0,
+		// WebKit less than 534 doesn't show validation UI - we need to check for this (from http://stackoverflow.com/questions/6030522/html5-form-validation-modernizr-safari)
+		hasNativeBubbles = navigator.userAgent.indexOf('WebKit') < 0 || parseInt(navigator.userAgent.match(/AppleWebKit\/([^ ]*)/)[1].split('.')[0])  > 533;
+		
+	
+	var globalEvent = document.addEventListener?document.createEvent("HTMLEvents"):null;
+	
+	
+	
+	me.init = function () {
+		var scriptNodes = document.getElementsByTagName('script');
+		
+		for (var i=0; i<scriptNodes.length; i++) {
+			scriptNode = scriptNodes[i];
+			
+			if (scriptNode.src.match('html5Forms(_src|-p|)\.js')) {
+				scriptNode = scriptNode;
+				scriptDir = getScriptDir();
+				break;
+			}
+		}
+		
+		if (scriptNode) {
+			if (window.yepnope) {
+				var inputSupport = Modernizr.inputtypes;
+				/* let's load the supporting scripts according to what is in data-webforms2-support */
+				var supportArray = scriptNode.getAttribute('data-webforms2-support');
+				var forceJSValidation = (scriptNode.getAttribute('data-webforms2-force-js-validation') == 'true');
+				
+				if (!supportArray) {
+					return;
+				} else if (trim(supportArray) == 'all') {
+					supportArray="validation,number,color,date,ouput,range,placeholder";
+				}
+				
+				supportArray = supportArray.split(',');
+				var toLoad = [];
+				var toRunAfterLoad = [];
+				var loadHTML5Widgets = false;
+				
+				
+				for (var i=0; i<supportArray.length; i++) {
+					var supportReq = trim(supportArray[i]);
+					
+					switch(supportReq) {
+						
+						case "validation":
+						case "autofocus":
+							if (!Modernizr.input.required || hasBadValidationImplementation || forceJSValidation) {
+								
+								toLoad = toLoad.concat([  
+										scriptDir + '../../shared/js/weston.ruter.net/webforms2/webforms2_src.js']);
+								
+								if (supportReq == 'autofocus') {
+									loadHTML5Widgets = true;
+								}
+								
+							}	
+							break;
+						case "number":
+							if (!inputSupport.number) {
+								toLoad = toLoad.concat([
+										scriptDir + '../../shared/css/number.css']);
+								loadHTML5Widgets = true;
+							}
+							break;
+						case "color":
+							if (!inputSupport.color) {
+								
+								toLoad = toLoad.concat([  scriptDir + '../../shared/js/jscolor/jscolor.js']);
+								
+								loadHTML5Widgets = true;
+							}	
+							break;
+						
+						case "datetime":
+						case "date":
+							var lang = scriptNode.getAttribute('data-lang');
+							
+							
+							/* If data-lang is not set, or is set to an unsupported language, use English by default. */
+							if (!lang || 
+								!lang.match(/^(af|al|bg|big5|br|ca|cn|cs|da|de|du|el|en|es|fi|fr|he|hr|hu|it|jp|ko|ko|lt|lt|lv|nl|no|pl|pl|pt|ro|ru|si|sk|sp|sv|tr|zh)$/)){
+
+								
+								lang = navigator.language.split('-')[0];
+							}
+							
+							
+							
+							if (!inputSupport.date) {
+								toLoad = toLoad.concat([  
+										  scriptDir + '../../shared/js/jscalendar-1.0/calendar-win2k-1.css',
+										  scriptDir + '../../shared/js/jscalendar-1.0/calendar.js', 
+										  scriptDir + '../../shared/js/jscalendar-1.0/lang/calendar-' + lang + '.js', 
+										  scriptDir + '../../shared/js/jscalendar-1.0/calendar-setup.js']);
+								loadHTML5Widgets = true;
+							}
+							break;
+							
+						case "output":
+							if(!supportsOutput()) {
+								
+								loadHTML5Widgets = true;
+							}
+							break;
+						
+						case "range":
+						   /* yepnope({
+						    	load: ['ie6!' + scriptDir + '../../shared/css/slider.css']
+						   }); */
+						    
+							if(!inputSupport.range) {
+								toLoad = toLoad.concat([  scriptDir + '../../shared/css/slider.css',
+										  scriptDir + '../../shared/js/frequency-decoder.com/slider.js']);
+							
+										  
+								loadHTML5Widgets = true;
+								toRunAfterLoad.push('fdSliderController.redrawAll');
+									 
+							}
+							break;
+						case "placeholder":
+						case "autofocus":
+							if (!Modernizr.input[supportReq]) {
+								loadHTML5Widgets = true;
+							}
+					}
+				}
+				
+				
+				if (toLoad.length == 0) {
+					loadWidgets();
+					
+					// allow browsers that don't need webforms2 to handle custom error messages populated
+					// in the data-errormessage attribute
+					if (document.addEventListener) {
+						document.addEventListener('DOMContentLoaded', handleCustomErrorMessages, false);
+					}
+				} else {
+					yepnope({
+						load: toLoad,
+						complete: function (){
+							loadWidgets();
+							handleCustomErrorMessages();
+						}
+					});
+				}
+			}
+		}
+		
+		function loadWidgets() {
+			
+			yepnope({
+				test: loadHTML5Widgets,
+				yep: scriptDir + '../../shared/js/html5Widgets.js',
+				complete: function () {
+					if (loadHTML5Widgets) {
+						for (var i=0; i<toRunAfterLoad.length; i++)  {
+							eval(toRunAfterLoad[i] + '()');
+						}
+						EventHelpers.init();
+						html5Widgets.init();
+						//toRunAfterLoad.push('html5Widgets.init');
+					}
+				}
+			})
+			
+		}
+		
+		/*
+		 * This should work even when webforms2 is not loaded.
+		 */
+		function handleCustomErrorMessages() {
+			
+			var nodeNames = ["input", "select", "textarea"];
+			for (var i=0; i<nodeNames.length; i++) {
+				var nodes = document.getElementsByTagName(nodeNames[i]);
+				
+				for (var j=0; j<nodes.length; j++) {
+					var node = nodes[j];
+					var message = me.getAttributeValue(node, 'data-errormessage');
+					if (message) {
+						if(document.addEventListener){
+							node.addEventListener('invalid', showCustomMessageEvent, false);
+							node.addEventListener('focus', showCustomMessageEvent, false);
+							
+							// Opera doesn't work well with this.
+							if (!window.opera) {
+								node.addEventListener('keypress', clearMessageIfValidEvent, false);
+							}
+							
+							node.addEventListener('input', clearMessageIfValidEvent, false);
+						} else {
+							var invalidEvent = ' this.setCustomValidity("' + message + '");';
+							if (node.oninvalid) {
+								node.oninvalid += invalidEvent;
+							} else {
+								node.oninvalid = invalidEvent;
+							}
+							node.oninvalid = new Function('event', node.oninvalid);
+							
+							// IE freaks a little on keypress here, so change to keydown.
+							node.attachEvent('onkeydown', clearMessageIfValidEvent);
+							node.attachEvent('oninput', clearMessageIfValidEvent); 
+						}
+						clearMessageIfValid(node);
+			
+					}
+				}
+			}
+		}
+		
+		function showCustomMessageEvent(event) {
+			var node = event.currentTarget || event.srcElement;
+			showCustomMessage(node);
+		}
+		
+		function showCustomMessage(node) {
+			if (node.validity.valid) {
+				return;
+			}
+			var message = me.getAttributeValue(node, 'data-errormessage');
+			node.setCustomValidity(message)
+			console.log('set custom validity')
+		}
+		
+		function clearMessageIfValidEvent (event) {
+			console.log(event.type)
+			var node = event.currentTarget || event.srcElement;
+			clearMessageIfValid(node);
+		}
+		
+		function clearMessageIfValid(node) {
+			node.setCustomValidity(''); 
+			if (!node.checkValidity()) {
+				showCustomMessage(node);
+				console.log('invalid')
+				if (document.addEventListener) {
+					globalEvent.initEvent('invalid', true, true); // event type,bubbling,cancelable
+	        		node.dispatchEvent(globalEvent);
+	        	}
+			} else {
+				console.log('valid')
+			}
+		}
+		
+	}
+	
+	var supportsOutput = function () {
+		var outputEl = document.createElement('output');
+		return (outputEl.value != undefined && (outputEl.onforminput !== undefined || outputEl.oninput !== undefined));
+		
+	}
+	
+	var getScriptDir = function () {
+		var arr = scriptNode.src.split('/');
+		arr.pop();
+		
+		return arr.join('/') + '/';
+	}
+	
+	me.getAttributeByName = function (obj, attrName) {
+		var i;
+		
+		var attributes = obj.attributes;
+		for (var i=0; i<attributes.length; i++) {
+			var attr = attributes[i]
+			if (attr.nodeName == attrName && attr.specified) {
+			  	return attr;
+			}
+		}
+		return null;
+	}
+	
+	me.getAttributeValue = function (obj, attrName) {
+		var attr = me.getAttributeByName(obj, attrName);
+		
+		if (attr != null) {
+			return attr.nodeValue;
+		} else {
+			return null;
+		}
+	}
+	
+	var initWhitespaceRe = /^\s\s*/;
+	var endWhitespaceRe = /\s\s*$/;
+	
+	function trim(str) {
+		return str.replace(initWhitespaceRe, '')
+			.replace(endWhitespaceRe, '');
+	}  
+
+}
+
+html5Forms.init();
diff --git a/shared/js/html5Widgets.js b/shared/js/html5Widgets.js
index 6e27725..9f9e1a0 100644
--- a/shared/js/html5Widgets.js
+++ b/shared/js/html5Widgets.js
@@ -11,6 +11,7 @@
  *  version 1.0: initial release
  *  version 1.1: implemented oninput method for form elements for unsupported browsers
  *               fix IE9 to ensure backspace and delete keys fire an oninput event.
+ *  version 1.2: Added Number Element Widget
  *  
  * released under the MIT License:
  *   http://www.opensource.org/licenses/mit-license.php
@@ -181,6 +182,7 @@ var html5Widgets = new function(){
 				case "range":
 				
 					if (!inputSupport.range) {
+						
 						me.inputNodes.push(new RangeElement(formElement));
 					}
 					
@@ -202,6 +204,13 @@ var html5Widgets = new function(){
 						me.inputNodes.push(new ColorElement(formElement, elType));
 					} 
 					
+					break;
+				case "number":
+				
+					if (!inputSupport.number) {
+						me.inputNodes.push(new NumberElement(formElement, elType));
+					} 
+					
 					break;
 			}
 			
@@ -221,10 +230,13 @@ var html5Widgets = new function(){
 	
 	
 	
-	function delayedFireEvent(el, ev){
+	function delayedFireEvent(el, ev, callback){
 			
 			if (!document.createEventObject ) {
 				me.fireEvent(el, ev);
+				if (callback) {
+					callback();
+				}
 			}
 			else {
 				
@@ -236,6 +248,10 @@ var html5Widgets = new function(){
 				delayEventTimeout = setTimeout(
 					function(){
 						EventHelpers.fireEvent(el, ev);
+						
+						if (callback) {
+							callback();
+						}
 					}
 				, 1);
 				
@@ -321,12 +337,14 @@ var html5Widgets = new function(){
 	 */
 	
 	function RangeElement(node){
-		var me = this;
-		var parentForm;
+		var me = this,
+			parentForm,
+			hasFiredChangeEvent = false;
 		
 		me.node = node;
 		me.sliderNode = null;
 		
+		
 		function init (){
 			parentForm = DOMHelpers.getAncestorByTagName(node, 'form');
 			var min = parseFloat(DOMHelpers.getAttributeValue(me.node, 'min'));
@@ -421,9 +439,16 @@ var html5Widgets = new function(){
 			if (oninput) {
 				eval(html5Widgets.getValueFormula(oninput, parentForm));
 			}
-			delayedFireEvent(me.node, 'change');
+			
+			/* The if statement is to prevent this to continuously fire in an endless loop */
+			if (!hasFiredChangeEvent) {
+				hasFiredChangeEvent = true;
+				delayedFireEvent(me.node, 'change', function () {
+					hasFiredChangeEvent = false;
+				});
+			}
 		}
-		
+			
 		function changeOriginalNodeEvent(e) {
 			
 			fdSliderController.updateSlider(me.node.id);
@@ -513,9 +538,10 @@ var html5Widgets = new function(){
 			
 			// this will call submitEvent() after the form has been validated by
 			// webforms2.js
-			
-			$wf2.callBeforeValidation.push(prepareForSubmission);
-			$wf2.callAfterValidation.push(validationEvent);
+			if (window.$wf2) {
+				$wf2.callBeforeValidation.push(prepareForSubmission);
+				$wf2.callAfterValidation.push(validationEvent);
+			}
 			
 		}
 		
@@ -706,6 +732,202 @@ var html5Widgets = new function(){
 		init();
 	}
 	
+	/*
+	 * NumberElement: refactored from http://www.kethinov.com/jsstepper.php.
+	 */
+	
+	function NumberElement (node) {
+		var me = this,
+			min = parseFloat(DOMHelpers.getAttributeValue(node, 'min')),
+			max = parseFloat(DOMHelpers.getAttributeValue(node, 'max')),
+			step = parseFloat(DOMHelpers.getAttributeValue(node, 'step'));
+		
+		me.node = node;
+		
+		
+		
+		if (isNaN(step)) {
+			// we don't have to create the up and down arraw widgets
+			return;
+		}
+		
+		EventHelpers.addEvent(node, 'keyup', keyUpEvent);
+		
+		
+		function keyUpEvent() {
+			
+			if (isNumeric(this.value)) {
+				
+					/* if (this.value > max) this.value = max;
+					else if (this.value < min) this.value = this.min; */
+				
+			} else if (this.value != '') {
+				var val = parseFloat(this.value);
+				if (isNaN(val)) {
+					this.value = '';
+				} else {
+					this.value = val;
+				} 
+			}
+			
+		}
+	
+		
+		
+		function nearestValid(value, direction) { 
+			
+			var n = (value - min)/step,
+				r;
+			//alert(StringHelpers.sprintf("n: %s, value: %s, min: %s, step: %s", n, value, min, step))
+			if (n == parseInt(n)) {
+				r = value;
+			} else {
+			
+				if (direction < 0) {
+					n = Math.floor(n + 1);
+				} else {
+					n = Math.ceil(n -1);
+				}
+				
+				r = min + step * n;
+			}
+			
+			if (r > max) {
+				r -= step;
+			} else if (r < min) {
+				r+= step
+			}
+			
+			return r;
+		}
+		
+		function buttonMouseDownEvent(e) {
+			
+			var buttonType = this.className;
+			var stepMult = step;
+			if (buttonType == 'dnbutton') {
+				stepMult = -step;
+			}
+			
+			
+			var min = this.min;
+			var max = this.max;
+			if (
+				(stepMult < 0 && (node.value > min || isNaN(min))) ||
+				(stepMult > 0 && (node.value < max || isNaN(max)))
+			) {
+				setValue(me.node, nearestValid(parseFloat(node.value) + stepMult, stepMult));
+			}
+
+			var delayedOnce = false;
+			var date = new Date();
+			var curDate = null;
+		
+			this.interval = setInterval(function() {
+				if (!delayedOnce) {
+					curDate = new Date();
+					if (curDate - date > 500) delayedOnce = true;
+				}
+				else if (
+					(stepMult < 0 && (node.value > min || isNaN(min))) ||
+					(stepMult > 0 && (node.value < max || isNaN(max)))
+				) {
+					setValue(me.node, nearestValid(parseFloat(node.value) + stepMult, stepMult));
+				}
+			}, 50);
+			EventHelpers.preventDefault(e);
+		}
+		
+		function setValue(node, value) {
+			if (isNaN(value)) {
+				node.value = '';
+			} else {
+				node.value = value;
+			}
+		}
+		
+		function buttonClickEvent(e) {
+			clearInterval(this.interval);
+			EventHelpers.preventDefault(e);
+		}
+		function buttonMouseUpEvent(e) {
+			clearInterval(this.interval);
+			EventHelpers.preventDefault(e);
+		}
+		
+		function isNumeric(n) {
+		  return !isNaN(parseFloat(n)) && isFinite(n);
+		}
+
+	
+		function hasNativeSpinner() {
+			try {
+				return window.getComputedStyle(me.node, '-webkit-inner-spin-button').WebkitAppearance != undefined;
+			} catch (ex) {
+				return false;
+			}
+		}	
+		
+		function init () {
+			var upbutton = document.createElement('a');
+			upbutton.className = 'upbutton';
+			upbutton.appendChild(document.createTextNode("\u25B2"));
+			upbutton.targInput = node;
+			upbutton.max = max;
+			
+			var dnbutton = document.createElement('a');
+			dnbutton.className = 'dnbutton';
+			dnbutton.appendChild(document.createTextNode("\u25BC"));
+			dnbutton.targInput = node;
+			dnbutton.min = min;
+			dnbutton.max = max;
+		
+			EventHelpers.addEvent(upbutton, 'mousedown', buttonMouseDownEvent);
+			EventHelpers.addEvent(dnbutton, 'mousedown', buttonMouseDownEvent);
+			
+			EventHelpers.addEvent(upbutton, 'click', buttonClickEvent);
+			EventHelpers.addEvent(upbutton, 'mouseup', buttonMouseUpEvent);
+			EventHelpers.addEvent(dnbutton, 'click', buttonClickEvent);
+			EventHelpers.addEvent(dnbutton, 'mouseup', buttonMouseUpEvent);
+			
+			
+			if (!hasNativeSpinner()) {
+				var controlsNode = document.createElement('div');
+				controlsNode.className = 'html5-numberControls';
+				controlsNode.appendChild(upbutton);
+				controlsNode.appendChild(dnbutton);
+				
+				var wrapperNode = document.createElement('div')
+				wrapperNode.className = 'html5-numberWrapper';
+				wrapperNode.appendChild(controlsNode);
+				var parentNode = node.parentNode;
+				
+				
+				
+				
+				parentNode.insertBefore(wrapperNode, node);
+				
+		
+				var nodeWidth = node.offsetWidth;
+				var nodeStyle = CSSHelpers.getCurrentStyle(node);
+			
+				node.style.width = (nodeWidth - upbutton.offsetWidth -9) + 'px';
+				wrapperNode.style.width = nodeWidth + 'px';
+				wrapperNode.style.marginTop = nodeStyle.marginTop;
+				wrapperNode.style.height = (node.offsetHeight) + 'px';
+			}
+			
+			
+			
+		}
+		/* Finally: if the form field has a value onload that is not a number, remove it 
+		if (!isNumeric(node.value)) {
+			node.value = '';
+			EventHelpers.fireEvent(node, 'change');
+		}*/
+		init();
+	}
+	
 	function PlaceholderInput (node) {
 		var me = this;
 		
@@ -717,7 +939,7 @@ var html5Widgets = new function(){
 			defaultText = DOMHelpers.getAttributeValue(node, 'placeholder');
 			form = DOMHelpers.getAncestorByTagName(node, 'form');
 			
-			setPlaceholderText(true);
+			me.setPlaceholderText(true);
 			EventHelpers.addEvent(me.node, 'blur', blurEvent);
 			EventHelpers.addEvent(me.node, 'focus', focusEvent);
 			
@@ -736,7 +958,7 @@ var html5Widgets = new function(){
 			}
 		}
 		
-		function setPlaceholderText(isLoadEvent) {
+		me.setPlaceholderText = function (isLoadEvent) {
 			//jslog.debug(StringHelpers.sprintf('initiator: %s', this));
 			var isAutofocus = DOMHelpers.getAttributeValue(me.node, 'autofocus') != null;
 			
@@ -765,7 +987,7 @@ var html5Widgets = new function(){
 		function blurEvent(e) {
 			//jslog.debug('removed focus on ' + me.node.name)
 			CSSHelpers.removeClass(me.node, 'html5-hasFocus');
-			setPlaceholderText();
+			me.setPlaceholderText();
 		}
 		
 		function removePlaceholderText() {
@@ -779,7 +1001,7 @@ var html5Widgets = new function(){
 		function postValidationEvent(e, didValidate) {
 			////jslog.debug(StringHelpers.sprintf('post Validation: %s, didValidate = %s, has focus = %s', me.node.name, didValidate, CSSHelpers.isMemberOfClass(me.node, 'html5-hasFocus') )	)
 			if (!didValidate && !CSSHelpers.isMemberOfClass(me.node, 'html5-hasFocus')) {
-				setPlaceholderText();
+				me.setPlaceholderText();
 			} 
 		}
 		
@@ -815,6 +1037,7 @@ var html5Widgets = new function(){
 		 * @param {String} className - a CSS class name.
 		 */
 		me.addClass = function (obj, className) {
+			
 			if (blankRe.test(className)) {
 				return;
 			}
@@ -823,6 +1046,7 @@ var html5Widgets = new function(){
 			if (!me.isMemberOfClass(obj, className)) {
 				obj.className += " " + className;
 			}
+			
 		}
 		
 		/**
@@ -832,7 +1056,7 @@ var html5Widgets = new function(){
 		 * @param {Object} className - a CSS class name.
 		 */
 		me.removeClass = function (obj, className) {
-		
+			
 			if (blankRe.test(className)) {
 				return; 
 			}
@@ -844,10 +1068,9 @@ var html5Widgets = new function(){
 		
 		
 			if (obj.className) {
-				obj.className = oldClassName.replace(re, '');
+				obj.className = oldClassName.replace(re, ' ');
 			}
 		
-		
 		}
 		
 		/**
@@ -866,8 +1089,22 @@ var html5Widgets = new function(){
 		
 		
 		}
+		
+		/* from http://blog.stchur.com/2006/06/21/css-computed-style/ */
+		me.getCurrentStyle = function(obj)
+		{
+		  var computedStyle;
+		  if (typeof obj.currentStyle != 'undefined')
+		    { computedStyle = obj.currentStyle; }
+		  else
+		    { computedStyle = document.defaultView.getComputedStyle(obj, null); }
+		
+		  return computedStyle;
+		}
 	}
 	
+	
+	
 	var DOMHelpers = new function () {
 		var me = this;
 		
@@ -948,6 +1185,12 @@ var html5Widgets = new function(){
 			return null;
 		}
 		
+		me.removeNode = function (node) {
+			var parentNode = node.parentNode;
+			if (parentNode) {
+				parentNode.removeChild(node);
+			} 
+		}
 		
 	}
 	
@@ -1154,11 +1397,319 @@ var html5Widgets = new function(){
 	}
 }
 
+/*******************************************************************************
+ * This notice must be untouched at all times.
+ *
+ * This javascript library contains helper routines to assist with event 
+ * handling consistently among browsers
+ *
+ * EventHelpers.js v.1.4 available at http://www.useragentman.com/
+ *
+ * released under the MIT License:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *   
+ * Chagelog: 1.4: fix fireEvent to work correctly for IE9.
+ *
+ *******************************************************************************/
+var EventHelpers = new function(){
+    var me = this;
+    
+    var safariTimer;
+    var isSafari = /WebKit/i.test(navigator.userAgent);
+    var globalEvent;
+	
+	me.init = function () {
+		if (me.hasPageLoadHappened(arguments)) {
+			return;	
+		}
+		
+		/* This is for fireEvent */
+		if (document.createEvent) {
+			globalEvent = document.createEvent("HTMLEvents");
+		} else if (document.createEventObject){
+	        // dispatch for IE8 and lower.
+	        globalEvent = document.createEventObject();
+	    } 	
+		
+		me.docIsLoaded = true;
+	}
+	
+    /**
+     * Adds an event to the document.  Examples of usage:
+     * me.addEvent(window, "load", myFunction);
+     * me.addEvent(docunent, "keydown", keyPressedFunc);
+     * me.addEvent(document, "keyup", keyPressFunc);
+     *
+     * @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
+     * @author John Resig - http://ejohn.org/projects/flexible-javascript-events/
+     * @param {Object} obj - a javascript object.
+     * @param {String} evType - an event to attach to the object.
+     * @param {Function} fn - the function that is attached to the event.
+     */
+    me.addEvent = function(obj, evType, fn){
+    
+        if (obj.addEventListener) {
+            obj.addEventListener(evType, fn, false);
+        } else if (obj.attachEvent) {
+            obj['e' + evType + fn] = fn;
+            obj[evType + fn] = function(){
+                obj["e" + evType + fn](self.event);
+            }
+            obj.attachEvent("on" + evType, obj[evType + fn]);
+        }
+    }
+    
+    
+    /**
+     * Removes an event that is attached to a javascript object.
+     *
+     * @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
+     * @author John Resig - http://ejohn.org/projects/flexible-javascript-events/	 * @param {Object} obj - a javascript object.
+     * @param {String} evType - an event attached to the object.
+     * @param {Function} fn - the function that is called when the event fires.
+     */
+    me.removeEvent = function(obj, evType, fn){
+    
+        if (obj.removeEventListener) {
+            obj.removeEventListener(evType, fn, false);
+        } else if (obj.detachEvent) {
+            try {
+                obj.detachEvent("on" + evType, obj[evType + fn]);
+                obj[evType + fn] = null;
+                obj["e" + evType + fn] = null;
+            } 
+            catch (ex) {
+                // do nothing;
+            }
+        }
+    }
+    
+   
+    /** 
+     * Find the HTML object that fired an Event.
+     *
+     * @param {Object} e - an HTML object
+     * @return {Object} - the HTML object that fired the event.
+     */
+    me.getEventTarget = function(e){
+        // first, IE method for mouse events(also supported by Safari and Opera)
+        if (e.toElement) {
+            return e.toElement;
+            // W3C
+        } else if (e.currentTarget) {
+            return e.currentTarget;
+            
+            // MS way
+        } else if (e.srcElement) {
+            return e.srcElement;
+        } else {
+            return null;
+        }
+    }
+    
+    
+    
+    
+    /**
+     * Given an event fired by the keyboard, find the key associated with that event.
+     *
+     * @param {Object} e - an event object.
+     * @return {String} - the ASCII character code representing the key associated with the event.
+     */
+    me.getKey = function(e){
+        if (e.keyCode) {
+            return e.keyCode;
+        } else if (e.event && e.event.keyCode) {
+            return window.event.keyCode;
+        } else if (e.which) {
+            return e.which;
+        }
+    }
+    
+    
+    /** 
+     *  Will execute a function when the page's DOM has fully loaded (and before all attached images, iframes,
+     *  etc., are).
+     *
+     *  Usage:
+     *
+     *  EventHelpers.addPageLoadEvent('init');
+     *
+     *  where the function init() has this code at the beginning:
+     *
+     *  function init() {
+     *
+     *  if (EventHelpers.hasPageLoadHappened(arguments)) return;
+     *
+     *	// rest of code
+     *   ....
+     *  }
+     *
+     * @author This code is based off of code from http://dean.edwards.name/weblog/2005/09/busted/ by Dean
+     * Edwards, with a modification by me.
+     *
+     * @param {String} funcName - a string containing the function to be called.
+     */
+    me.addPageLoadEvent = function(funcName){
+    
+        var func = eval(funcName);
+        
+        // for Internet Explorer (using conditional comments)
+        /*@cc_on @*/
+        /*@if (@_win32)
+         pageLoadEventArray.push(func);
+         return;
+         /*@end @*/
+        if (isSafari) { // sniff
+            pageLoadEventArray.push(func);
+            
+            if (!safariTimer) {
+            
+                safariTimer = setInterval(function(){
+                    if (/loaded|complete/.test(document.readyState)) {
+                        clearInterval(safariTimer);
+                        
+                        /*
+                         * call the onload handler
+                         * func();
+                         */
+                        me.runPageLoadEvents();
+                        return;
+                    }
+                    set = true;
+                }, 10);
+            }
+            /* for Mozilla */
+        } else if (document.addEventListener) {
+            var x = document.addEventListener("DOMContentLoaded", func, null);
+            
+            /* Others */
+        } else {
+            me.addEvent(window, 'load', func);
+        }
+    }
+    
+    var pageLoadEventArray = new Array();
+    
+    me.runPageLoadEvents = function(e){
+        if (isSafari || e.srcElement.readyState == "complete") {
+        
+            for (var i = 0; i < pageLoadEventArray.length; i++) {
+                pageLoadEventArray[i]();
+            }
+        }
+    }
+    /**
+     * Determines if either addPageLoadEvent('funcName') or addEvent(window, 'load', funcName)
+     * has been executed.
+     *
+     * @see addPageLoadEvent
+     * @param {Function} funcArgs - the arguments of the containing. function
+     */
+    me.hasPageLoadHappened = function(funcArgs){
+        // If the function already been called, return true;
+        if (funcArgs.callee.done) 
+            return true;
+        
+        // flag this function so we don't do the same thing twice
+        funcArgs.callee.done = true;
+    }
+    
+    
+    
+    /**
+     * Used in an event method/function to indicate that the default behaviour of the event
+     * should *not* happen.
+     *
+     * @param {Object} e - an event object.
+     * @return {Boolean} - always false
+     */
+    me.preventDefault = function(e){
+    
+        if (e.preventDefault) {
+            e.preventDefault();
+        }
+        
+        try {
+            e.returnValue = false;
+        } 
+        catch (ex) {
+            // do nothing
+        }
+        
+    }
+    
+	
+	/* 
+	 * Fires an event manually.
+	 * @author Scott Andrew - http://www.scottandrew.com/weblog/articles/cbs-events
+	 * @author John Resig - http://ejohn.org/projects/flexible-javascript-events/	 
+	 * @param {Object} obj - a javascript object.
+	 * @param {String} evType - an event attached to the object.
+	 * @param {Function} fn - the function that is called when the event fires.
+	 * 
+	 */
+	me.fireEvent = function (element,event, options){
+		
+		if(!element) {
+			return;
+		}
+		
+		if (element.dispatchEvent) {
+	        // dispatch for firefox + ie9 + others
+	        globalEvent.initEvent(event, true, true); // event type,bubbling,cancelable
+	        return !element.dispatchEvent(globalEvent);
+	    } else if (document.createEventObject){
+			return element.fireEvent('on' + event, globalEvent)	
+		} else {
+			return false;
+		}
+	}
+	
+	/*
+	 * Detects whether the event "eventName" is supported on a tag with name 
+	 * "nodeName".  Based on code from 
+	 * http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
+	 */
+	me.isSupported = function (eventName, nodeName) {
+      var el = document.createElement(nodeName);
+      eventName = 'on' + eventName;
+      var isSupported = (eventName in el);
+      if (!isSupported) {
+        el.setAttribute(eventName, 'return;');
+        isSupported = typeof el[eventName] == 'function';
+      }
+      el = null;
+      return isSupported;
+    }
+    
+    
+    /* EventHelpers.init () */
+    function init(){
+        // Conditional comment alert: Do not remove comments.  Leave intact.
+        // The detection if the page is secure or not is important. If 
+        // this logic is removed, Internet Explorer will give security
+        // alerts.
+        /*@cc_on @*/
+        /*@if (@_win32)
+        
+         document.write('<script id="__ie_onload" defer src="' +
+        
+         ((location.protocol == 'https:') ? '//0' : 'javascript:void(0)') + '"><\/script>');
+        
+         var script = document.getElementById("__ie_onload");
+        
+         me.addEvent(script, 'readystatechange', me.runPageLoadEvents);
+        
+         /*@end @*/
+        
+    }
+    if (!window.html5Forms) {
+    	init();
+    }
+}
 
-
-
-
-
-
-EventHelpers.addPageLoadEvent('html5Widgets.init');
-
+if (!window.html5Forms) {
+	EventHelpers.addPageLoadEvent('EventHelpers.init');
+	EventHelpers.addPageLoadEvent('html5Widgets.init');
+}
diff --git a/shared/js/jscalendar-1.0/.DS_Store b/shared/js/jscalendar-1.0/.DS_Store
new file mode 100644
index 0000000..b42dd96
Binary files /dev/null and b/shared/js/jscalendar-1.0/.DS_Store differ
diff --git a/shared/js/jscalendar-1.0/altblue.html b/shared/js/jscalendar-1.0/altblue.html
index b8d462c..1de7463 100644
--- a/shared/js/jscalendar-1.0/altblue.html
+++ b/shared/js/jscalendar-1.0/altblue.html
@@ -11,7 +11,7 @@
     <script type="text/javascript" src="calendar-handler.js"></script>
   </head>
   <body>
-    <form action="#" method="get">
+    <form action="http://www.useragentman.com/testForm.php" method="get">
         <div>
             <input type="hidden" id="f_date" name="date" />
             <button type="reset" class="submit button" id="f_date_trigger">...</button>
diff --git a/shared/js/jscalendar-1.0/bugtest-hidden-selects.html b/shared/js/jscalendar-1.0/bugtest-hidden-selects.html
index df35337..fd955c0 100644
--- a/shared/js/jscalendar-1.0/bugtest-hidden-selects.html
+++ b/shared/js/jscalendar-1.0/bugtest-hidden-selects.html
@@ -77,7 +77,7 @@
 </head>
 
 <body>
-<form>
+<form action="http://www.useragentman.com/testForm.php">
 <b>Date:</b>
 <br>
 <input type="text" name="date1" id="sel1" size="30">
diff --git a/shared/js/jscalendar-1.0/index.html b/shared/js/jscalendar-1.0/index.html
index 1dc217c..1b02750 100644
--- a/shared/js/jscalendar-1.0/index.html
+++ b/shared/js/jscalendar-1.0/index.html
@@ -221,7 +221,7 @@ <h2><a href="http://www.dynarch.com/projects/calendar/"
 <tr valign="top">
 <td style="background: #ffa; padding: 5px; border: 1px solid #995;">
 
-<form action="#">
+<form action="http://www.useragentman.com/testForm.php">
 <div style="background: #995; color: #ffa; font-weight: bold; padding: 2px;">
 Popup examples
 </div>
diff --git a/shared/js/jscalendar-1.0/lang/calendar-cn.js b/shared/js/jscalendar-1.0/lang/calendar-cn.js
new file mode 100644
index 0000000..a0ef7c6
--- /dev/null
+++ b/shared/js/jscalendar-1.0/lang/calendar-cn.js
@@ -0,0 +1,123 @@
+// ** I18N
+
+// Calendar EN language
+// Author: Mihai Bazon, <mishoo@infoiasi.ro>
+// Encoding: any
+// Translator : Niko <nikoused@gmail.com>
+// Distributed under the same terms as the calendar itself.
+
+// For translators: please use UTF-8 if possible.  We strongly believe that
+// Unicode is the answer to a real internationalized world.  Also please
+// include your contact information in the header, as can be seen above.
+
+// full day names
+Calendar._DN = new Array
+("\u5468\u65e5",//\u5468\u65e5
+ "\u5468\u4e00",//\u5468\u4e00
+ "\u5468\u4e8c",//\u5468\u4e8c
+ "\u5468\u4e09",//\u5468\u4e09
+ "\u5468\u56db",//\u5468\u56db
+ "\u5468\u4e94",//\u5468\u4e94
+ "\u5468\u516d",//\u5468\u516d
+ "\u5468\u65e5");//\u5468\u65e5
+
+// Please note that the following array of short day names (and the same goes
+// for short month names, _SMN) isn't absolutely necessary.  We give it here
+// for exemplification on how one can customize the short day names, but if
+// they are simply the first N letters of the full name you can simply say:
+//
+//   Calendar._SDN_len = N; // short day name length
+//   Calendar._SMN_len = N; // short month name length
+//
+// If N = 3 then this is not needed either since we assume a value of 3 if not
+// present, to be compatible with translation files that were written before
+// this feature.
+
+// short day names
+Calendar._SDN = new Array
+("\u5468\u65e5",
+ "\u5468\u4e00",
+ "\u5468\u4e8c",
+ "\u5468\u4e09",
+ "\u5468\u56db",
+ "\u5468\u4e94",
+ "\u5468\u516d",
+ "\u5468\u65e5");
+
+// full month names
+Calendar._MN = new Array
+("\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708");
+
+// short month names
+Calendar._SMN = new Array
+("\u4e00\u6708",
+ "\u4e8c\u6708",
+ "\u4e09\u6708",
+ "\u56db\u6708",
+ "\u4e94\u6708",
+ "\u516d\u6708",
+ "\u4e03\u6708",
+ "\u516b\u6708",
+ "\u4e5d\u6708",
+ "\u5341\u6708",
+ "\u5341\u4e00\u6708",
+ "\u5341\u4e8c\u6708");
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "\u5173\u4e8e";
+
+Calendar._TT["ABOUT"] =
+"   DHTML \u65e5\u8d77/\u65f6\u95f4\u9009\u62e9\u63a7\u4ef6\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"For latest version visit: \u6700\u65b0\u7248\u672c\u8bf7\u767b\u9646http://www.dynarch.com/projects/calendar/\u5bdf\u770b\n" +
+"\u9075\u5faaGNU LGPL.  \u7ec6\u8282\u53c2\u9605 http://gnu.org/licenses/lgpl.html" +
+"\n\n" +
+"\u65e5\u671f\u9009\u62e9:\n" +
+"- \u70b9\u51fb\xab(\xbb)\u6309\u94ae\u9009\u62e9\u4e0a(\u4e0b)\u4e00\u5e74\u5ea6.\n" +
+"- \u70b9\u51fb" + String.fromCharCode(0x2039) + "(" + String.fromCharCode(0x203a) + ")\u6309\u94ae\u9009\u62e9\u4e0a(\u4e0b)\u4e2a\u6708\u4efd.\n" +
+"- \u957f\u65f6\u95f4\u6309\u7740\u6309\u94ae\u5c06\u51fa\u73b0\u66f4\u591a\u9009\u62e9\u9879.";
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"\u65f6\u95f4\u9009\u62e9:\n" +
+"-\u5728\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\u4e0a\u5355\u51fb\u9f20\u6807\u5de6\u952e\u6765\u589e\u52a0\u5f53\u524d\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\n" +
+"-\u5728\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2)\u4e0a\u6309\u4f4fShift\u952e\u540e\u5355\u51fb\u9f20\u6807\u5de6\u952e\u6765\u51cf\u5c11\u5f53\u524d\u65f6\u95f4\u90e8\u5206(\u5206\u6216\u8005\u79d2).";
+
+Calendar._TT["PREV_YEAR"] = "\u4e0a\u4e00\u5e74";
+Calendar._TT["PREV_MONTH"] = "\u4e0a\u4e2a\u6708";
+Calendar._TT["GO_TODAY"] = "\u5230\u4eca\u5929";
+Calendar._TT["NEXT_MONTH"] = "\u4e0b\u4e2a\u6708";
+Calendar._TT["NEXT_YEAR"] = "\u4e0b\u4e00\u5e74";
+Calendar._TT["SEL_DATE"] = "\u9009\u62e9\u65e5\u671f";
+Calendar._TT["DRAG_TO_MOVE"] = "\u62d6\u52a8";
+Calendar._TT["PART_TODAY"] = " (\u4eca\u5929)";
+
+// the following is to inform that "%s" is to be the first day of week
+// %s will be replaced with the day name.
+Calendar._TT["DAY_FIRST"] = "%s\u4e3a\u8fd9\u5468\u7684\u7b2c\u4e00\u5929";
+
+// This may be locale-dependent.  It specifies the week-end days, as an array
+// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
+// means Monday, etc.
+Calendar._TT["WEEKEND"] = "0,6";
+
+Calendar._TT["CLOSE"] = "\u5173\u95ed";
+Calendar._TT["TODAY"] = "\u4eca\u5929";
+Calendar._TT["TIME_PART"] = "(\u6309\u7740Shift\u952e)\u5355\u51fb\u6216\u62d6\u52a8\u6539\u53d8\u503c";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e\u65e5";
+
+Calendar._TT["WK"] = "\u5468";
+Calendar._TT["TIME"] = "\u65f6\u95f4:";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-cs.js b/shared/js/jscalendar-1.0/lang/calendar-cs.js
new file mode 100644
index 0000000..f6bbbeb
--- /dev/null
+++ b/shared/js/jscalendar-1.0/lang/calendar-cs.js
@@ -0,0 +1,65 @@
+/* 
+	calendar-cs-win.js
+	language: Czech
+	encoding: windows-1250
+	author: Lubos Jerabek (xnet@seznam.cz)
+	        Jan Uhlir (espinosa@centrum.cz)
+*/
+
+// ** I18N
+Calendar._DN  = new Array('NedÄle','PondÄlÃ­','ÃterÃ½','StÅeda','Ätvrtek','PÃ¡tek','Sobota','NedÄle');
+Calendar._SDN = new Array('Ne','Po','Ãt','St','Ät','PÃ¡','So','Ne');
+Calendar._MN  = new Array('Leden','Ãnor','BÅezen','Duben','KvÄten','Äerven','Äervenec','Srpen','ZÃ¡ÅÃ­','ÅÃ­jen','Listopad','Prosinec');
+Calendar._SMN = new Array('Led','Ãno','BÅe','Dub','KvÄ','Ärv','Ävc','Srp','ZÃ¡Å','ÅÃ­j','Lis','Pro');
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "O komponentÄ kalendÃ¡Å";
+Calendar._TT["TOGGLE"] = "ZmÄna prvnÃ­ho dne v tÃ½dnu";
+Calendar._TT["PREV_YEAR"] = "PÅedchozÃ­ rok (pÅidrÅ¾ pro menu)";
+Calendar._TT["PREV_MONTH"] = "PÅedchozÃ­ mÄsÃ­c (pÅidrÅ¾ pro menu)";
+Calendar._TT["GO_TODAY"] = "DneÅ¡nÃ­ datum";
+Calendar._TT["NEXT_MONTH"] = "DalÅ¡Ã­ mÄsÃ­c (pÅidrÅ¾ pro menu)";
+Calendar._TT["NEXT_YEAR"] = "DalÅ¡Ã­ rok (pÅidrÅ¾ pro menu)";
+Calendar._TT["SEL_DATE"] = "Vyber datum";
+Calendar._TT["DRAG_TO_MOVE"] = "ChyÅ¥ a tÃ¡hni, pro pÅesun";
+Calendar._TT["PART_TODAY"] = " (dnes)";
+Calendar._TT["MON_FIRST"] = "UkaÅ¾ jako prvnÃ­ PondÄlÃ­";
+//Calendar._TT["SUN_FIRST"] = "UkaÅ¾ jako prvnÃ­ NedÄli";
+
+Calendar._TT["ABOUT"] =
+"DHTML Date/Time Selector\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
+"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details." +
+"\n\n" +
+"VÃ½bÄr datumu:\n" +
+"- Use the \xab, \xbb buttons to select year\n" +
+"- PouÅ¾ijte tlaÄÃ­tka " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " k vÃ½bÄru mÄsÃ­ce\n" +
+"- PodrÅ¾te tlaÄÃ­tko myÅ¡i na jakÃ©mkoliv z tÄch tlaÄÃ­tek pro rychlejÅ¡Ã­ vÃ½bÄr.";
+
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"VÃ½bÄr Äasu:\n" +
+"- KliknÄte na jakoukoliv z ÄÃ¡stÃ­ vÃ½bÄru Äasu pro zvÃ½Å¡enÃ­.\n" +
+"- nebo Shift-click pro snÃ­Å¾enÃ­\n" +
+"- nebo kliknÄte a tÃ¡hnÄte pro rychlejÅ¡Ã­ vÃ½bÄr.";
+
+// the following is to inform that "%s" is to be the first day of week
+// %s will be replaced with the day name.
+Calendar._TT["DAY_FIRST"] = "Zobraz %s prvnÃ­";
+
+// This may be locale-dependent.  It specifies the week-end days, as an array
+// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
+// means Monday, etc.
+Calendar._TT["WEEKEND"] = "0,6";
+
+Calendar._TT["CLOSE"] = "ZavÅÃ­t";
+Calendar._TT["TODAY"] = "Dnes";
+Calendar._TT["TIME_PART"] = "(Shift-)Klikni nebo tÃ¡hni pro zmÄnu hodnoty";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "d.m.yy";
+Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
+
+Calendar._TT["WK"] = "wk";
+Calendar._TT["TIME"] = "Äas:";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-he.js b/shared/js/jscalendar-1.0/lang/calendar-he.js
new file mode 100644
index 0000000..7861217
--- /dev/null
+++ b/shared/js/jscalendar-1.0/lang/calendar-he.js
@@ -0,0 +1,123 @@
+// ** I18N
+
+// Calendar EN language
+// Author: Idan Sofer, <idan@idanso.dyndns.org>
+// Encoding: UTF-8
+// Distributed under the same terms as the calendar itself.
+
+// For translators: please use UTF-8 if possible.  We strongly believe that
+// Unicode is the answer to a real internationalized world.  Also please
+// include your contact information in the header, as can be seen above.
+
+// full day names
+Calendar._DN = new Array
+("×¨××©××",
+ "×©× ×",
+ "×©×××©×",
+ "×¨×××¢×",
+ "××××©×",
+ "×©××©×",
+ "×©××ª",
+ "×¨××©××");
+
+// Please note that the following array of short day names (and the same goes
+// for short month names, _SMN) isn't absolutely necessary.  We give it here
+// for exemplification on how one can customize the short day names, but if
+// they are simply the first N letters of the full name you can simply say:
+//
+//   Calendar._SDN_len = N; // short day name length
+//   Calendar._SMN_len = N; // short month name length
+//
+// If N = 3 then this is not needed either since we assume a value of 3 if not
+// present, to be compatible with translation files that were written before
+// this feature.
+
+// short day names
+Calendar._SDN = new Array
+("×",
+ "×",
+ "×",
+ "×",
+ "×",
+ "×",
+ "×©",
+ "×");
+
+// full month names
+Calendar._MN = new Array
+("×× ×××¨",
+ "×¤××¨×××¨",
+ "××¨×¥",
+ "××¤×¨××",
+ "×××",
+ "××× ×",
+ "××××",
+ "×××××¡×",
+ "×¡×¤××××¨",
+ "×××§××××¨",
+ "× ×××××¨",
+ "××¦×××¨");
+
+// short month names
+Calendar._SMN = new Array
+("×× ×",
+ "×¤××¨",
+ "××¨×¥",
+ "××¤×¨",
+ "×××",
+ "××× ",
+ "×××",
+ "×××",
+ "×¡×¤×",
+ "×××§",
+ "× ××",
+ "××¦×");
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "×××××ª ××©× ×ª××";
+
+Calendar._TT["ABOUT"] =
+"×××¨× ×ª××¨××/×©×¢× DHTML\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"××××¨×¡× ××××¨×× × ×××× × ×: http://www.dynarch.com/projects/calendar/\n" +
+"×××¤×¥ ×ª××ª ×××××× × GNU LGPL.  ×¢××× × http://gnu.org/licenses/lgpl.html ××¤×¨××× × ××¡×¤××." +
+"\n\n" +
+××××¨×ª ×ª××¨××:\n" +
+"- ××©×ª××© ×××¤×ª××¨×× \xab, \xbb ×××××¨×ª ×©× ×\n" +
+"- ××©×ª××© ×××¤×ª××¨×× " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ×××××¨×ª ××××©\n" +
+"- ××××§ ××¢×××¨ ××××¥ ××¢× ×××¤×ª××¨×× ××××××¨×× ××¢×× ×××××¨× ××××¨× ×××ª×¨.";
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"××××¨×ª ×××:\n" +
+"- ×××¥ ×¢× ×× ××× ××××§× ×××× ××× ××××¡××£\n" +
+"- ×× shift ××©×××× ×¢× ××××¦× ××× ××××¡××¨\n" +
+"- ×× ×××¥ ×××¨××¨ ××¤×¢××× ××××¨× ×××ª×¨.";
+
+Calendar._TT["PREV_YEAR"] = "×©× × ×§××××ª - ××××§ ××§×××ª ×ª×¤×¨××";
+Calendar._TT["PREV_MONTH"] = "××××© ×§××× - ××××§ ××§×××ª ×ª×¤×¨××";
+Calendar._TT["GO_TODAY"] = "×¢×××¨ ×××××";
+Calendar._TT["NEXT_MONTH"] = "××××© ××× - ××××§ ××ª×¤×¨××";
+Calendar._TT["NEXT_YEAR"] = "×©× × ×××× - ××××§ ××ª×¤×¨××";
+Calendar._TT["SEL_DATE"] = "×××¨ ×ª××¨××";
+Calendar._TT["DRAG_TO_MOVE"] = "××¨××¨ ×××××";
+Calendar._TT["PART_TODAY"] = " )××××(";
+
+// the following is to inform that "%s" is to be the first day of week
+// %s will be replaced with the day name.
+Calendar._TT["DAY_FIRST"] = "××¦× %s ×§×××";
+
+// This may be locale-dependent.  It specifies the week-end days, as an array
+// of comma-separated numbers.  The numbers are from 0 to 6: 0 means Sunday, 1
+// means Monday, etc.
+Calendar._TT["WEEKEND"] = "6";
+
+Calendar._TT["CLOSE"] = "×¡×××¨";
+Calendar._TT["TODAY"] = "××××";
+Calendar._TT["TIME_PART"] = "(×©××¤×-)×××¥ ×××¨××¨ ××× ××©× ××ª ×¢×¨×";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
+
+Calendar._TT["WK"] = "wk";
+Calendar._TT["TIME"] = "×©×¢×::";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-hr-old.js b/shared/js/jscalendar-1.0/lang/calendar-hr-old.js
new file mode 100644
index 0000000..6c27f60
Binary files /dev/null and b/shared/js/jscalendar-1.0/lang/calendar-hr-old.js differ
diff --git a/shared/js/jscalendar-1.0/lang/calendar-hr.js b/shared/js/jscalendar-1.0/lang/calendar-hr.js
index 6c27f60..d569cfd 100644
Binary files a/shared/js/jscalendar-1.0/lang/calendar-hr.js and b/shared/js/jscalendar-1.0/lang/calendar-hr.js differ
diff --git a/shared/js/jscalendar-1.0/lang/calendar-ko.js b/shared/js/jscalendar-1.0/lang/calendar-ko.js
index 8cddf58..035dd74 100644
--- a/shared/js/jscalendar-1.0/lang/calendar-ko.js
+++ b/shared/js/jscalendar-1.0/lang/calendar-ko.js
@@ -14,14 +14,14 @@
 // full day names
 
 Calendar._DN = new Array
-("ÀÏ¿äÀÏ",
- "¿ù¿äÀÏ",
- "È­¿äÀÏ",
- "¼ö¿äÀÏ",
- "¸ñ¿äÀÏ",
- "±Ý¿äÀÏ",
- "Åä¿äÀÏ",
- "ÀÏ¿äÀÏ");
+("ì¼ìì¼",
+ "ììì¼",
+ "íìì¼",
+ "ììì¼",
+ "ëª©ìì¼",
+ "ê¸ìì¼",
+ "í ìì¼",
+ "ì¼ìì¼");
 
 // Please note that the following array of short day names (and the same goes
 // for short month names, _SMN) isn't absolutely necessary.  We give it here
@@ -37,29 +37,29 @@ Calendar._DN = new Array
 
 // short day names
 Calendar._SDN = new Array
-("ÀÏ",
- "¿ù",
- "È­",
- "¼ö",
- "¸ñ",
- "±Ý",
- "Åä",
- "ÀÏ");
+("ì¼",
+ "ì",
+ "í",
+ "ì",
+ "ëª©",
+ "ê¸",
+ "í ",
+ "ì¼");
 
 // full month names
 Calendar._MN = new Array
-("1¿ù",
- "2¿ù",
- "3¿ù",
- "4¿ù",
- "5¿ù",
- "6¿ù",
- "7¿ù",
- "8¿ù",
- "9¿ù",
- "10¿ù",
- "11¿ù",
- "12¿ù");
+("1ì",
+ "2ì",
+ "3ì",
+ "4ì",
+ "5ì",
+ "6ì",
+ "7ì",
+ "8ì",
+ "9ì",
+ "10ì",
+ "11ì",
+ "12ì");
 
 // short month names
 Calendar._SMN = new Array
@@ -78,43 +78,43 @@ Calendar._SMN = new Array
 
 // tooltips
 Calendar._TT = {};
-Calendar._TT["INFO"] = "calendar ¿¡ ´ëÇØ¼­";
+Calendar._TT["INFO"] = "calendar ì ëí´ì";
 
 Calendar._TT["ABOUT"] =
 "DHTML Date/Time Selector\n" +
 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
 "\n"+
-"ÃÖ½Å ¹öÀüÀ» ¹ÞÀ¸½Ã·Á¸é http://www.dynarch.com/projects/calendar/ ¿¡ ¹æ¹®ÇÏ¼¼¿ä\n" +
+"ìµì  ë²ì ì ë°ì¼ìë ¤ë©´ http://www.dynarch.com/projects/calendar/ ì ë°©ë¬¸íì¸ì\n" +
 "\n"+
-"GNU LGPL ¶óÀÌ¼¾½º·Î ¹èÆ÷µË´Ï´Ù. \n"+
-"¶óÀÌ¼¾½º¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº http://gnu.org/licenses/lgpl.html À» ÀÐÀ¸¼¼¿ä." +
+"GNU LGPL ë¼ì´ì¼ì¤ë¡ ë°°í¬ë©ëë¤. \n"+
+"ë¼ì´ì¼ì¤ì ëí ìì¸í ë´ì©ì http://gnu.org/licenses/lgpl.html ì ì½ì¼ì¸ì." +
 "\n\n" +
-"³¯Â¥ ¼±ÅÃ:\n" +
-"- ¿¬µµ¸¦ ¼±ÅÃÇÏ·Á¸é \xab, \xbb ¹öÆ°À» »ç¿ëÇÕ´Ï´Ù\n" +
-"- ´ÞÀ» ¼±ÅÃÇÏ·Á¸é " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ¹öÆ°À» ´©¸£¼¼¿ä\n" +
-"- °è¼Ó ´©¸£°í ÀÖÀ¸¸é À§ °ªµéÀ» ºü¸£°Ô ¼±ÅÃÇÏ½Ç ¼ö ÀÖ½À´Ï´Ù.";
+"ë ì§ ì í:\n" +
+"- ì°ëë¥¼ ì ííë ¤ë©´ \xab, \xbb ë²í¼ì ì¬ì©í©ëë¤\n" +
+"- ë¬ì ì ííë ¤ë©´ " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ë²í¼ì ëë¥´ì¸ì\n" +
+"- ê³ì ëë¥´ê³  ìì¼ë©´ ì ê°ë¤ì ë¹ ë¥´ê² ì ííì¤ ì ììµëë¤.";
 Calendar._TT["ABOUT_TIME"] = "\n\n" +
-"½Ã°£ ¼±ÅÃ:\n" +
-"- ¸¶¿ì½º·Î ´©¸£¸é ½Ã°£ÀÌ Áõ°¡ÇÕ´Ï´Ù\n" +
-"- Shift Å°¿Í ÇÔ²² ´©¸£¸é °¨¼ÒÇÕ´Ï´Ù\n" +
-"- ´©¸¥ »óÅÂ¿¡¼­ ¸¶¿ì½º¸¦ ¿òÁ÷ÀÌ¸é Á» ´õ ºü¸£°Ô °ªÀÌ º¯ÇÕ´Ï´Ù.\n";
+"ìê° ì í:\n" +
+"- ë§ì°ì¤ë¡ ëë¥´ë©´ ìê°ì´ ì¦ê°í©ëë¤\n" +
+"- Shift í¤ì í¨ê» ëë¥´ë©´ ê°ìí©ëë¤\n" +
+"- ëë¥¸ ìíìì ë§ì°ì¤ë¥¼ ìì§ì´ë©´ ì¢ ë ë¹ ë¥´ê² ê°ì´ ë³í©ëë¤.\n";
 
-Calendar._TT["PREV_YEAR"] = "Áö³­ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
-Calendar._TT["PREV_MONTH"] = "Áö³­ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
-Calendar._TT["GO_TODAY"] = "¿À´Ã ³¯Â¥·Î";
-Calendar._TT["NEXT_MONTH"] = "´ÙÀ½ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
-Calendar._TT["NEXT_YEAR"] = "´ÙÀ½ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
-Calendar._TT["SEL_DATE"] = "³¯Â¥¸¦ ¼±ÅÃÇÏ¼¼¿ä";
-Calendar._TT["DRAG_TO_MOVE"] = "¸¶¿ì½º µå·¡±×·Î ÀÌµ¿ ÇÏ¼¼¿ä";
-Calendar._TT["PART_TODAY"] = " (¿À´Ã)";
-Calendar._TT["MON_FIRST"] = "¿ù¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î";
-Calendar._TT["SUN_FIRST"] = "ÀÏ¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î";
-Calendar._TT["CLOSE"] = "´Ý±â";
-Calendar._TT["TODAY"] = "¿À´Ã";
-Calendar._TT["TIME_PART"] = "(Shift-)Å¬¸¯ ¶Ç´Â µå·¡±× ÇÏ¼¼¿ä";
+Calendar._TT["PREV_YEAR"] = "ì§ë í´ (ê¸¸ê² ëë¥´ë©´ ëª©ë¡)";
+Calendar._TT["PREV_MONTH"] = "ì§ë ë¬ (ê¸¸ê² ëë¥´ë©´ ëª©ë¡)";
+Calendar._TT["GO_TODAY"] = "ì¤ë ë ì§ë¡";
+Calendar._TT["NEXT_MONTH"] = "ë¤ì ë¬ (ê¸¸ê² ëë¥´ë©´ ëª©ë¡)";
+Calendar._TT["NEXT_YEAR"] = "ë¤ì í´ (ê¸¸ê² ëë¥´ë©´ ëª©ë¡)";
+Calendar._TT["SEL_DATE"] = "ë ì§ë¥¼ ì ííì¸ì";
+Calendar._TT["DRAG_TO_MOVE"] = "ë§ì°ì¤ ëëê·¸ë¡ ì´ë íì¸ì";
+Calendar._TT["PART_TODAY"] = " (ì¤ë)";
+Calendar._TT["MON_FIRST"] = "ììì¼ì í ì£¼ì ìì ìì¼ë¡";
+Calendar._TT["SUN_FIRST"] = "ì¼ìì¼ì í ì£¼ì ìì ìì¼ë¡";
+Calendar._TT["CLOSE"] = "ë«ê¸°";
+Calendar._TT["TODAY"] = "ì¤ë";
+Calendar._TT["TIME_PART"] = "(Shift-)í´ë¦­ ëë ëëê·¸ íì¸ì";
 
 // date formats
 Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
 Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]";
 
-Calendar._TT["WK"] = "ÁÖ";
+Calendar._TT["WK"] = "ì£¼";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-ko.old.js b/shared/js/jscalendar-1.0/lang/calendar-ko.old.js
new file mode 100644
index 0000000..8cddf58
--- /dev/null
+++ b/shared/js/jscalendar-1.0/lang/calendar-ko.old.js
@@ -0,0 +1,120 @@
+// ** I18N
+
+// Calendar EN language
+// Author: Mihai Bazon, <mihai_bazon@yahoo.com>
+// Translation: Yourim Yi <yyi@yourim.net>
+// Encoding: EUC-KR
+// lang : ko
+// Distributed under the same terms as the calendar itself.
+
+// For translators: please use UTF-8 if possible.  We strongly believe that
+// Unicode is the answer to a real internationalized world.  Also please
+// include your contact information in the header, as can be seen above.
+
+// full day names
+
+Calendar._DN = new Array
+("ÀÏ¿äÀÏ",
+ "¿ù¿äÀÏ",
+ "È­¿äÀÏ",
+ "¼ö¿äÀÏ",
+ "¸ñ¿äÀÏ",
+ "±Ý¿äÀÏ",
+ "Åä¿äÀÏ",
+ "ÀÏ¿äÀÏ");
+
+// Please note that the following array of short day names (and the same goes
+// for short month names, _SMN) isn't absolutely necessary.  We give it here
+// for exemplification on how one can customize the short day names, but if
+// they are simply the first N letters of the full name you can simply say:
+//
+//   Calendar._SDN_len = N; // short day name length
+//   Calendar._SMN_len = N; // short month name length
+//
+// If N = 3 then this is not needed either since we assume a value of 3 if not
+// present, to be compatible with translation files that were written before
+// this feature.
+
+// short day names
+Calendar._SDN = new Array
+("ÀÏ",
+ "¿ù",
+ "È­",
+ "¼ö",
+ "¸ñ",
+ "±Ý",
+ "Åä",
+ "ÀÏ");
+
+// full month names
+Calendar._MN = new Array
+("1¿ù",
+ "2¿ù",
+ "3¿ù",
+ "4¿ù",
+ "5¿ù",
+ "6¿ù",
+ "7¿ù",
+ "8¿ù",
+ "9¿ù",
+ "10¿ù",
+ "11¿ù",
+ "12¿ù");
+
+// short month names
+Calendar._SMN = new Array
+("1",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12");
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "calendar ¿¡ ´ëÇØ¼­";
+
+Calendar._TT["ABOUT"] =
+"DHTML Date/Time Selector\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"\n"+
+"ÃÖ½Å ¹öÀüÀ» ¹ÞÀ¸½Ã·Á¸é http://www.dynarch.com/projects/calendar/ ¿¡ ¹æ¹®ÇÏ¼¼¿ä\n" +
+"\n"+
+"GNU LGPL ¶óÀÌ¼¾½º·Î ¹èÆ÷µË´Ï´Ù. \n"+
+"¶óÀÌ¼¾½º¿¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº http://gnu.org/licenses/lgpl.html À» ÀÐÀ¸¼¼¿ä." +
+"\n\n" +
+"³¯Â¥ ¼±ÅÃ:\n" +
+"- ¿¬µµ¸¦ ¼±ÅÃÇÏ·Á¸é \xab, \xbb ¹öÆ°À» »ç¿ëÇÕ´Ï´Ù\n" +
+"- ´ÞÀ» ¼±ÅÃÇÏ·Á¸é " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " ¹öÆ°À» ´©¸£¼¼¿ä\n" +
+"- °è¼Ó ´©¸£°í ÀÖÀ¸¸é À§ °ªµéÀ» ºü¸£°Ô ¼±ÅÃÇÏ½Ç ¼ö ÀÖ½À´Ï´Ù.";
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"½Ã°£ ¼±ÅÃ:\n" +
+"- ¸¶¿ì½º·Î ´©¸£¸é ½Ã°£ÀÌ Áõ°¡ÇÕ´Ï´Ù\n" +
+"- Shift Å°¿Í ÇÔ²² ´©¸£¸é °¨¼ÒÇÕ´Ï´Ù\n" +
+"- ´©¸¥ »óÅÂ¿¡¼­ ¸¶¿ì½º¸¦ ¿òÁ÷ÀÌ¸é Á» ´õ ºü¸£°Ô °ªÀÌ º¯ÇÕ´Ï´Ù.\n";
+
+Calendar._TT["PREV_YEAR"] = "Áö³­ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
+Calendar._TT["PREV_MONTH"] = "Áö³­ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
+Calendar._TT["GO_TODAY"] = "¿À´Ã ³¯Â¥·Î";
+Calendar._TT["NEXT_MONTH"] = "´ÙÀ½ ´Þ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
+Calendar._TT["NEXT_YEAR"] = "´ÙÀ½ ÇØ (±æ°Ô ´©¸£¸é ¸ñ·Ï)";
+Calendar._TT["SEL_DATE"] = "³¯Â¥¸¦ ¼±ÅÃÇÏ¼¼¿ä";
+Calendar._TT["DRAG_TO_MOVE"] = "¸¶¿ì½º µå·¡±×·Î ÀÌµ¿ ÇÏ¼¼¿ä";
+Calendar._TT["PART_TODAY"] = " (¿À´Ã)";
+Calendar._TT["MON_FIRST"] = "¿ù¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î";
+Calendar._TT["SUN_FIRST"] = "ÀÏ¿äÀÏÀ» ÇÑ ÁÖÀÇ ½ÃÀÛ ¿äÀÏ·Î";
+Calendar._TT["CLOSE"] = "´Ý±â";
+Calendar._TT["TODAY"] = "¿À´Ã";
+Calendar._TT["TIME_PART"] = "(Shift-)Å¬¸¯ ¶Ç´Â µå·¡±× ÇÏ¼¼¿ä";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%b/%e [%a]";
+
+Calendar._TT["WK"] = "ÁÖ";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-lt.js b/shared/js/jscalendar-1.0/lang/calendar-lt.js
index 43b93d6..d39653b 100644
--- a/shared/js/jscalendar-1.0/lang/calendar-lt.js
+++ b/shared/js/jscalendar-1.0/lang/calendar-lt.js
@@ -2,7 +2,7 @@
 
 // Calendar LT language
 // Author: Martynas Majeris, <martynas@solmetra.lt>
-// Encoding: Windows-1257
+// Encoding: UTF-8
 // Distributed under the same terms as the calendar itself.
 
 // For translators: please use UTF-8 if possible.  We strongly believe that
@@ -14,10 +14,10 @@ Calendar._DN = new Array
 ("Sekmadienis",
  "Pirmadienis",
  "Antradienis",
- "Treèiadienis",
+ "TreÄiadienis",
  "Ketvirtadienis",
  "Pentadienis",
- "Ðeðtadienis",
+ "Å eÅ¡tadienis",
  "Sekmadienis");
 
 // Please note that the following array of short day names (and the same goes
@@ -40,7 +40,7 @@ Calendar._SDN = new Array
  "Tre",
  "Ket",
  "Pen",
- "Ðeð",
+ "Å eÅ¡",
  "Sek");
 
 // full month names
@@ -49,11 +49,11 @@ Calendar._MN = new Array
  "Vasaris",
  "Kovas",
  "Balandis",
- "Geguþë",
- "Birþelis",
+ "GeguÅ¾Ä",
+ "BirÅ¾elis",
  "Liepa",
- "Rugpjûtis",
- "Rugsëjis",
+ "RugpjÅ«tis",
+ "RugsÄjis",
  "Spalis",
  "Lapkritis",
  "Gruodis");
@@ -75,36 +75,36 @@ Calendar._SMN = new Array
 
 // tooltips
 Calendar._TT = {};
-Calendar._TT["INFO"] = "Apie kalendoriø";
+Calendar._TT["INFO"] = "Apie kalendoriÅ³";
 
 Calendar._TT["ABOUT"] =
 "DHTML Date/Time Selector\n" +
 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
-"Naujausià versijà rasite: http://www.dynarch.com/projects/calendar/\n" +
-"Platinamas pagal GNU LGPL licencijà. Aplankykite http://gnu.org/licenses/lgpl.html" +
+"NaujausiÄ versijÄ rasite: http://www.dynarch.com/projects/calendar/\n" +
+"Platinamas pagal GNU LGPL licencijÄ. Aplankykite http://gnu.org/licenses/lgpl.html" +
 "\n\n" +
 "Datos pasirinkimas:\n" +
-"- Metø pasirinkimas: \xab, \xbb\n" +
-"- Mënesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" +
-"- Nuspauskite ir laikykite pelës klaviðà greitesniam pasirinkimui.";
+"- MetÅ³ pasirinkimas: \xab, \xbb\n" +
+"- MÄnesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" +
+"- Nuspauskite ir laikykite pelÄs klaviÅ¡Ä greitesniam pasirinkimui.";
 Calendar._TT["ABOUT_TIME"] = "\n\n" +
 "Laiko pasirinkimas:\n" +
-"- Spustelkite ant valandø arba minuèiø - skaièus padidës vienetu.\n" +
-"- Jei spausite kartu su Shift, skaièius sumaþës.\n" +
-"- Greitam pasirinkimui spustelkite ir pajudinkite pelæ.";
+"- Spustelkite ant valandÅ³ arba minuÄiÅ³ - skaiÄius padidÄs vienetu.\n" +
+"- Jei spausite kartu su Shift, skaiÄius sumaÅ¾Äs.\n" +
+"- Greitam pasirinkimui spustelkite ir pajudinkite pelÄ.";
 
 Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)";
-Calendar._TT["PREV_MONTH"] = "Ankstesnis mënuo (laikykite, jei norite meniu)";
-Calendar._TT["GO_TODAY"] = "Pasirinkti ðiandienà";
-Calendar._TT["NEXT_MONTH"] = "Kitas mënuo (laikykite, jei norite meniu)";
+Calendar._TT["PREV_MONTH"] = "Ankstesnis mÄnuo (laikykite, jei norite meniu)";
+Calendar._TT["GO_TODAY"] = "Pasirinkti Å¡iandienÄ";
+Calendar._TT["NEXT_MONTH"] = "Kitas mÄnuo (laikykite, jei norite meniu)";
 Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)";
-Calendar._TT["SEL_DATE"] = "Pasirinkite datà";
+Calendar._TT["SEL_DATE"] = "Pasirinkite datÄ";
 Calendar._TT["DRAG_TO_MOVE"] = "Tempkite";
-Calendar._TT["PART_TODAY"] = " (ðiandien)";
-Calendar._TT["MON_FIRST"] = "Pirma savaitës diena - pirmadienis";
-Calendar._TT["SUN_FIRST"] = "Pirma savaitës diena - sekmadienis";
-Calendar._TT["CLOSE"] = "Uþdaryti";
-Calendar._TT["TODAY"] = "Ðiandien";
+Calendar._TT["PART_TODAY"] = " (Å¡iandien)";
+Calendar._TT["MON_FIRST"] = "Pirma savaitÄs diena - pirmadienis";
+Calendar._TT["SUN_FIRST"] = "Pirma savaitÄs diena - sekmadienis";
+Calendar._TT["CLOSE"] = "UÅ¾daryti";
+Calendar._TT["TODAY"] = "Å iandien";
 Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti";
 
 // date formats
diff --git a/shared/js/jscalendar-1.0/lang/calendar-lt.old.js b/shared/js/jscalendar-1.0/lang/calendar-lt.old.js
new file mode 100644
index 0000000..43b93d6
--- /dev/null
+++ b/shared/js/jscalendar-1.0/lang/calendar-lt.old.js
@@ -0,0 +1,114 @@
+// ** I18N
+
+// Calendar LT language
+// Author: Martynas Majeris, <martynas@solmetra.lt>
+// Encoding: Windows-1257
+// Distributed under the same terms as the calendar itself.
+
+// For translators: please use UTF-8 if possible.  We strongly believe that
+// Unicode is the answer to a real internationalized world.  Also please
+// include your contact information in the header, as can be seen above.
+
+// full day names
+Calendar._DN = new Array
+("Sekmadienis",
+ "Pirmadienis",
+ "Antradienis",
+ "Treèiadienis",
+ "Ketvirtadienis",
+ "Pentadienis",
+ "Ðeðtadienis",
+ "Sekmadienis");
+
+// Please note that the following array of short day names (and the same goes
+// for short month names, _SMN) isn't absolutely necessary.  We give it here
+// for exemplification on how one can customize the short day names, but if
+// they are simply the first N letters of the full name you can simply say:
+//
+//   Calendar._SDN_len = N; // short day name length
+//   Calendar._SMN_len = N; // short month name length
+//
+// If N = 3 then this is not needed either since we assume a value of 3 if not
+// present, to be compatible with translation files that were written before
+// this feature.
+
+// short day names
+Calendar._SDN = new Array
+("Sek",
+ "Pir",
+ "Ant",
+ "Tre",
+ "Ket",
+ "Pen",
+ "Ðeð",
+ "Sek");
+
+// full month names
+Calendar._MN = new Array
+("Sausis",
+ "Vasaris",
+ "Kovas",
+ "Balandis",
+ "Geguþë",
+ "Birþelis",
+ "Liepa",
+ "Rugpjûtis",
+ "Rugsëjis",
+ "Spalis",
+ "Lapkritis",
+ "Gruodis");
+
+// short month names
+Calendar._SMN = new Array
+("Sau",
+ "Vas",
+ "Kov",
+ "Bal",
+ "Geg",
+ "Bir",
+ "Lie",
+ "Rgp",
+ "Rgs",
+ "Spa",
+ "Lap",
+ "Gru");
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "Apie kalendoriø";
+
+Calendar._TT["ABOUT"] =
+"DHTML Date/Time Selector\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"Naujausià versijà rasite: http://www.dynarch.com/projects/calendar/\n" +
+"Platinamas pagal GNU LGPL licencijà. Aplankykite http://gnu.org/licenses/lgpl.html" +
+"\n\n" +
+"Datos pasirinkimas:\n" +
+"- Metø pasirinkimas: \xab, \xbb\n" +
+"- Mënesio pasirinkimas: " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" +
+"- Nuspauskite ir laikykite pelës klaviðà greitesniam pasirinkimui.";
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"Laiko pasirinkimas:\n" +
+"- Spustelkite ant valandø arba minuèiø - skaièus padidës vienetu.\n" +
+"- Jei spausite kartu su Shift, skaièius sumaþës.\n" +
+"- Greitam pasirinkimui spustelkite ir pajudinkite pelæ.";
+
+Calendar._TT["PREV_YEAR"] = "Ankstesni metai (laikykite, jei norite meniu)";
+Calendar._TT["PREV_MONTH"] = "Ankstesnis mënuo (laikykite, jei norite meniu)";
+Calendar._TT["GO_TODAY"] = "Pasirinkti ðiandienà";
+Calendar._TT["NEXT_MONTH"] = "Kitas mënuo (laikykite, jei norite meniu)";
+Calendar._TT["NEXT_YEAR"] = "Kiti metai (laikykite, jei norite meniu)";
+Calendar._TT["SEL_DATE"] = "Pasirinkite datà";
+Calendar._TT["DRAG_TO_MOVE"] = "Tempkite";
+Calendar._TT["PART_TODAY"] = " (ðiandien)";
+Calendar._TT["MON_FIRST"] = "Pirma savaitës diena - pirmadienis";
+Calendar._TT["SUN_FIRST"] = "Pirma savaitës diena - sekmadienis";
+Calendar._TT["CLOSE"] = "Uþdaryti";
+Calendar._TT["TODAY"] = "Ðiandien";
+Calendar._TT["TIME_PART"] = "Spustelkite arba tempkite jei norite pakeisti";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%A, %Y-%m-%d";
+
+Calendar._TT["WK"] = "sav";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-pl.js b/shared/js/jscalendar-1.0/lang/calendar-pl.js
index 76e0551..6b8ca67 100644
--- a/shared/js/jscalendar-1.0/lang/calendar-pl.js
+++ b/shared/js/jscalendar-1.0/lang/calendar-pl.js
@@ -1,19 +1,55 @@
-// ** I18N
+ï»¿// ** I18N
+
 // Calendar PL language
-// Author: Artur Filipiak, <imagen@poczta.fm>
-// January, 2004
-// Encoding: UTF-8
-Calendar._DN = new Array
-("Niedziela", "PoniedziaÅek", "Wtorek", "Åroda", "Czwartek", "PiÄtek", "Sobota", "Niedziela");
+// Author: Dariusz Pietrzak, <eyck@ghost.anime.pl>
+// Author: Janusz Piwowarski, <jpiw@go2.pl>
+// Encoding: utf-8
+// Distributed under the same terms as the calendar itself.
 
+Calendar._DN = new Array
+("Niedziela",
+ "PoniedziaÅek",
+ "Wtorek",
+ "Åroda",
+ "Czwartek",
+ "PiÄtek",
+ "Sobota",
+ "Niedziela");
 Calendar._SDN = new Array
-("N", "Pn", "Wt", "År", "Cz", "Pt", "So", "N");
-
+("Nie",
+ "Pn",
+ "Wt",
+ "År",
+ "Cz",
+ "Pt",
+ "So",
+ "Nie");
 Calendar._MN = new Array
-("StyczeÅ", "Luty", "Marzec", "KwiecieÅ", "Maj", "Czerwiec", "Lipiec", "SierpieÅ", "WrzesieÅ", "PaÅºdziernik", "Listopad", "GrudzieÅ");
-
+("StyczeÅ",
+ "Luty",
+ "Marzec",
+ "KwiecieÅ",
+ "Maj",
+ "Czerwiec",
+ "Lipiec",
+ "SierpieÅ",
+ "WrzesieÅ",
+ "PaÅºdziernik",
+ "Listopad",
+ "GrudzieÅ");
 Calendar._SMN = new Array
-("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "PaÅº", "Lis", "Gru");
+("Sty",
+ "Lut",
+ "Mar",
+ "Kwi",
+ "Maj",
+ "Cze",
+ "Lip",
+ "Sie",
+ "Wrz",
+ "PaÅº",
+ "Lis",
+ "Gru");
 
 // tooltips
 Calendar._TT = {};
@@ -22,35 +58,36 @@ Calendar._TT["INFO"] = "O kalendarzu";
 Calendar._TT["ABOUT"] =
 "DHTML Date/Time Selector\n" +
 "(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
-"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
-"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details." +
+"Aby pobraÄ najnowszÄ wersjÄ, odwiedÅº: http://www.dynarch.com/projects/calendar/\n" +
+"DostÄpny na licencji GNU LGPL. Zobacz szczegÃ³Åy na http://gnu.org/licenses/lgpl.html." +
 "\n\n" +
 "WybÃ³r daty:\n" +
-"- aby wybraÄ rok uÅ¼yj przyciskÃ³w \xab, \xbb\n" +
-"- aby wybraÄ miesiÄc uÅ¼yj przyciskÃ³w " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" +
-"- aby przyspieszyÄ wybÃ³r przytrzymaj wciÅniÄty przycisk myszy nad ww. przyciskami.";
+"- UÅ¼yj przyciskÃ³w \xab, \xbb by wybraÄ rok\n" +
+"- UÅ¼yj przyciskÃ³w " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " by wybraÄ miesiÄc\n" +
+"- Przytrzymaj klawisz myszy nad jednym z powyÅ¼szych przyciskÃ³w dla szybszego wyboru.";
 Calendar._TT["ABOUT_TIME"] = "\n\n" +
 "WybÃ³r czasu:\n" +
-"- aby zwiÄkszyÄ wartoÅÄ kliknij na dowolnym elemencie selekcji czasu\n" +
-"- aby zmniejszyÄ wartoÅÄ uÅ¼yj dodatkowo klawisza Shift\n" +
-"- moÅ¼esz rÃ³wnieÅ¼ poruszaÄ myszkÄ w lewo i prawo wraz z wciÅniÄtym lewym klawiszem.";
+"- Kliknij na jednym z pÃ³l czasu by zwiÄkszyÄ jego wartoÅÄ\n" +
+"- lub kliknij trzymajÄc Shift by zmiejszyÄ jego wartoÅÄ\n" +
+"- lub kliknij i przeciÄgnij dla szybszego wyboru.";
 
-Calendar._TT["PREV_YEAR"] = "Poprz. rok (przytrzymaj dla menu)";
-Calendar._TT["PREV_MONTH"] = "Poprz. miesiÄc (przytrzymaj dla menu)";
-Calendar._TT["GO_TODAY"] = "PokaÅ¼ dziÅ";
-Calendar._TT["NEXT_MONTH"] = "Nast. miesiÄc (przytrzymaj dla menu)";
-Calendar._TT["NEXT_YEAR"] = "Nast. rok (przytrzymaj dla menu)";
+//Calendar._TT["TOGGLE"] = "ZmieÅ pierwszy dzieÅ tygodnia";
+Calendar._TT["PREV_YEAR"] = "Poprzedni rok (przytrzymaj dla menu)";
+Calendar._TT["PREV_MONTH"] = "Poprzedni miesiÄc (przytrzymaj dla menu)";
+Calendar._TT["GO_TODAY"] = "IdÅº do dzisiaj";
+Calendar._TT["NEXT_MONTH"] = "NastÄpny miesiÄc (przytrzymaj dla menu)";
+Calendar._TT["NEXT_YEAR"] = "NastÄpny rok (przytrzymaj dla menu)";
 Calendar._TT["SEL_DATE"] = "Wybierz datÄ";
-Calendar._TT["DRAG_TO_MOVE"] = "PrzesuÅ okienko";
-Calendar._TT["PART_TODAY"] = " (dziÅ)";
-Calendar._TT["MON_FIRST"] = "PokaÅ¼ PoniedziaÅek jako pierwszy";
-Calendar._TT["SUN_FIRST"] = "PokaÅ¼ NiedzielÄ jako pierwszÄ";
+Calendar._TT["DRAG_TO_MOVE"] = "PrzeciÄgnij by przesunÄÄ";
+Calendar._TT["PART_TODAY"] = " (dzisiaj)";
+Calendar._TT["MON_FIRST"] = "WyÅwietl poniedziaÅek jako pierwszy";
+Calendar._TT["SUN_FIRST"] = "WyÅwietl niedzielÄ jako pierwszÄ";
 Calendar._TT["CLOSE"] = "Zamknij";
-Calendar._TT["TODAY"] = "DziÅ";
-Calendar._TT["TIME_PART"] = "(Shift-)klik | drag, aby zmieniÄ wartoÅÄ";
+Calendar._TT["TODAY"] = "Dzisiaj";
+Calendar._TT["TIME_PART"] = "(Shift-)Kliknij lub przeciÄgnij by zmieniÄ wartoÅÄ";
 
 // date formats
-Calendar._TT["DEF_DATE_FORMAT"] = "%Y.%m.%d";
-Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y-%m-%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%e %B, %A";
 
-Calendar._TT["WK"] = "wk";
\ No newline at end of file
+Calendar._TT["WK"] = "ty";
diff --git a/shared/js/jscalendar-1.0/lang/calendar-pl.old.js b/shared/js/jscalendar-1.0/lang/calendar-pl.old.js
new file mode 100644
index 0000000..76e0551
--- /dev/null
+++ b/shared/js/jscalendar-1.0/lang/calendar-pl.old.js
@@ -0,0 +1,56 @@
+// ** I18N
+// Calendar PL language
+// Author: Artur Filipiak, <imagen@poczta.fm>
+// January, 2004
+// Encoding: UTF-8
+Calendar._DN = new Array
+("Niedziela", "PoniedziaÅek", "Wtorek", "Åroda", "Czwartek", "PiÄtek", "Sobota", "Niedziela");
+
+Calendar._SDN = new Array
+("N", "Pn", "Wt", "År", "Cz", "Pt", "So", "N");
+
+Calendar._MN = new Array
+("StyczeÅ", "Luty", "Marzec", "KwiecieÅ", "Maj", "Czerwiec", "Lipiec", "SierpieÅ", "WrzesieÅ", "PaÅºdziernik", "Listopad", "GrudzieÅ");
+
+Calendar._SMN = new Array
+("Sty", "Lut", "Mar", "Kwi", "Maj", "Cze", "Lip", "Sie", "Wrz", "PaÅº", "Lis", "Gru");
+
+// tooltips
+Calendar._TT = {};
+Calendar._TT["INFO"] = "O kalendarzu";
+
+Calendar._TT["ABOUT"] =
+"DHTML Date/Time Selector\n" +
+"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-)
+"For latest version visit: http://www.dynarch.com/projects/calendar/\n" +
+"Distributed under GNU LGPL.  See http://gnu.org/licenses/lgpl.html for details." +
+"\n\n" +
+"WybÃ³r daty:\n" +
+"- aby wybraÄ rok uÅ¼yj przyciskÃ³w \xab, \xbb\n" +
+"- aby wybraÄ miesiÄc uÅ¼yj przyciskÃ³w " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + "\n" +
+"- aby przyspieszyÄ wybÃ³r przytrzymaj wciÅniÄty przycisk myszy nad ww. przyciskami.";
+Calendar._TT["ABOUT_TIME"] = "\n\n" +
+"WybÃ³r czasu:\n" +
+"- aby zwiÄkszyÄ wartoÅÄ kliknij na dowolnym elemencie selekcji czasu\n" +
+"- aby zmniejszyÄ wartoÅÄ uÅ¼yj dodatkowo klawisza Shift\n" +
+"- moÅ¼esz rÃ³wnieÅ¼ poruszaÄ myszkÄ w lewo i prawo wraz z wciÅniÄtym lewym klawiszem.";
+
+Calendar._TT["PREV_YEAR"] = "Poprz. rok (przytrzymaj dla menu)";
+Calendar._TT["PREV_MONTH"] = "Poprz. miesiÄc (przytrzymaj dla menu)";
+Calendar._TT["GO_TODAY"] = "PokaÅ¼ dziÅ";
+Calendar._TT["NEXT_MONTH"] = "Nast. miesiÄc (przytrzymaj dla menu)";
+Calendar._TT["NEXT_YEAR"] = "Nast. rok (przytrzymaj dla menu)";
+Calendar._TT["SEL_DATE"] = "Wybierz datÄ";
+Calendar._TT["DRAG_TO_MOVE"] = "PrzesuÅ okienko";
+Calendar._TT["PART_TODAY"] = " (dziÅ)";
+Calendar._TT["MON_FIRST"] = "PokaÅ¼ PoniedziaÅek jako pierwszy";
+Calendar._TT["SUN_FIRST"] = "PokaÅ¼ NiedzielÄ jako pierwszÄ";
+Calendar._TT["CLOSE"] = "Zamknij";
+Calendar._TT["TODAY"] = "DziÅ";
+Calendar._TT["TIME_PART"] = "(Shift-)klik | drag, aby zmieniÄ wartoÅÄ";
+
+// date formats
+Calendar._TT["DEF_DATE_FORMAT"] = "%Y.%m.%d";
+Calendar._TT["TT_DATE_FORMAT"] = "%a, %b %e";
+
+Calendar._TT["WK"] = "wk";
\ No newline at end of file
diff --git a/shared/js/jscalendar-1.0/simple-1.html b/shared/js/jscalendar-1.0/simple-1.html
index 51546dc..285bff6 100644
--- a/shared/js/jscalendar-1.0/simple-1.html
+++ b/shared/js/jscalendar-1.0/simple-1.html
@@ -56,7 +56,7 @@ <h2>DHTML Calendar &mdash; for the impatient</h2>
 is updated so that the difference between them remains one week.  The
 property useful here is "onUpdate".</p>
 
-<form action="#" method="get">
+<form action="http://www.useragentman.com/testForm.php" method="get">
 <input type="text" name="date" id="f_date_a" />
 <input type="text" name="date" id="f_calcdate" />
 </form>
@@ -102,7 +102,7 @@ <h2>DHTML Calendar &mdash; for the impatient</h2>
 introduced in 0.9.6 (show all years in drop-down boxes, instead of every
 other year as default).</p>
 
-<form action="#" method="get">
+<form action="http://www.useragentman.com/testForm.php" method="get">
 <input type="text" name="date" id="f_date_b" /><button type="reset" id="f_trigger_b">...</button>
 </form>
 
@@ -126,7 +126,7 @@ <h2>DHTML Calendar &mdash; for the impatient</h2>
 Also in this example we setup a different alignment, just to show how it's
 done.  The input field is read-only (that is set from HTML).</p>
 
-<form action="#" method="get">
+<form action="http://www.useragentman.com/testForm.php" method="get">
 <table cellspacing="0" cellpadding="0" style="border-collapse: collapse"><tr>
  <td><input type="text" name="date" id="f_date_c" readonly="1" /></td>
  <td><img src="img.gif" id="f_trigger_c" style="cursor: pointer; border: 1px solid red;" title="Date selector"
@@ -157,7 +157,7 @@ <h2>DHTML Calendar &mdash; for the impatient</h2>
 we need to store one format in the database (thus pass it in the input
 field) but we wanna show a friendlier format to the end-user.</p>
 
-<form action="#" method="get" style="visibility: hidden">
+<form action="http://www.useragentman.com/testForm.php" method="get" style="visibility: hidden">
 <input type="hidden" name="date" id="f_date_d" />
 </form>
 
@@ -186,7 +186,7 @@ <h2>DHTML Calendar &mdash; for the impatient</h2>
 <p><b>Hidden field, display area, trigger image.</b> Very similar to the
 previous example.  The difference is that we also have a trigger image.</p>
 
-<form action="#" method="get" style="visibility: hidden">
+<form action="http://www.useragentman.com/testForm.php" method="get" style="visibility: hidden">
 <input type="hidden" name="date" id="f_date_e" />
 </form>
 
@@ -215,7 +215,7 @@ <h2>DHTML Calendar &mdash; for the impatient</h2>
 but we now disable some dates (all weekends, that is, Saturdays and
 Sundays).</p>
 
-<form action="#" method="get" style="visibility: hidden">
+<form action="http://www.useragentman.com/testForm.php" method="get" style="visibility: hidden">
 <input type="hidden" name="date" id="f_date_f" />
 </form>
 
diff --git a/shared/js/modernizr.com/Modernizr-2.5.3.forms.js b/shared/js/modernizr.com/Modernizr-2.5.3.forms.js
new file mode 100644
index 0000000..0ba6592
--- /dev/null
+++ b/shared/js/modernizr.com/Modernizr-2.5.3.forms.js
@@ -0,0 +1,4 @@
+/* Modernizr 2.5.3 (Custom Build) | MIT & BSD
+ * Build: http://www.modernizr.com/download/#-input-inputtypes-shiv-cssclasses-load
+ */
+;window.Modernizr=function(a,b,c){function v(a){j.cssText=a}function w(a,b){return v(prefixes.join(a+";")+(b||""))}function x(a,b){return typeof a===b}function y(a,b){return!!~(""+a).indexOf(b)}function z(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:x(f,"function")?f.bind(d||b):f}return!1}function A(){e.input=function(c){for(var d=0,e=c.length;d<e;d++)p[c[d]]=c[d]in k;return p.list&&(p.list=!!b.createElement("datalist")&&!!a.HTMLDataListElement),p}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)k.setAttribute("type",f=a[d]),e=k.type!=="text",e&&(k.value=l,k.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&k.style.WebkitAppearance!==c?(g.appendChild(k),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(k,null).WebkitAppearance!=="textfield"&&k.offsetHeight!==0,g.removeChild(k)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=k.checkValidity&&k.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(k),g.offsetWidth,e=k.value!=l,g.removeChild(k)):e=k.value!=l)),o[a[d]]=!!e;return o}("search tel url email datetime date month week time datetime-local number range color".split(" "))}var d="2.5.3",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k=b.createElement("input"),l=":)",m={}.toString,n={},o={},p={},q=[],r=q.slice,s,t={}.hasOwnProperty,u;!x(t,"undefined")&&!x(t.call,"undefined")?u=function(a,b){return t.call(a,b)}:u=function(a,b){return b in a&&x(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=r.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(r.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(r.call(arguments)))};return e});for(var B in n)u(n,B)&&(s=B.toLowerCase(),e[s]=n[B](),q.push((e[s]?"":"no-")+s));return e.input||A(),v(""),i=k=null,function(a,b){function g(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function h(){var a=k.elements;return typeof a=="string"?a.split(" "):a}function i(a){var b={},c=a.createElement,e=a.createDocumentFragment,f=e();a.createElement=function(a){var e=(b[a]||(b[a]=c(a))).cloneNode();return k.shivMethods&&e.canHaveChildren&&!d.test(a)?f.appendChild(e):e},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+h().join().replace(/\w+/g,function(a){return b[a]=c(a),f.createElement(a),'c("'+a+'")'})+");return n}")(k,f)}function j(a){var b;return a.documentShived?a:(k.shivCSS&&!e&&(b=!!g(a,"article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio{display:none}canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden]{display:none}audio[controls]{display:inline-block;*display:inline;*zoom:1}mark{background:#FF0;color:#000}")),f||(b=!i(a)),b&&(a.documentShived=b),a)}var c=a.html5||{},d=/^<|^(?:button|form|map|select|textarea)$/i,e,f;(function(){var a=b.createElement("a");a.innerHTML="<xyz></xyz>",e="hidden"in a,f=a.childNodes.length==1||function(){try{b.createElement("a")}catch(a){return!0}var c=b.createDocumentFragment();return typeof c.cloneNode=="undefined"||typeof c.createDocumentFragment=="undefined"||typeof c.createElement=="undefined"}()})();var k={elements:c.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:c.shivCSS!==!1,shivMethods:c.shivMethods!==!1,type:"default",shivDocument:j};a.html5=k,j(b)}(this,b),e._version=d,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+q.join(" "):""),e}(this,this.document),function(a,b,c){function d(a){return o.call(a)=="[object Function]"}function e(a){return typeof a=="string"}function f(){}function g(a){return!a||a=="loaded"||a=="complete"||a=="uninitialized"}function h(){var a=p.shift();q=1,a?a.t?m(function(){(a.t=="c"?B.injectCss:B.injectJs)(a.s,0,a.a,a.x,a.e,1)},0):(a(),h()):q=0}function i(a,c,d,e,f,i,j){function k(b){if(!o&&g(l.readyState)&&(u.r=o=1,!q&&h(),l.onload=l.onreadystatechange=null,b)){a!="img"&&m(function(){t.removeChild(l)},50);for(var d in y[c])y[c].hasOwnProperty(d)&&y[c][d].onload()}}var j=j||B.errorTimeout,l={},o=0,r=0,u={t:d,s:c,e:f,a:i,x:j};y[c]===1&&(r=1,y[c]=[],l=b.createElement(a)),a=="object"?l.data=c:(l.src=c,l.type=a),l.width=l.height="0",l.onerror=l.onload=l.onreadystatechange=function(){k.call(this,r)},p.splice(e,0,u),a!="img"&&(r||y[c]===2?(t.insertBefore(l,s?null:n),m(k,j)):y[c].push(l))}function j(a,b,c,d,f){return q=0,b=b||"j",e(a)?i(b=="c"?v:u,a,b,this.i++,c,d,f):(p.splice(this.i++,0,a),p.length==1&&h()),this}function k(){var a=B;return a.loader={load:j,i:0},a}var l=b.documentElement,m=a.setTimeout,n=b.getElementsByTagName("script")[0],o={}.toString,p=[],q=0,r="MozAppearance"in l.style,s=r&&!!b.createRange().compareNode,t=s?l:n.parentNode,l=a.opera&&o.call(a.opera)=="[object Opera]",l=!!b.attachEvent&&!l,u=r?"object":l?"script":"img",v=l?"script":u,w=Array.isArray||function(a){return o.call(a)=="[object Array]"},x=[],y={},z={timeout:function(a,b){return b.length&&(a.timeout=b[0]),a}},A,B;B=function(a){function b(a){var a=a.split("!"),b=x.length,c=a.pop(),d=a.length,c={url:c,origUrl:c,prefixes:a},e,f,g;for(f=0;f<d;f++)g=a[f].split("="),(e=z[g.shift()])&&(c=e(c,g));for(f=0;f<b;f++)c=x[f](c);return c}function g(a,e,f,g,i){var j=b(a),l=j.autoCallback;j.url.split(".").pop().split("?").shift(),j.bypass||(e&&(e=d(e)?e:e[a]||e[g]||e[a.split("/").pop().split("?")[0]]||h),j.instead?j.instead(a,e,f,g,i):(y[j.url]?j.noexec=!0:y[j.url]=1,f.load(j.url,j.forceCSS||!j.forceJS&&"css"==j.url.split(".").pop().split("?").shift()?"c":c,j.noexec,j.attrs,j.timeout),(d(e)||d(l))&&f.load(function(){k(),e&&e(j.origUrl,i,g),l&&l(j.origUrl,i,g),y[j.url]=2})))}function i(a,b){function c(a,c){if(a){if(e(a))c||(j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}),g(a,j,b,0,h);else if(Object(a)===a)for(n in m=function(){var b=0,c;for(c in a)a.hasOwnProperty(c)&&b++;return b}(),a)a.hasOwnProperty(n)&&(!c&&!--m&&(d(j)?j=function(){var a=[].slice.call(arguments);k.apply(this,a),l()}:j[n]=function(a){return function(){var b=[].slice.call(arguments);a&&a.apply(this,b),l()}}(k[n])),g(a[n],j,b,n,h))}else!c&&l()}var h=!!a.test,i=a.load||a.both,j=a.callback||f,k=j,l=a.complete||f,m,n;c(h?a.yep:a.nope,!!i),i&&c(i)}var j,l,m=this.yepnope.loader;if(e(a))g(a,0,m,0);else if(w(a))for(j=0;j<a.length;j++)l=a[j],e(l)?g(l,0,m,0):w(l)?B(l):Object(l)===l&&i(l,m);else Object(a)===a&&i(a,m)},B.addPrefix=function(a,b){z[a]=b},B.addFilter=function(a){x.push(a)},B.errorTimeout=1e4,b.readyState==null&&b.addEventListener&&(b.readyState="loading",b.addEventListener("DOMContentLoaded",A=function(){b.removeEventListener("DOMContentLoaded",A,0),b.readyState="complete"},0)),a.yepnope=k(),a.yepnope.executeStack=h,a.yepnope.injectJs=function(a,c,d,e,i,j){var k=b.createElement("script"),l,o,e=e||B.errorTimeout;k.src=a;for(o in d)k.setAttribute(o,d[o]);c=j?h:c||f,k.onreadystatechange=k.onload=function(){!l&&g(k.readyState)&&(l=1,c(),k.onload=k.onreadystatechange=null)},m(function(){l||(l=1,c(1))},e),i?k.onload():n.parentNode.insertBefore(k,n)},a.yepnope.injectCss=function(a,c,d,e,g,i){var e=b.createElement("link"),j,c=i?h:c||f;e.href=a,e.rel="stylesheet",e.type="text/css";for(j in d)e.setAttribute(j,d[j]);g||(n.parentNode.insertBefore(e,n),m(c,0))}}(this,document),Modernizr.load=function(){yepnope.apply(window,[].slice.call(arguments,0))};
\ No newline at end of file
diff --git a/shared/js/weston.ruter.net/.DS_Store b/shared/js/weston.ruter.net/.DS_Store
new file mode 100644
index 0000000..72a32cf
Binary files /dev/null and b/shared/js/weston.ruter.net/.DS_Store differ
diff --git a/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/001.html b/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/001.html
index 3fd2905..b3785a9 100644
--- a/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/001.html
+++ b/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/001.html
@@ -38,7 +38,7 @@ <h1>Validation</h1>
 <p>In this example, the input field is declared "required", which means the form cannot be submitted if the field is empty. Instead an error message will be displayed to the user.</p>
 
 <div class="example">
-<form>
+<form action="http://www.useragentman.com/testForm.php">
   <input name="textfield" type="text" required>
   <button type=submit>Submit me</button>
 </form>
@@ -55,7 +55,7 @@ <h1>Validation</h1>
 <p>This field requires a number between 18 and 99:
 
 <div class="example">
-<form>
+<form action="http://www.useragentman.com/testForm.php">
   Age: <input name="age" type="number" min="18" max="99" required  oninvalid="return true">
   <button type=submit>Submit me</button>
 </form>
@@ -72,7 +72,7 @@ <h1>Validation</h1>
 <p>Here is a sample form using an assortment of the new validation constraints:</p>
 
 <div class="example">
-<form>
+<form action="http://www.useragentman.com/testForm.php">
   <p><label>Your e-mail address:</label><input name="email" type="email"> (must be an email adress)</p>
   <p><label>Your web page:</label><input name="url" type="uri"> (must be an URI)</p>
   <p><label>Your age:</label><input name="age" type="number" min=18 max=90> (must be between 18 and 90)</p>
@@ -90,7 +90,7 @@ <h2>Custom validation</h2>
 <p>Of course, the built-in types and constraints cannot cover every use case. Therefore it is possible to hook custom code into the validation system.
 
 <div class="example">
-<form>
+<form action="http://www.useragentman.com/testForm.php">
 <script>
 function isSquareNumber(num) {
 	return (Math.sqrt(num)!=Math.round(Math.sqrt(num)))
diff --git a/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/002.html b/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/002.html
index c88bceb..a139f7e 100644
--- a/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/002.html
+++ b/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/002.html
@@ -4,7 +4,7 @@
 		<script language="javascript" src="../wf2-validation.js"></script>
 	</head>
 	<body>
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			
 			<button type="submit">Submit</button>
 		</form>
diff --git a/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/003.html b/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/003.html
index 5286469..dcaa98f 100644
--- a/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/003.html
+++ b/shared/js/weston.ruter.net/webforms2/proto-validation/wf2-validation-testcases/003.html
@@ -88,7 +88,7 @@
 	</head>
 	<body>
 		<div style="margin-left:10em; margin-top:3em; position:relative;">
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<label for="name">Name: </label><input type="text" id="name" name="name" required="required" pattern="\w+( \w+)+" oninvalid="if(!document.addEventListener) handleEvent(event)" /><br />
 			<label for="email">Email: </label><input type="email" id="email" name="email" required="required" oninvalid="if(!document.addEventListener) handleEvent(event)" /><br />
 			<button type="submit">Submit</button>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/001.html b/shared/js/weston.ruter.net/webforms2/testsuite/001.html
index 28adf01..c31a4ef 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/001.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/001.html
@@ -33,7 +33,7 @@ <h1>Web Forms 2.0 Test Case 1: Spec Example: Sample Order Form</h1>
   
 
   <h1>Sample Order Form</h1>
-  <form>
+  <form action="http://www.useragentman.com/testForm.php">
    <table>
     <thead>
      <tr>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/002.html b/shared/js/weston.ruter.net/webforms2/testsuite/002.html
index 5b598b6..22abb53 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/002.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/002.html
@@ -32,7 +32,7 @@ <h1>Web Forms 2.0 Test Case 2: Spec Example: Repeated rows</h1>
 		</div>
   
 
-  <form action="http://software.hixie.ch/utilities/cgi/test-tools/echo" method="post" enctype="multipart/form-data">
+  <form action="http://www.useragentman.com/testForm.php" method="post" enctype="multipart/form-data">
    <table>
     <thead>
      <tr>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/003.html b/shared/js/weston.ruter.net/webforms2/testsuite/003.html
index 9cf7cdf..776eb26 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/003.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/003.html
@@ -32,7 +32,7 @@ <h1>Web Forms 2.0 Test Case 3: Spec Example: Solar system</h1>
 		</div>
   
 
-  <form>
+  <form action="http://www.useragentman.com/testForm.php">
    <h1> Solar system </h1>
    <p> <label> System Name: <input name="name"/> </label> </p>
    <h2> Planets </h2>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/004.html b/shared/js/weston.ruter.net/webforms2/testsuite/004.html
index c5935ad..1bc040d 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/004.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/004.html
@@ -206,7 +206,7 @@ <h1>Web Forms 2.0 Test Case 4: Movement Buttons and Canceling Default Action</h1
 		
 		
 		<p><strong>Note:</strong> Buttons with ellipses will confirm the action.</p>
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<table cellspacing="0">
 				<tbody>
 				<tr id="order" repeat="template" repeat-start="0" repeat-min="0" repeat-max="5">				
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/006.html b/shared/js/weston.ruter.net/webforms2/testsuite/006.html
index a0ef639..b5f58d5 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/006.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/006.html
@@ -178,7 +178,7 @@ <h1>Web Forms 2.0 Test Case 6: Repetition Events</h1>
   
 
 		
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<fieldset style="display:inline;">
 				<legend><strong>Event model options</strong></legend>
 				<div><input type="checkbox" id="dom2EventModel" onclick="toggleDOM2Events(this.checked)" checked="checked" />
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/007.html b/shared/js/weston.ruter.net/webforms2/testsuite/007.html
index b9344fa..e80ea15 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/007.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/007.html
@@ -114,7 +114,7 @@ <h1>Web Forms 2.0 Test Case 7: Repetition Event Handler Attributes</h1>
   
 
 		
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<p><button type="add" template="i" style="font-size:large">Add row</button></p>
 			<ul>
 				<li id="i" repeat="template" repeat-start="0" onadd="addEventLogEntry(event)" onremove="addEventLogEntry(event)" onmove="addEventLogEntry(event)">
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/015.html b/shared/js/weston.ruter.net/webforms2/testsuite/015.html
index aae251e..1d549c2 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/015.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/015.html
@@ -38,7 +38,7 @@ <h1>Web Forms 2.0 Test Case 15: Required Elements in Repeated Blocks</h1>
 
 
 
-  <form action="http://software.hixie.ch/utilities/cgi/test-tools/echo" method="post" enctype="multipart/form-data">
+  <form action="http://www.useragentman.com/testForm.php" method="post" enctype="multipart/form-data">
    <table>
     <thead>
      <tr>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/018.html b/shared/js/weston.ruter.net/webforms2/testsuite/018.html
index c41f910..20a6be6 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/018.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/018.html
@@ -39,7 +39,7 @@ <h1>Web Forms 2.0 Test Case 18: Input Controls in Nested Repetition Blocks</h1>
 		</div>
   
 
-  <form>
+  <form action="http://www.useragentman.com/testForm.php">
    <h1> Solar system </h1>
    <p> <label> System Name: <input name="name"/> </label> </p>
    <h2> Planets </h2>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/001.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/001.html
index 89a3cfd..a5e1364 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/001.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/001.html
@@ -13,7 +13,7 @@
 
 <!-- BEGIN TEST CASE -->
   <h1>Sample Order Form</h1>
-  <form>
+  <form action="http://www.useragentman.com/testForm.php">
    <table>
     <thead>
      <tr>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/002.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/002.html
index f94ca2c..955b191 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/002.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/002.html
@@ -20,7 +20,7 @@
 </div>
 
 <!-- BEGIN TEST CASE -->
-  <form action="http://software.hixie.ch/utilities/cgi/test-tools/echo" method="post" enctype="multipart/form-data">
+  <form action="http://www.useragentman.com/testForm.php" method="post" enctype="multipart/form-data">
    <table>
     <thead>
      <tr>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/003.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/003.html
index 40b624e..2417c09 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/003.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/003.html
@@ -19,7 +19,7 @@
 </div>
 
 <!-- BEGIN TEST CASE -->
-  <form>
+  <form action="http://www.useragentman.com/testForm.php">
    <h1> Solar system </h1>
    <p> <label> System Name: <input name="name"/> </label> </p>
    <h2> Planets </h2>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/004.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/004.html
index edeeb59..92e88f8 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/004.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/004.html
@@ -188,7 +188,7 @@
 		
 		
 		<p><strong>Note:</strong> Buttons with ellipses will confirm the action.</p>
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<table cellspacing="0">
 				<tbody>
 				<tr id="order" repeat="template" repeat-start="0" repeat-min="0" repeat-max="5">				
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/006.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/006.html
index e85fbf0..98d398a 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/006.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/006.html
@@ -160,7 +160,7 @@
 		
 		<!-- BEGIN TEST CASE -->
 		
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<fieldset style="display:inline;">
 				<legend><strong>Event model options</strong></legend>
 				<div><input type="checkbox" id="dom2EventModel" onclick="toggleDOM2Events(this.checked)" checked="checked" />
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/007.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/007.html
index 18920a5..b7bb0b9 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/007.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/007.html
@@ -97,7 +97,7 @@
 		
 		<!-- BEGIN TEST CASE -->
 		
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<p><button type="add" template="i" style="font-size:large">Add row</button></p>
 			<ul>
 				<li id="i" repeat="template" repeat-start="0" onadd="addEventLogEntry(event)" onremove="addEventLogEntry(event)" onmove="addEventLogEntry(event)">
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/015.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/015.html
index d3e53c5..70fccd6 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/015.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/015.html
@@ -20,7 +20,7 @@
 		<!-- BEGIN TEST CASE -->
 
 
-  <form action="http://software.hixie.ch/utilities/cgi/test-tools/echo" method="post" enctype="multipart/form-data">
+  <form action="http://www.useragentman.com/testForm.php" method="post" enctype="multipart/form-data">
    <table>
     <thead>
      <tr>
diff --git a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/018.html b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/018.html
index 95d9692..96ab524 100644
--- a/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/018.html
+++ b/shared/js/weston.ruter.net/webforms2/testsuite/~testcases/018.html
@@ -22,7 +22,7 @@
 		</div>
 		
 		<!-- BEGIN TEST CASE -->
-  <form>
+  <form action="http://www.useragentman.com/testForm.php">
    <h1> Solar system </h1>
    <p> <label> System Name: <input name="name"/> </label> </p>
    <h2> Planets </h2>
diff --git a/shared/js/weston.ruter.net/webforms2/validationPointer.png b/shared/js/weston.ruter.net/webforms2/validationPointer.png
new file mode 100644
index 0000000..d293f7a
Binary files /dev/null and b/shared/js/weston.ruter.net/webforms2/validationPointer.png differ
diff --git a/shared/js/weston.ruter.net/webforms2/webforms2-p b/shared/js/weston.ruter.net/webforms2/webforms2-p
new file mode 100644
index 0000000..24fdd81
--- /dev/null
+++ b/shared/js/weston.ruter.net/webforms2/webforms2-p
@@ -0,0 +1,56 @@
+if(!window.$wf2){var $wf2={};document.implementation&&document.implementation.hasFeature&&!document.implementation.hasFeature("WebForms","2.0")&&($wf2={version:"0.5.4",isInitialized:!1,libpath:"",globalEvent:null,hasElementExtensions:window.HTMLElement&&HTMLElement.prototype,hasGettersAndSetters:$wf2.__defineGetter__&&$wf2.__defineSetter__,hasBadImplementation:0<navigator.userAgent.indexOf("WebKit"),callBeforeValidation:[],callAfterValidation:[],callAfterDOMContentLoaded:[],onDOMContentLoaded:function(){if(!$wf2.isInitialized){$wf2.isInitialized=
+!0;var a;document.createEventObject?$wf2.globalEvent=document.createEventObject():document.createEvent&&($wf2.globalEvent=document.createEvent("HTMLEvents"));a=document.createElement("link");a.setAttribute("type","text/css");a.setAttribute("rel","stylesheet");a.setAttribute("href",$wf2.libpath+"webforms2.css");var b=document.getElementsByTagName("head")[0];b||(b=document.getElementsByTagName("*")[0]);b.insertBefore(a,b.firstChild);$wf2.zeroPoint={};$wf2.zeroPoint.datetime=$wf2.parseISO8601("1970-01-01T00:00:00.0Z");
+$wf2.zeroPoint["datetime-local"]=$wf2.parseISO8601("1970-01-01T00:00:00.0");$wf2.zeroPoint.date=$wf2.zeroPoint.datetime;$wf2.zeroPoint.month=$wf2.zeroPoint.datetime;$wf2.zeroPoint.week=$wf2.parseISO8601("1970-W01");$wf2.zeroPoint.time=$wf2.zeroPoint.datetime;$wf2.xhr=null;if(window.XMLHttpRequest)$wf2.xhr=new XMLHttpRequest;else if(window.ActiveXObject)try{$wf2.xhr=new ActiveXObject("Msxml2.XMLHTTP")}catch(d){try{$wf2.xhr=new ActiveXObject("Microsoft.XMLHTTP")}catch(c){}}$wf2.xhr&&($wf2.prefillSelectElements(),
+$wf2.prefillFormElements());window.$wf2Rep&&($wf2.initRepetitionBlocks(),$wf2.initRepetitionTemplates(),$wf2.initRepetitionButtons("add"),$wf2.initRepetitionButtons("remove"),$wf2.initRepetitionButtons("move-up"),$wf2.initRepetitionButtons("move-down"),$wf2.updateAddButtons(),$wf2.updateMoveButtons());document.addEventListener?(document.addEventListener("mousedown",$wf2.clearInvalidIndicators,!1),document.addEventListener("keydown",$wf2.clearInvalidIndicators,!1)):document.attachEvent&&(document.attachEvent("onmousedown",
+$wf2.clearInvalidIndicators),document.attachEvent("onkeydown",$wf2.clearInvalidIndicators));$wf2.initNonRepetitionFunctionality();for(a=0;a<$wf2.callAfterDOMContentLoaded.length;a++)$wf2.callAfterDOMContentLoaded[a]()}},prefillSelectElements:function(){for(var a,b=$wf2.getElementsByTagNames.apply(document.documentElement,["select","datalist"]),d=0;a=b[d];d++){var c=$wf2.loadDataURI(a);if(c&&c.documentElement&&/:?\bselect$/i.test(c.documentElement.nodeName)&&"http://www.w3.org/1999/xhtml"==c.documentElement.namespaceURI){c=
+c.documentElement;if("incremental"!=c.getAttribute("type"))for(;a.lastChild;)a.removeChild(a.lastChild);for(node=c.firstChild;node;)a.appendChild($wf2.cloneNode(node)),node=node.nextSibling}}},prefillFormElements:function(){for(var a,b=document.getElementsByTagName("form"),d=0;a=b[d];d++){var c=$wf2.loadDataURI(a);if(c&&c.documentElement&&/:?\bformdata$/.test(c.documentElement.nodeName)&&"http://n.whatwg.org/formdata"==c.documentElement.namespaceURI){var e,f=c.documentElement;"incremental"!=f.getAttribute("type")&&
+a.reset();var g=f.getElementsByTagName("clear");for(j=0;c=g[j];j++)if("http://n.whatwg.org/formdata"==c.namespaceURI&&c.parentNode==f&&!c.firstChild&&(e=document.getElementById(c.getAttribute("template")))&&"template"==e.getAttribute("repeat"))for(var m,h,c=e.parentNode.firstChild;c;)1==c.nodeType&&(m=c.getAttributeNode("repeat"))&&"template"!=m.value?(h=c.nextSibling,c.parentNode.removeChild(c),c=h):c=c.nextSibling;var o,g=f.getElementsByTagName("repeat");for(j=0;c=g[j];j++)if("http://n.whatwg.org/formdata"==
+c.namespaceURI&&c.parentNode==f&&!c.firstChild&&(e=document.getElementById(c.getAttribute("template")))&&"template"==e.getAttribute("repeat")&&/^-?\d+$/.test(o=c.getAttribute("index"))){for(var q,c=e.parentNode.firstChild;c;){if(1==c.nodeType&&(m=c.getAttributeNode("repeat"))&&m.value==o){q=!0;break}c=c.nextSibling}q||$wf2.addRepetitionBlockByIndex.apply(e,[null,o])}var p,f=f.getElementsByTagName("field"),g=$wf2.getFormElements.apply(a);for(j=0;p=f[j];j++){var k=p.getAttributeNode("index"),n=p.getAttribute("name");
+if(n&&(!k||/^\d+$/.test(k.value))){h="";for(l=0;c=p.childNodes[l];l++)if(3==c.nodeType||4==c.nodeType)h+=c.data;else break;for(l=p=0;c=g[l];l++)if("image"==c.type){if(c.name?c.name+".x"==n||c.name+".y"==n:"x"==n||"y"==n)if(!k||++p-1>=k.value)break}else if(c.name==n){if(k){if(++p-1<k.value)continue}else if(("radio"==c.type||"checkbox"==c.type)&&h&&c.value!=h)continue;break}if(!("file"==c.type||"button"==c.type||"image"==c.type))if(!c.getAttributeNode("multiple")||!c.wf2Prefilled){if("checkbox"==c.type||
+"radio"==c.type)if(h)if(c.value==h)c.checked=!0;else break;else c.checked=!1;else if("select"==c.nodeName.toLowerCase()){c.selectedIndex=-1;for(var l=0;k=c.options[l];l++)if(k.value?k.value==h:k.text==h){k.selected=!0;break}}else c.value=h,$wf2.updateValidityState(c),c.validity.valid||(c.value=c.defaultValue,$wf2.updateValidityState(c));c.wf2Prefilled=!0}else if(c.getAttributeNode("multiple"))for(l=0;k=c.options[l];l++)if(!k.selected&&(k.value?k.value==h:k.text==h)){k.selected=!0;break}}}g=$wf2.getFormElements.apply(a);
+for(j=0;j<g.length;j++);}}},initNonRepetitionFunctionality:function(a){var a=a||document.documentElement,b,d,c=a.getElementsByTagName("form");for(b=0;d=c[b];b++)if(!d.checkValidity||$wf2.hasBadImplementation)d.checkValidity=$wf2.formCheckValidity,d.addEventListener?d.addEventListener("submit",$wf2.onsubmitValidityHandler,!1):d.attachEvent("onsubmit",$wf2.onsubmitValidityHandler);c=$wf2.getElementsByTagNames.apply(a,["input","select","textarea","button"]);for(b=0;d=c[b];b++)$wf2.applyValidityInterface(d),
+$wf2.updateValidityState(d);d=$wf2.getElementsByTagNamesAndAttribute.apply(document.documentElement,[["*"],"autofocus"]);a.getAttribute("autofocus")&&d.unshift(a);for(b=0;b<d.length;b++)$wf2.initAutofocusElement(d[b]);d=$wf2.getElementsByTagNamesAndAttribute.apply(a,[["textarea"],"maxlength"]);"textarea"==a.nodeName.toLowerCase()&&d.unshift(a);for(b=0;b<d.length;b++)d[b].maxLength=parseInt(d[b].getAttribute("maxlength"))},initAutofocusElement:function(a){if(!(!1===a.autofocus||!0===a.autofocus))if(a.autofocus=
+!0,!a.disabled){for(var b=a;b&&1==b.nodeType;){if("hidden"==$wf2.getElementStyle(b,"visibility")||"none"==$wf2.getElementStyle(b,"display"))return;b=b.parentNode}a.focus()}},formCheckValidity:function(){var a,b,d=!0,c=$wf2.getFormElements.apply(this);for(a=0;b=c[a];a++){var e=b.getAttribute("type")?b.getAttribute("type").toLowerCase():b.type;b.willValidate=!(/(hidden|button|reset|add|remove|move-up|move-down)/.test(e)||!b.name||b.disabled);b.checkValidity&&b.willValidate&&!b.checkValidity()&&void 0!=
+b.checkValidity()&&(d=!1)}d||$wf2.hiliteFirstError();return d},hiliteFirstError:function(){if($wf2.invalidIndicators.length){$wf2.css.addClass($wf2.invalidIndicators[0].errorMsg,"wf2_firstErrorMsg");el=$wf2.invalidIndicators[0].target;var a="true"!=el.form.getAttribute("data-wf2-no-scroll-on-error");if("none"==el.style.display||!el.offsetParent){for(;el&&(1!=el.nodeType||"none"==el.style.display||!el.offsetParent);)el=el.previousSibling;var b=el,d=0;if(b&&b.offsetParent)for(d=b.offsetTop;b=b.offsetParent;)d+=
+b.offsetTop;a&&scrollTo(0,d)}else setTimeout(function(){el.focus();$wf2.fireEvent(el,"focus")},10),a&&scrollBy(0,$wf2.invalidIndicators[0].errorMsg.offsetHeight)}},controlCheckValidity:function(){return $wf2.controlCheckValidityOfElement(this)},controlCheckValidityOfElement:function(a){$wf2.updateValidityState(a);if(a.validity.valid)return!0;var b=!1,d;try{$wf2.fireEvent(a,"invalid")}catch(c){d={},d.initEvent?d.initEvent("invalid",!0,!0):(d.type="invalid",d.cancelBubble=!1),d.target=d.srcElement=
+a}var e=a.getAttribute("oninvalid");if(e&&(!a.oninvalid||"function"!=typeof a.oninvalid))a.oninvalid=new Function("event",e);try{a.oninvalid&&(b=!1===a.oninvalid.apply(a,[d])||b)}catch(f){setTimeout(function(){throw f;},0)}d=!1;if("radio"==a.type||"checkbox"==a.type)for(e=0;e<$wf2.invalidIndicators.length;e++)if(a.form[a.name][0]==$wf2.invalidIndicators[e].target){d=!0;break}!b&&!d&&$wf2.addInvalidIndicator(a);return!1},numberRegExp:/^-?\d+(.\d+)?(e-?\d+)?$/,urlRegExp:/^(\w+):(\/\/)?.+$/i,emailRegExp:/^\S+@\S+$/i,
+copyOf:function(a){if(null!==a&&void 0!==a){var b={};for(i in a)try{b[i]=a[i]}catch(d){}}else b=null;return b},getOriginalAttrNode:function(a,b){return $wf2.copyOf(a.getAttributeNode(b))},updateValidityState:function(a){var b,d,c;b=$wf2.getOriginalAttrNode(a,"min");d=$wf2.getOriginalAttrNode(a,"max");l=$wf2.getOriginalAttrNode(a,"step");c=$wf2.getOriginalAttrNode(a,"value");a.min=void 0;a.max=void 0;a.step=void 0;a.validity=$wf2.createValidityState();a.validity.customError=!!a.validationMessage;var e=
+a.getAttribute("type")?a.getAttribute("type").toLowerCase():a.type,f="datetime"==e||"datetime-local"==e||"time"==e,g="date"==e||"month"==e||"week"==e,m="number"==e||"range"==e,h="file"==e,o=f||g||m,q=o||"textarea"==a.nodeName.toLowerCase(),p=o||h,k="radio"==e||"checkbox"==e,h=q||h||"email"==e||"url"==e||"text"==e||"password"==e||"tel"==e||k;if("range"==e){if(a.min=b&&$wf2.numberRegExp.test(b.value)?Number(b.value):0,(!c||!c.specified)&&""===a.value&&!a.wf2ValueProvided)a.setAttribute("value",a.min),
+a.value=a.min,a.wf2ValueProvided=!0}else{a.wf2Value=$wf2.css.isMemberOfClass(a,"html5-hasPlaceholderText")?"":a.value;e=a.getAttribute("type")?a.getAttribute("type").toLowerCase():a.type;a.willValidate=!(/(hidden|button|reset|add|remove|move-up|move-down)/.test(e)||!a.name||a.disabled);if(h&&a.willValidate)if(k){if(a.form&&a.form[a.name]){var h=k=!1,n=a.form[a.name];if(void 0==n.length)n.getAttributeNode("required")&&(k=!0),n.checked&&(h=!0);else for(c=0;c<n.length;c++)n[c].getAttributeNode("required")&&
+(k=!0),n[c].checked&&(h=!0);a.validity.valueMissing=k&&!h}}else a.getAttributeNode("required")&&(a.validity.valueMissing=""==a.wf2Value);if(!a.validity.valueMissing&&a.wf2Value){if(c=a.getAttributeNode("pattern"))c=RegExp("^(?:"+c.value+")$"),c.global=!1,c.ignoreCase=!1,c.multiline=!1,c&&(a.validity.patternMismatch=!c.test(a.wf2Value));if(!g&&!f)switch(e){case "number":case "range":a.validity.typeMismatch=!$wf2.numberRegExp.test(a.wf2Value);break;case "email":a.validity.typeMismatch=!$wf2.emailRegExp.test(a.wf2Value);
+break;case "url":a.validity.typeMismatch=!$wf2.urlRegExp.test(a.wf2Value)}if(!a.validity.patternMismatch&&!a.validity.typeMismatch){if(p)if(m){if("range"==e)a.max=d&&$wf2.numberRegExp.test(d.value)?Number(d.value):100;else if(b&&$wf2.numberRegExp.test(b.value)&&(a.min=Number(b.value)),d&&$wf2.numberRegExp.test(d.value)&&(a.max=Number(d.value)),l&&$wf2.numberRegExp.test(l.value))a.step=Number(l.value);a.validity.rangeUnderflow=void 0!=a.min&&Number(a.wf2Value)<a.min;a.validity.rangeOverflow=void 0!=
+a.max&&Number(a.wf2Value)>a.max;a.validity.stepMismatch=!$wf2.isValidNumber(a)}else if("file"==e)a.min=b&&/^\d+$/.test(b.value)?Number(b.value):0,a.max=d&&/^\d+$/.test(d.value)?Number(d.value):1;else if(b&&(a.min=$wf2.parseISO8601(b.value,e),a.validity.rangeUnderflow=a.min&&a.wf2Value<a.min),d)a.max=$wf2.parseISO8601(d.value,e),a.validity.rangeOverflow=a.max&&a.wf2Value>a.max;if(!g&&!f&&o&&!a.validity.rangeUnderflow&&!a.validity.rangeOverflow){var l=$wf2.getOriginalAttrNode(a,"step");a.step=l?"any"==
+l.value?"any":$wf2.numberRegExp.test(l.value)&&0<l.value?Number(l.value):f?60:1:f?60:1;if("any"!=a.step&&(a.wf2StepDatum=null,a.wf2StepDatum=b?a.min:d?a.max:$wf2.zeroPoint[e]?$wf2.zeroPoint[e]:0,b=a.step,!("month"==e&&a.wf2StepDatum&&a.wf2StepDatum.getUTCFullYear))){switch(e){case "datetime":case "datetime-local":case "time":b=parseInt(1E3*b);break;case "date":b=parseInt(864E5*b);break;case "week":b=parseInt(6048E5*b)}a.validity.stepMismatch=0!=Math.round(1E3*(a.wf2Value-a.wf2StepDatum))%Math.round(1E3*
+b)}}}if(q&&0<=a.maxLength&&a.wf2Value!=a.defaultValue){e=a.wf2Value;a.wf2ValueLength=e.length;for(c=1;c<e.length;c++)("\n"===e[c]&&"\r"!==e[c-1]||"\r"==e[c]&&e[c+1]&&"\n"!==e[c+1])&&a.wf2ValueLength++;a.validity.tooLong=a.wf2ValueLength>a.maxLength}}else if(b&&$wf2.numberRegExp.test(b.value)&&(a.min=Number(b.value)),d&&$wf2.numberRegExp.test(d.value)&&(a.max=Number(d.value)),l&&$wf2.numberRegExp.test(l.value))a.step=Number(l.value);a.validity.valid=!$wf2.hasInvalidState(a.validity);a.validity.valid?
+($wf2.css.removeClass(a,"wf2_invalid"),$wf2.css.addClass(a,"wf2_valid")):($wf2.css.removeClass(a,"wf2_valid"),$wf2.css.addClass(a,"wf2_invalid"))}},isValidNumber:function(a){a=(parseFloat(a.wf2Value)-parseFloat(a.min))/parseFloat(a.step);return a==parseInt(a)},applyValidityInterface:function(a){if($wf2.hasBadImplementation){if("submit"==a.type||"button"==a.type)a.formNoValidate=!0}else if(a.validity&&void 0!==a.validity.typeMismatch)return a;a.validationMessage="";a.validity=$wf2.createValidityState();
+a.willValidate=!0;var b=a.nodeName.toLowerCase();if("button"==b||"fieldset"==b)return a.setCustomValidity=function(){throw $wf2.DOMException(9);},a.checkValidity=function(){return!0},a;a.setCustomValidity||(a.setCustomValidity=$wf2.controlSetCustomValidity);a.checkValidity=$wf2.controlCheckValidity;if(/(hidden|button|reset|add|remove|move-up|move-down)/.test(a.getAttribute("type")?a.getAttribute("type").toLowerCase():a.type)||!a.name||a.disabled)a.willValidate=!1;else if(window.RepetitionElement)for(b=
+a;b=b.parentNode;)if(b.repetitionType==RepetitionElement.REPETITION_TEMPLATE){a.willValidate=!1;break}b=function(a){return $wf2.updateValidityState(a.currentTarget||a.srcElement)};document.addEventListener?(a.addEventListener("change",b,!1),a.addEventListener("blur",b,!1),a.addEventListener("keyup",b,!1)):window.attachEvent&&(a.attachEvent("onchange",b),a.attachEvent("onblur",b),a.attachEvent("onkeyup",b));return a},onsubmitValidityHandler:function(a){for(var b=a.currentTarget||a.srcElement,d=0;d<
+$wf2.callBeforeValidation.length;d++)$wf2.callBeforeValidation[d](a);b.checkValidity()?b=a.returnValue=!0:(a.preventDefault&&a.preventDefault(),b=a.returnValue=!1);for(d=0;d<$wf2.callAfterValidation.length;d++)$wf2.callAfterValidation[d](a,b);return b},controlSetCustomValidity:function(a){a?(this.validationMessage=""+a,this.validity.customError=!0):(this.validationMessage="",this.validity.customError=!1);this.validity.valid=!$wf2.hasInvalidState(this.validity)},hasInvalidState:function(a){return a.typeMismatch||
+a.rangeUnderflow||a.rangeOverflow||a.stepMismatch||a.tooLong||a.patternMismatch||a.valueMissing||a.customError},createValidityState:function(){return{typeMismatch:!1,rangeUnderflow:!1,rangeOverflow:!1,stepMismatch:!1,tooLong:!1,patternMismatch:!1,valueMissing:!1,customError:!1,valid:!0}},invalidIndicators:[],indicatorTimeoutId:null,indicatorIntervalId:null,stepUnits:{datetime:"second","datetime-local":"second",time:"second",date:"day",week:"week",month:"month"},invalidMessages:{valueMissing:"Please fill out this field.",
+typeMismatch:"Please enter a valid %s.",rangeUnderflow:"The value must be equal to or greater than %s.",rangeOverflow:"The value must be equal to or less than %s.",stepMismatch:"The value has a step mismatch; it must be a certain number multiples of %s from %s.",tooLong:"The value is too long. The field may have a maximum of %s characters but you supplied %s. Note that each line-break counts as two characters.",patternMismatch:"Please match the requested format."},valueToWF2Type:function(a,b){switch((""+
+b).toLowerCase()){case "datetime":case "datetime-local":case "date":case "month":case "week":case "time":return $wf2.dateToISO8601(a,b);default:return a}},addInvalidIndicator:function(a){var b=document.createElement("div");b.className="wf2_errorMsg";var d=document.createElement("div");d.className="wf2_errorMsgContainer";b.appendChild(d);b.id=(a.id||a.name)+"_wf2_errorMsg";b.onmousedown=function(){this.parentNode.removeChild(this)};var c=a.getAttribute("type")?a.getAttribute("type").toLowerCase():
+a.type,e=document.createElement("ol");a.validity.customError?e.appendChild($wf2.createLI(a.validationMessage)):(a.validity.valueMissing&&e.appendChild($wf2.createLI($wf2.invalidMessages.valueMissing)),a.validity.typeMismatch&&e.appendChild($wf2.createLI($wf2.invalidMessages.typeMismatch.replace(/%s/,c))),a.validity.rangeUnderflow&&e.appendChild($wf2.createLI($wf2.invalidMessages.rangeUnderflow.replace(/%s/,$wf2.valueToWF2Type(a.min,c)))),a.validity.rangeOverflow&&e.appendChild($wf2.createLI($wf2.invalidMessages.rangeOverflow.replace(/%s/,
+$wf2.valueToWF2Type(a.max,c)))),a.validity.stepMismatch&&e.appendChild($wf2.createLI($wf2.invalidMessages.stepMismatch.replace(/%s/,a.step+($wf2.stepUnits[c]?" "+$wf2.stepUnits[c]+"(s)":"")).replace(/%s/,$wf2.valueToWF2Type(a.wf2StepDatum,c)))),a.validity.tooLong&&e.appendChild($wf2.createLI($wf2.invalidMessages.tooLong.replace(/%s/,a.maxLength).replace(/%s/,a.wf2ValueLength?a.wf2ValueLength:a.value.length))),a.validity.patternMismatch&&e.appendChild($wf2.createLI($wf2.invalidMessages.patternMismatch.replace(/%s/,
+a.title?a.title:' "'+a.getAttribute("pattern")+'"'))));1==e.childNodes.length&&(e.className="single");d.appendChild(e);d=document.body?document.body:document.documentElement;$wf2.invalidIndicators.length?d.insertBefore(b,$wf2.invalidIndicators[$wf2.invalidIndicators.length-1].errorMsg):d.insertBefore(b,null);for(d=a;d&&(1!=d.nodeType||"none"==d.style.display||"hidden"==d.style.visibility||!d.offsetParent);)d=d.parentNode;c=left=0;if((e=d)&&e.offsetParent){left=e.offsetLeft;for(c=e.offsetTop;e=e.offsetParent;)left+=
+e.offsetLeft,c+=e.offsetTop;c+=d.offsetHeight}b.style.top=c+"px";b.style.left=left+"px";$wf2.invalidIndicators.push({target:a,errorMsg:b});$wf2.css.addClass(a,"wf2_invalid");null==$wf2.indicatorIntervalId&&($wf2.indicatorIntervalId=setInterval(function(){for(var a,b=0;a=$wf2.invalidIndicators[b];b++)$wf2.css.isMemberOfClass(a.target,"wf2_invalid")?$wf2.css.removeClass(a.target,"wf2_invalid"):$wf2.css.addClass(a.target,"wf2_invalid")},500))},clearInvalidIndicators:function(){clearTimeout($wf2.indicatorTimeoutId);
+$wf2.indicatorTimeoutId=null;clearInterval($wf2.indicatorIntervalId);$wf2.indicatorIntervalId=null;for(var a;a=$wf2.invalidIndicators[0];)a.errorMsg&&a.errorMsg.parentNode&&a.errorMsg.parentNode.removeChild(a.errorMsg),$wf2.invalidIndicators.shift()},cloneNode_customAttrs:{type:1,template:1,repeat:1,"repeat-template":1,"repeat-min":1,"repeat-max":1,"repeat-start":1,value:1,"class":1,required:1,pattern:1,form:1,autocomplete:1,autofocus:1,inputmode:1,max:1,min:1,step:1,onmoved:1,onadded:1,onremoved:1,
+onadd:1,onremove:1,onmove:1},cloneNode_skippedAttrs:{name:1,"class":1,"for":1,style:1,checked:1,addRepetitionBlock:1,addRepetitionBlockByIndex:1,moveRepetitionBlock:1,removeRepetitionBlock:1,repetitionBlocks:1,setCustomValidity:1,checkValidity:1,validity:1,validationMessage:1,willValidate:1,wf2StepDatum:1,wf2Value:1,wf2Initialized:1,wf2ValueLength:1},cloneNode_rtEventHandlerAttrs:{onmoved:1,onadded:1,onremoved:1,onadd:1,onremove:1,onmove:1},cloneNode:function(a,b,d){d||(d=0);var c,e,f;switch(a.nodeType){case 1:var g=
+"template"==a.getAttribute("repeat");g&&d++;c=[];a.name&&(c.name=b?b(a.name):a.name);"radio"==a.type&&(c.type=a.type);a.checked&&(c.checked="checked");c=$wf2.createElement(a.nodeName,c);for(e=0;f=a.attributes[e];e++)if((f.specified||$wf2.cloneNode_customAttrs[f.name])&&!$wf2.cloneNode_skippedAttrs[f.name]&&(!g||1<d||!$wf2.cloneNode_rtEventHandlerAttrs[f.name]))if(2>d&&0===f.name.indexOf("on")&&"function"==typeof a[f.name]){var m=b(a[f.name].toString().match(/{((?:.|\n)+)}/)[1]),m=b(m);c[f.name]=new Function("event",
+m)}else m=a.getAttribute(f.name),m=b?b(m):m,c.setAttribute(f.name,m);if(a.className)if(g=b?b(a.className):a.className,c.getAttributeNode("class"))for(e=0;e<c.attributes.length;e++)"class"==c.attributes[e].name&&(c.attributes[e].value=g);else c.setAttribute("class",g);/\bdisabled\b/.test(a.className)||(c.disabled=!1);a.style&&a.style.cssText&&(c.style.cssText=b?b(a.style.cssText):a.style.cssText);a.nodeName&&"label"==a.nodeName.toLowerCase()&&a.htmlFor&&(c.htmlFor=b?b(a.htmlFor):a.htmlFor);"option"==
+c.nodeName.toLowerCase()&&(c.selected=a.selected,c.defaultSelected=a.defaultSelected);for(e=0;e<a.childNodes.length;e++)c.appendChild($wf2.cloneNode(a.childNodes[e],b,d));break;case 3:case 4:c=document.createTextNode(a.data);break;case 8:c=document.createComment(a.data);break;default:c=a.cloneNode(!0)}return c},getFormElements:function(){for(var a=[],b=$wf2.getElementsByTagNames.apply(this,["input","output","select","textarea","button"]),d=0;d<b.length;d++){for(var c=b[d].parentNode;c&&1==c.nodeType&&
+"template"!=c.getAttribute("repeat");)c=c.parentNode;(!c||1!=c.nodeType)&&a.push(b[d])}return a},loadDataURI:function(a){a=a.data||a.getAttribute("data");if(!a)return null;var b=null,d;try{if(d=a.match(/^data:[^,]*xml[^,]*,((?:.|\n)+)/)){var c=decodeURI(d[1].replace(/%3D/ig,"=").replace(/%3A/ig,":").replace(/%2F/ig,"/"));window.DOMParser?b=(new DOMParser).parseFromString(c,"text/xml"):window.ActiveXObject&&(b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(c))}else $wf2.xhr.open("GET",
+a,!1),$wf2.xhr.send(null),b=$wf2.xhr.responseXML}catch(e){return null}return b},getAttributeByName:function(a,b){var d,c=a.attributes;for(d=0;d<c.length;d++){var e=c[d];if(e.nodeName==b&&e.specified)return e}return null},getAttributeValue:function(a,b){var d=$wf2.getAttributeByName(a,b);return null!=d?d.nodeValue:null},setAttributeValue:function(a,b,d){a=$wf2.getAttributeByName(a,b);null!=a&&(a.nodeValue=d)},getDatasetItem:function(a,b){var d=$wf2.getAttributeValue(a,"data-"+b);d||(d=$wf2.getAttributeValue(a,
+"data-"+b.toLowerCase()));d||(d=a["data-"+b.toLowerCase()]);return d},setDatasetItem:function(a,b,d){b="data-"+b.toLowerCase();$wf2.setAttributeValue(a,b,d);null==$wf2.getAttributeValue(a,b)&&(a[b]=d)},getElementsByTagNames:function(){var a,b,d=[];if(document.evaluate){a=[];for(b=0;b<arguments.length;b++)a.push(".//"+arguments[b]);a=document.evaluate(a.join("|"),this,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(b=0;b<a.snapshotLength;b++)d.push(a.snapshotItem(b))}else{for(b=0;b<arguments.length;b++){a=
+this.getElementsByTagName(arguments[b]);for(var c=0;c<a.length;c++)d.push(a[c])}$wf2.sortNodes&&d.sort($wf2.sortNodes)}return d},getElementsByTagNamesAndAttribute:function(a,b,d,c){var e,f,g,m,h=[];if(document.evaluate){e="";b&&(e="[@"+b+(d?(c?"!=":"=")+'"'+d+'"':"")+"]");b=[];for(g=0;g<a.length;g++)b.push(".//"+a[g]+e);e=document.evaluate(b.join("|"),this,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(g=0;g<e.snapshotLength;g++)h.push(e.snapshotItem(g))}else{for(g=0;g<a.length;g++){e=this.getElementsByTagName(a[g]);
+for(m=0;f=e[m];m++){var o=f.getAttributeNode(b),q=f.getAttribute(b);(!b||o&&(void 0===d||(c?q!=d:q==d)))&&h.push(f)}}$wf2.sortNodes&&h.sort($wf2.sortNodes)}return h},arrayHasItem:function(a,b){for(var d=0;d<a.length;d++)if(a[d]==b)return!0;return!1},getElementStyle:function(a,b){return a.currentStyle?a.currentStyle[b]:window.getComputedStyle?getComputedStyle(a,"").getPropertyValue(b):a.style?a.style[b]:""},createElement:function(){try{var a=document.createElement('<div name="foo">');if("div"!=a.tagName.toLowerCase()||
+"foo"!=a.name)throw"create element error";return function(a,b){var e="<"+a,f;for(f in b)e+=" "+f+'="'+b[f]+'"';e+=">";"input"!=a.toLowerCase()&&(e+="</"+a+">");return document.createElement(e)}}catch(b){return function(a,b){var e=document.createElement(a),f;for(f in b)e.setAttribute(f,b[f]);return e}}}(),sortNodes:function(){var a=document.documentElement.firstChild;if(a.sourceIndex)return function(a,d){return a.sourceIndex-d.sourceIndex};if(a.compareDocumentPosition)return function(a,d){return 3-
+(a.compareDocumentPosition(d)&6)}}(),createLI:function(a){var b=document.createElement("li");b.appendChild(document.createTextNode(a));return b},ISO8601RegExp:/^(?:(\d\d\d\d)-(W(0[1-9]|[1-4]\d|5[0-2])|(0\d|1[0-2])(-(0\d|[1-2]\d|3[0-1])(T(0\d|1\d|2[0-4]):([0-5]\d)(:([0-5]\d)(\.(\d+))?)?(Z)?)?)?)|(0\d|1\d|2[0-4]):([0-5]\d)(:([0-5]\d)(\.(\d+))?)?)$/,parseISO8601:function(a,b){var d=$wf2.validateDateTimeType(a,b);if(!d)return null;var c=new Date(0),e=8;if(d[15]){if(b&&"time"!=b)return null;e=15}else{c.setUTCFullYear(d[1]);
+if(d[3]){if(b&&"week"!=b)return null;c.setUTCDate(c.getUTCDate()+(8-c.getUTCDay())%7+7*(d[3]-1));return c}c.setUTCMonth(d[4]-1);d[6]&&c.setUTCDate(d[6])}d[e+0]&&c.setUTCHours(d[e+0]);d[e+1]&&c.setUTCMinutes(d[e+1]);d[e+2]&&c.setUTCSeconds(d[e+3]);d[e+4]&&c.setUTCMilliseconds(Math.round(1E3*Number(d[e+4])));d[4]&&d[e+0]&&!d[e+6]&&c.setUTCMinutes(c.getUTCMinutes()+c.getTimezoneOffset());return c},validateDateTimeType:function(a,b){var d=!1,c=$wf2.ISO8601RegExp.exec(a);if(!c||!b)return c;b=b.toLowerCase();
+if("week"==b)d=0===c[2].toString().indexOf("W");else if("time"==b)d=!!c[15];else if("month"==b)d=!c[5];else if(c[6])if((new Date(c[1],c[4]-1,c[6])).getMonth()!=c[4]-1)d=!1;else switch(b){case "date":d=c[4]&&!c[7];break;case "datetime":d=!!c[14];break;case "datetime-local":d=c[7]&&!c[14]}return d?c:null},zeroPad:function(a,b){b||(b=2);for(var d=a.toString();d.length<b;)d="0"+d;return d},dateToISO8601:function(a,b){var b=(""+b).toLowerCase(),d="";a.getUTCMilliseconds()&&(d="."+$wf2.zeroPad(a.getUTCMilliseconds(),
+3).replace(/0+$/,""));switch(b){case "date":return a.getUTCFullYear()+"-"+$wf2.zeroPad(a.getUTCMonth()+1)+"-"+$wf2.zeroPad(a.getUTCDate());case "datetime-local":return a.getFullYear()+"-"+$wf2.zeroPad(a.getMonth()+1)+"-"+$wf2.zeroPad(a.getDate())+"T"+$wf2.zeroPad(a.getHours())+":"+$wf2.zeroPad(a.getMinutes())+":"+$wf2.zeroPad(a.getMinutes())+d+"Z";case "month":return a.getUTCFullYear()+"-"+$wf2.zeroPad(a.getUTCMonth()+1);case "week":return d=$wf2.parseISO8601(a.getUTCFullYear()+"-W01"),a.getUTCFullYear()+
+"-W"+$wf2.zeroPad((a.valueOf()-d.valueOf())/6048E5+1);case "time":return $wf2.zeroPad(a.getUTCHours())+":"+$wf2.zeroPad(a.getUTCMinutes())+":"+$wf2.zeroPad(a.getUTCMinutes())+d;default:return a.getUTCFullYear()+"-"+$wf2.zeroPad(a.getUTCMonth()+1)+"-"+$wf2.zeroPad(a.getUTCDate())+"T"+$wf2.zeroPad(a.getUTCHours())+":"+$wf2.zeroPad(a.getUTCMinutes())+":"+$wf2.zeroPad(a.getUTCMinutes())+d+"Z"}},fireEvent:function(a,b){if(a)if(document.createEventObject)try{return a.fireEvent("on"+b,$wf2.globalEvent)}catch(d){return window.jQuery?
+jQuery(a).trigger(b):null}else return $wf2.globalEvent.initEvent(b,!0,!0),!a.dispatchEvent($wf2.globalEvent)},DOMException:function(a){var b="DOMException: ";switch(a){case 1:b+="INDEX_SIZE_ERR";break;case 9:b+="NOT_SUPPORTED_ERR";break;case 11:b+="INVALID_STATE_ERR";break;case 12:b+="SYNTAX_ERR";break;case 13:b+="INVALID_MODIFICATION_ERR"}b=Error(b);b.code=a;b.name="DOMException";b.INDEX_SIZE_ERR=1;b.NOT_SUPPORTED_ERR=9;b.INVALID_STATE_ERR=11;b.SYNTAX_ERR=12;b.INVALID_MODIFICATION_ERR=13;return b},
+css:new function(){function a(a){return"\\s"+a+"\\s|^"+a+"\\s|\\s"+a+"$|^"+a+"$"}var b=this,d=/\s/;b.addClass=function(a,e){!d.test(e)&&!b.isMemberOfClass(a,e)&&(a.className+=" "+e)};b.removeClass=function(b,e){if(!d.test(e)){var f=RegExp(a(e),"g"),g=b.className;b.className&&(b.className=g.replace(f," "))}};b.isMemberOfClass=function(b,e){return d.test(e)?!1:RegExp(a(e),"g").test(b.className)}}},document.addEventListener&&(document.addEventListener("DOMNodeInsertedIntoDocument",function(a){1==a.target.nodeType&&
+a.target.hasAttribute("autofocus")&&$wf2.initAutofocusElement(a.target)},!1),document.addEventListener("DOMAttrModified",function(a){"autofocus"==a.attrName&&(a.attrChange==a.ADDITION?$wf2.initAutofocusElement(a.target):a.attrChange==a.REMOVAL&&(a.target.autofocus=!1))},!1)),function(){for(var a,b=document.documentElement.getElementsByTagName("script"),d=0;d<b.length;d++)if(a=b[d].src.match(/^(.*)webforms2[^\/]+$/))$wf2.libpath=a[1];if(document.body)$wf2.onDOMContentLoaded();else{a=0;if(document.addEventListener){document.addEventListener("DOMContentLoaded",
+function(){$wf2.onDOMContentLoaded()},false);window.addEventListener("load",function(){$wf2.onDOMContentLoaded()},false);a=1}if(/WebKit/i.test(navigator.userAgent)){var c=setInterval(function(){if(/loaded|complete/.test(document.readyState)){clearInterval(c);delete c;$wf2.onDOMContentLoaded()}},10);a=1}else if(/MSIE/i.test(navigator.userAgent)&&!document.addEventListener&&window.attachEvent){window.attachEvent("onload",function(){$wf2.onDOMContentLoaded()});document.write("<script defer src='"+$wf2.libpath+
+"webforms2-msie.js'><\/script>");document.write("<script id='__wf2_ie_onload' defer src='//:'><\/script>");a=document.getElementById("__wf2_ie_onload");a.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);$wf2.onDOMContentLoaded();if(window.$wf2Rep&&$wf2.repetitionTemplates.length==0)$wf2.isInitialized=false}};a=null;a=1}if(!a)if(window.onload){var e=window.onload;window.onload=function(){$wf2.onDOMContentLoaded();e()}}else window.onload=function(){$wf2.onDOMContentLoaded()}}}())};
\ No newline at end of file
diff --git a/shared/js/weston.ruter.net/webforms2/webforms2-p.js b/shared/js/weston.ruter.net/webforms2/webforms2-p.js
new file mode 100644
index 0000000..ed28247
--- /dev/null
+++ b/shared/js/weston.ruter.net/webforms2/webforms2-p.js
@@ -0,0 +1,56 @@
+if(!window.$wf2){var $wf2={};document.implementation&&document.implementation.hasFeature&&!document.implementation.hasFeature("WebForms","2.0")&&($wf2={version:"0.5.4",isInitialized:!1,libpath:"",globalEvent:null,hasElementExtensions:window.HTMLElement&&HTMLElement.prototype,hasGettersAndSetters:$wf2.__defineGetter__&&$wf2.__defineSetter__,hasBadImplementation:0<navigator.userAgent.indexOf("WebKit"),callBeforeValidation:[],callAfterValidation:[],callAfterDOMContentLoaded:[],onDOMContentLoaded:function(){if(!$wf2.isInitialized){$wf2.isInitialized=
+!0;var a;document.createEventObject?$wf2.globalEvent=document.createEventObject():document.createEvent&&($wf2.globalEvent=document.createEvent("HTMLEvents"));a=document.createElement("link");a.setAttribute("type","text/css");a.setAttribute("rel","stylesheet");a.setAttribute("href",$wf2.libpath+"webforms2.css");var b=document.getElementsByTagName("head")[0];b||(b=document.getElementsByTagName("*")[0]);b.insertBefore(a,b.firstChild);$wf2.zeroPoint={};$wf2.zeroPoint.datetime=$wf2.parseISO8601("1970-01-01T00:00:00.0Z");
+$wf2.zeroPoint["datetime-local"]=$wf2.parseISO8601("1970-01-01T00:00:00.0");$wf2.zeroPoint.date=$wf2.zeroPoint.datetime;$wf2.zeroPoint.month=$wf2.zeroPoint.datetime;$wf2.zeroPoint.week=$wf2.parseISO8601("1970-W01");$wf2.zeroPoint.time=$wf2.zeroPoint.datetime;$wf2.xhr=null;if(window.XMLHttpRequest)$wf2.xhr=new XMLHttpRequest;else if(window.ActiveXObject)try{$wf2.xhr=new ActiveXObject("Msxml2.XMLHTTP")}catch(d){try{$wf2.xhr=new ActiveXObject("Microsoft.XMLHTTP")}catch(c){}}$wf2.xhr&&($wf2.prefillSelectElements(),
+$wf2.prefillFormElements());window.$wf2Rep&&($wf2.initRepetitionBlocks(),$wf2.initRepetitionTemplates(),$wf2.initRepetitionButtons("add"),$wf2.initRepetitionButtons("remove"),$wf2.initRepetitionButtons("move-up"),$wf2.initRepetitionButtons("move-down"),$wf2.updateAddButtons(),$wf2.updateMoveButtons());document.addEventListener?(document.addEventListener("mousedown",$wf2.clearInvalidIndicators,!1),document.addEventListener("keydown",$wf2.clearInvalidIndicators,!1)):document.attachEvent&&(document.attachEvent("onmousedown",
+$wf2.clearInvalidIndicators),document.attachEvent("onkeydown",$wf2.clearInvalidIndicators));$wf2.initNonRepetitionFunctionality();for(a=0;a<$wf2.callAfterDOMContentLoaded.length;a++)$wf2.callAfterDOMContentLoaded[a]()}},prefillSelectElements:function(){for(var a,b=$wf2.getElementsByTagNames.apply(document.documentElement,["select","datalist"]),d=0;a=b[d];d++){var c=$wf2.loadDataURI(a);if(c&&c.documentElement&&/:?\bselect$/i.test(c.documentElement.nodeName)&&"http://www.w3.org/1999/xhtml"==c.documentElement.namespaceURI){c=
+c.documentElement;if("incremental"!=c.getAttribute("type"))for(;a.lastChild;)a.removeChild(a.lastChild);for(node=c.firstChild;node;)a.appendChild($wf2.cloneNode(node)),node=node.nextSibling}}},prefillFormElements:function(){for(var a,b=document.getElementsByTagName("form"),d=0;a=b[d];d++){var c=$wf2.loadDataURI(a);if(c&&c.documentElement&&/:?\bformdata$/.test(c.documentElement.nodeName)&&"http://n.whatwg.org/formdata"==c.documentElement.namespaceURI){var e,f=c.documentElement;"incremental"!=f.getAttribute("type")&&
+a.reset();var g=f.getElementsByTagName("clear");for(j=0;c=g[j];j++)if("http://n.whatwg.org/formdata"==c.namespaceURI&&c.parentNode==f&&!c.firstChild&&(e=document.getElementById(c.getAttribute("template")))&&"template"==e.getAttribute("repeat"))for(var m,h,c=e.parentNode.firstChild;c;)1==c.nodeType&&(m=c.getAttributeNode("repeat"))&&"template"!=m.value?(h=c.nextSibling,c.parentNode.removeChild(c),c=h):c=c.nextSibling;var o,g=f.getElementsByTagName("repeat");for(j=0;c=g[j];j++)if("http://n.whatwg.org/formdata"==
+c.namespaceURI&&c.parentNode==f&&!c.firstChild&&(e=document.getElementById(c.getAttribute("template")))&&"template"==e.getAttribute("repeat")&&/^-?\d+$/.test(o=c.getAttribute("index"))){for(var q,c=e.parentNode.firstChild;c;){if(1==c.nodeType&&(m=c.getAttributeNode("repeat"))&&m.value==o){q=!0;break}c=c.nextSibling}q||$wf2.addRepetitionBlockByIndex.apply(e,[null,o])}var p,f=f.getElementsByTagName("field"),g=$wf2.getFormElements.apply(a);for(j=0;p=f[j];j++){var k=p.getAttributeNode("index"),n=p.getAttribute("name");
+if(n&&(!k||/^\d+$/.test(k.value))){h="";for(l=0;c=p.childNodes[l];l++)if(3==c.nodeType||4==c.nodeType)h+=c.data;else break;for(l=p=0;c=g[l];l++)if("image"==c.type){if(c.name?c.name+".x"==n||c.name+".y"==n:"x"==n||"y"==n)if(!k||++p-1>=k.value)break}else if(c.name==n){if(k){if(++p-1<k.value)continue}else if(("radio"==c.type||"checkbox"==c.type)&&h&&c.value!=h)continue;break}if(!("file"==c.type||"button"==c.type||"image"==c.type))if(!c.getAttributeNode("multiple")||!c.wf2Prefilled){if("checkbox"==c.type||
+"radio"==c.type)if(h)if(c.value==h)c.checked=!0;else break;else c.checked=!1;else if("select"==c.nodeName.toLowerCase()){c.selectedIndex=-1;for(var l=0;k=c.options[l];l++)if(k.value?k.value==h:k.text==h){k.selected=!0;break}}else c.value=h,$wf2.updateValidityState(c),c.validity.valid||(c.value=c.defaultValue,$wf2.updateValidityState(c));c.wf2Prefilled=!0}else if(c.getAttributeNode("multiple"))for(l=0;k=c.options[l];l++)if(!k.selected&&(k.value?k.value==h:k.text==h)){k.selected=!0;break}}}g=$wf2.getFormElements.apply(a);
+for(j=0;j<g.length;j++);}}},initNonRepetitionFunctionality:function(a){var a=a||document.documentElement,b,d,c=a.getElementsByTagName("form");for(b=0;d=c[b];b++)if(!d.checkValidity||$wf2.hasBadImplementation)d.checkValidity=$wf2.formCheckValidity,d.addEventListener?d.addEventListener("submit",$wf2.onsubmitValidityHandler,!1):d.attachEvent("onsubmit",$wf2.onsubmitValidityHandler);c=$wf2.getElementsByTagNames.apply(a,["input","select","textarea","button"]);for(b=0;d=c[b];b++)$wf2.applyValidityInterface(d),
+$wf2.updateValidityState(d);d=$wf2.getElementsByTagNamesAndAttribute.apply(document.documentElement,[["*"],"autofocus"]);a.getAttribute("autofocus")&&d.unshift(a);for(b=0;b<d.length;b++)$wf2.initAutofocusElement(d[b]);d=$wf2.getElementsByTagNamesAndAttribute.apply(a,[["textarea"],"maxlength"]);"textarea"==a.nodeName.toLowerCase()&&d.unshift(a);for(b=0;b<d.length;b++)d[b].maxLength=parseInt(d[b].getAttribute("maxlength"))},initAutofocusElement:function(a){if(!(!1===a.autofocus||!0===a.autofocus))if(a.autofocus=
+!0,!a.disabled){for(var b=a;b&&1==b.nodeType;){if("hidden"==$wf2.getElementStyle(b,"visibility")||"none"==$wf2.getElementStyle(b,"display"))return;b=b.parentNode}a.focus()}},formCheckValidity:function(){var a,b,d=!0,c=$wf2.getFormElements.apply(this);for(a=0;b=c[a];a++){var e=b.getAttribute("type")?b.getAttribute("type").toLowerCase():b.type;b.willValidate=!(/(hidden|button|reset|add|remove|move-up|move-down)/.test(e)||!b.name||b.disabled);b.checkValidity&&b.willValidate&&!b.checkValidity()&&void 0!=
+b.checkValidity()&&(d=!1)}d||$wf2.hiliteFirstError();return d},hiliteFirstError:function(){if($wf2.invalidIndicators.length){$wf2.css.addClass($wf2.invalidIndicators[0].errorMsg,"wf2_firstErrorMsg");el=$wf2.invalidIndicators[0].target;var a="true"!=el.form.getAttribute("data-wf2-no-scroll-on-error");if("none"==el.style.display||!el.offsetParent){for(;el&&(1!=el.nodeType||"none"==el.style.display||!el.offsetParent);)el=el.previousSibling;var b=el,d=0;if(b&&b.offsetParent)for(d=b.offsetTop;b=b.offsetParent;)d+=
+b.offsetTop;a&&scrollTo(0,d)}else setTimeout(function(){el.focus();$wf2.fireEvent(el,"focus")},10),a&&scrollBy(0,$wf2.invalidIndicators[0].errorMsg.offsetHeight)}},controlCheckValidity:function(){return $wf2.controlCheckValidityOfElement(this)},controlCheckValidityOfElement:function(a){$wf2.updateValidityState(a);if(a.validity.valid)return!0;var b=!1,d;try{$wf2.fireEvent(a,"invalid")}catch(c){d={},d.initEvent?d.initEvent("invalid",!0,!0):(d.type="invalid",d.cancelBubble=!1),d.target=d.srcElement=
+a}var e=a.getAttribute("oninvalid");if(e&&(!a.oninvalid||"function"!=typeof a.oninvalid))a.oninvalid=new Function("event",e);try{a.oninvalid&&(b=!1===a.oninvalid.apply(a,[d])||b)}catch(f){setTimeout(function(){throw f;},0)}d=!1;if("radio"==a.type||"checkbox"==a.type)for(e=0;e<$wf2.invalidIndicators.length;e++)if(a.form[a.name][0]==$wf2.invalidIndicators[e].target){d=!0;break}!b&&!d&&$wf2.addInvalidIndicator(a);return!1},numberRegExp:/^-?\d+(.\d+)?(e-?\d+)?$/,urlRegExp:/^(\w+):(\/\/)?.+$/i,emailRegExp:/^\S+@\S+$/i,
+copyOf:function(a){if(null!==a&&void 0!==a){var b={};for(i in a)try{b[i]=a[i]}catch(d){}}else b=null;return b},getOriginalAttrNode:function(a,b){return $wf2.copyOf(a.getAttributeNode(b))},updateValidityState:function(a){var b,d,c;b=$wf2.getOriginalAttrNode(a,"min");d=$wf2.getOriginalAttrNode(a,"max");l=$wf2.getOriginalAttrNode(a,"step");c=$wf2.getOriginalAttrNode(a,"value");a.min=void 0;a.max=void 0;a.step=void 0;a.validity=$wf2.createValidityState();a.validity.customError=!!a.validationMessage;var e=
+a.getAttribute("type")?a.getAttribute("type").toLowerCase():a.type,f="datetime"==e||"datetime-local"==e||"time"==e,g="date"==e||"month"==e||"week"==e,m="number"==e||"range"==e,h="file"==e,o=f||g||m,q=o||"textarea"==a.nodeName.toLowerCase(),p=o||h,k="radio"==e||"checkbox"==e,h=q||h||"email"==e||"url"==e||"text"==e||"password"==e||"tel"==e||k;if("range"==e){if(a.min=b&&$wf2.numberRegExp.test(b.value)?Number(b.value):0,(!c||!c.specified)&&""===a.value&&!a.wf2ValueProvided)a.setAttribute("value",a.min),
+a.value=a.min,a.wf2ValueProvided=!0}else{a.wf2Value=$wf2.css.isMemberOfClass(a,"html5-hasPlaceholderText")?"":a.value;e=a.getAttribute("type")?a.getAttribute("type").toLowerCase():a.type;a.willValidate=!(/(hidden|button|reset|add|remove|move-up|move-down)/.test(e)||!a.name||a.disabled);if(h&&a.willValidate)if(k){if(a.form&&a.form[a.name]){var h=k=!1,n=a.form[a.name];if(void 0==n.length)n.getAttributeNode("required")&&(k=!0),n.checked&&(h=!0);else for(c=0;c<n.length;c++)n[c].getAttributeNode("required")&&
+(k=!0),n[c].checked&&(h=!0);a.validity.valueMissing=k&&!h}}else a.getAttributeNode("required")&&(a.validity.valueMissing=""==a.wf2Value);if(!a.validity.valueMissing&&a.wf2Value){if(c=a.getAttributeNode("pattern"))c=RegExp("^(?:"+c.value+")$"),c.global=!1,c.ignoreCase=!1,c.multiline=!1,c&&(a.validity.patternMismatch=!c.test(a.wf2Value));if(!g&&!f)switch(e){case "number":case "range":a.validity.typeMismatch=!$wf2.numberRegExp.test(a.wf2Value);break;case "email":a.validity.typeMismatch=!$wf2.emailRegExp.test(a.wf2Value);
+break;case "url":a.validity.typeMismatch=!$wf2.urlRegExp.test(a.wf2Value)}if(!a.validity.patternMismatch&&!a.validity.typeMismatch){if(p)if(m){if("range"==e)a.max=d&&$wf2.numberRegExp.test(d.value)?Number(d.value):100;else if(b&&$wf2.numberRegExp.test(b.value)&&(a.min=Number(b.value)),d&&$wf2.numberRegExp.test(d.value)&&(a.max=Number(d.value)),l&&$wf2.numberRegExp.test(l.value))a.step=Number(l.value);a.validity.rangeUnderflow=void 0!=a.min&&Number(a.wf2Value)<a.min;a.validity.rangeOverflow=void 0!=
+a.max&&Number(a.wf2Value)>a.max;a.validity.stepMismatch=!$wf2.isValidNumber(a)}else if("file"==e)a.min=b&&/^\d+$/.test(b.value)?Number(b.value):0,a.max=d&&/^\d+$/.test(d.value)?Number(d.value):1;else if(b&&(a.min=$wf2.parseISO8601(b.value,e),a.validity.rangeUnderflow=a.min&&a.wf2Value<a.min),d)a.max=$wf2.parseISO8601(d.value,e),a.validity.rangeOverflow=a.max&&a.wf2Value>a.max;if(!g&&!f&&o&&!a.validity.rangeUnderflow&&!a.validity.rangeOverflow){var l=$wf2.getOriginalAttrNode(a,"step");a.step=l?"any"==
+l.value?"any":$wf2.numberRegExp.test(l.value)&&0<l.value?Number(l.value):f?60:1:f?60:1;if("any"!=a.step&&(a.wf2StepDatum=null,a.wf2StepDatum=b?a.min:d?a.max:$wf2.zeroPoint[e]?$wf2.zeroPoint[e]:0,b=a.step,!("month"==e&&a.wf2StepDatum&&a.wf2StepDatum.getUTCFullYear))){switch(e){case "datetime":case "datetime-local":case "time":b=parseInt(1E3*b);break;case "date":b=parseInt(864E5*b);break;case "week":b=parseInt(6048E5*b)}a.validity.stepMismatch=0!=Math.round(1E3*(a.wf2Value-a.wf2StepDatum))%Math.round(1E3*
+b)}}}if(q&&0<=a.maxLength&&a.wf2Value!=a.defaultValue){e=a.wf2Value;a.wf2ValueLength=e.length;for(c=1;c<e.length;c++)("\n"===e[c]&&"\r"!==e[c-1]||"\r"==e[c]&&e[c+1]&&"\n"!==e[c+1])&&a.wf2ValueLength++;a.validity.tooLong=a.wf2ValueLength>a.maxLength}}else if(b&&$wf2.numberRegExp.test(b.value)&&(a.min=Number(b.value)),d&&$wf2.numberRegExp.test(d.value)&&(a.max=Number(d.value)),l&&$wf2.numberRegExp.test(l.value))a.step=Number(l.value);a.validity.valid=!$wf2.hasInvalidState(a.validity);a.validity.valid?
+($wf2.css.removeClass(a,"wf2_invalid"),$wf2.css.addClass(a,"wf2_valid")):($wf2.css.removeClass(a,"wf2_valid"),$wf2.css.addClass(a,"wf2_invalid"))}},isValidNumber:function(a){a=(parseFloat(a.wf2Value)-parseFloat(a.min))/parseFloat(a.step);return a==parseInt(a)},applyValidityInterface:function(a){if($wf2.hasBadImplementation){if("submit"==a.type||"button"==a.type)a.formNoValidate=!0}else if(a.validity&&void 0!==a.validity.typeMismatch)return a;a.validationMessage="";a.validity=$wf2.createValidityState();
+a.willValidate=!0;var b=a.nodeName.toLowerCase();if("button"==b||"fieldset"==b)return a.setCustomValidity=function(){throw $wf2.DOMException(9);},a.checkValidity=function(){return!0},a;a.setCustomValidity||(a.setCustomValidity=$wf2.controlSetCustomValidity);a.checkValidity=$wf2.controlCheckValidity;if(/(hidden|button|reset|add|remove|move-up|move-down)/.test(a.getAttribute("type")?a.getAttribute("type").toLowerCase():a.type)||!a.name||a.disabled)a.willValidate=!1;else if(window.RepetitionElement)for(b=
+a;b=b.parentNode;)if(b.repetitionType==RepetitionElement.REPETITION_TEMPLATE){a.willValidate=!1;break}b=function(a){return $wf2.updateValidityState(a.currentTarget||a.srcElement)};document.addEventListener?(a.addEventListener("change",b,!1),a.addEventListener("blur",b,!1),a.addEventListener("keyup",b,!1)):window.attachEvent&&(a.attachEvent("onchange",b),a.attachEvent("onblur",b),a.attachEvent("onkeyup",b));return a},onsubmitValidityHandler:function(a){for(var b=a.currentTarget||a.srcElement,d=0;d<
+$wf2.callBeforeValidation.length;d++)$wf2.callBeforeValidation[d](a);b.checkValidity()?b=a.returnValue=!0:(a.preventDefault&&a.preventDefault(),b=a.returnValue=!1);for(d=0;d<$wf2.callAfterValidation.length;d++)$wf2.callAfterValidation[d](a,b);return b},controlSetCustomValidity:function(a){a?(this.validationMessage=""+a,this.validity.customError=!0):(this.validationMessage="",this.validity.customError=!1);this.validity.valid=!$wf2.hasInvalidState(this.validity)},hasInvalidState:function(a){return a.typeMismatch||
+a.rangeUnderflow||a.rangeOverflow||a.stepMismatch||a.tooLong||a.patternMismatch||a.valueMissing||a.customError},createValidityState:function(){return{typeMismatch:!1,rangeUnderflow:!1,rangeOverflow:!1,stepMismatch:!1,tooLong:!1,patternMismatch:!1,valueMissing:!1,customError:!1,valid:!0}},invalidIndicators:[],indicatorTimeoutId:null,indicatorIntervalId:null,stepUnits:{datetime:"second","datetime-local":"second",time:"second",date:"day",week:"week",month:"month"},invalidMessages:{valueMissing:"Please fill out this field.",
+typeMismatch:"Please enter a valid %s.",rangeUnderflow:"The value must be equal to or greater than %s.",rangeOverflow:"The value must be equal to or less than %s.",stepMismatch:"The value has a step mismatch; it must be a certain number multiples of %s from %s.",tooLong:"The value is too long. The field may have a maximum of %s characters but you supplied %s. Note that each line-break counts as two characters.",patternMismatch:"Please match the requested format."},valueToWF2Type:function(a,b){switch((""+
+b).toLowerCase()){case "datetime":case "datetime-local":case "date":case "month":case "week":case "time":return $wf2.dateToISO8601(a,b);default:return a}},addInvalidIndicator:function(a){console.log("addInvalidIndicator");var b=document.createElement("div");b.className="wf2_errorMsg";var d=document.createElement("div");d.className="wf2_errorMsgContainer";b.appendChild(d);b.id=(a.id||a.name)+"_wf2_errorMsg";b.onmousedown=function(){this.parentNode.removeChild(this)};var c=a.getAttribute("type")?a.getAttribute("type").toLowerCase():
+a.type,e=document.createElement("ol");a.validity.customError?e.appendChild($wf2.createLI(a.validationMessage)):(a.validity.valueMissing&&e.appendChild($wf2.createLI($wf2.invalidMessages.valueMissing)),a.validity.typeMismatch&&e.appendChild($wf2.createLI($wf2.invalidMessages.typeMismatch.replace(/%s/,c))),a.validity.rangeUnderflow&&e.appendChild($wf2.createLI($wf2.invalidMessages.rangeUnderflow.replace(/%s/,$wf2.valueToWF2Type(a.min,c)))),a.validity.rangeOverflow&&e.appendChild($wf2.createLI($wf2.invalidMessages.rangeOverflow.replace(/%s/,
+$wf2.valueToWF2Type(a.max,c)))),a.validity.stepMismatch&&e.appendChild($wf2.createLI($wf2.invalidMessages.stepMismatch.replace(/%s/,a.step+($wf2.stepUnits[c]?" "+$wf2.stepUnits[c]+"(s)":"")).replace(/%s/,$wf2.valueToWF2Type(a.wf2StepDatum,c)))),a.validity.tooLong&&e.appendChild($wf2.createLI($wf2.invalidMessages.tooLong.replace(/%s/,a.maxLength).replace(/%s/,a.wf2ValueLength?a.wf2ValueLength:a.value.length))),a.validity.patternMismatch&&e.appendChild($wf2.createLI($wf2.invalidMessages.patternMismatch.replace(/%s/,
+a.title?a.title:' "'+a.getAttribute("pattern")+'"'))));1==e.childNodes.length&&(e.className="single");d.appendChild(e);d=document.body?document.body:document.documentElement;$wf2.invalidIndicators.length?d.insertBefore(b,$wf2.invalidIndicators[$wf2.invalidIndicators.length-1].errorMsg):d.insertBefore(b,null);for(d=a;d&&(1!=d.nodeType||"none"==d.style.display||"hidden"==d.style.visibility||!d.offsetParent);)d=d.parentNode;c=left=0;if((e=d)&&e.offsetParent){left=e.offsetLeft;for(c=e.offsetTop;e=e.offsetParent;)left+=
+e.offsetLeft,c+=e.offsetTop;c+=d.offsetHeight}b.style.top=c+"px";b.style.left=left+"px";$wf2.invalidIndicators.push({target:a,errorMsg:b});$wf2.css.addClass(a,"wf2_invalid");null==$wf2.indicatorIntervalId&&($wf2.indicatorIntervalId=setInterval(function(){for(var a,b=0;a=$wf2.invalidIndicators[b];b++)$wf2.css.isMemberOfClass(a.target,"wf2_invalid")?$wf2.css.removeClass(a.target,"wf2_invalid"):$wf2.css.addClass(a.target,"wf2_invalid")},500))},clearInvalidIndicators:function(){clearTimeout($wf2.indicatorTimeoutId);
+$wf2.indicatorTimeoutId=null;clearInterval($wf2.indicatorIntervalId);$wf2.indicatorIntervalId=null;for(var a;a=$wf2.invalidIndicators[0];)a.errorMsg&&a.errorMsg.parentNode&&a.errorMsg.parentNode.removeChild(a.errorMsg),$wf2.invalidIndicators.shift()},cloneNode_customAttrs:{type:1,template:1,repeat:1,"repeat-template":1,"repeat-min":1,"repeat-max":1,"repeat-start":1,value:1,"class":1,required:1,pattern:1,form:1,autocomplete:1,autofocus:1,inputmode:1,max:1,min:1,step:1,onmoved:1,onadded:1,onremoved:1,
+onadd:1,onremove:1,onmove:1},cloneNode_skippedAttrs:{name:1,"class":1,"for":1,style:1,checked:1,addRepetitionBlock:1,addRepetitionBlockByIndex:1,moveRepetitionBlock:1,removeRepetitionBlock:1,repetitionBlocks:1,setCustomValidity:1,checkValidity:1,validity:1,validationMessage:1,willValidate:1,wf2StepDatum:1,wf2Value:1,wf2Initialized:1,wf2ValueLength:1},cloneNode_rtEventHandlerAttrs:{onmoved:1,onadded:1,onremoved:1,onadd:1,onremove:1,onmove:1},cloneNode:function(a,b,d){d||(d=0);var c,e,f;switch(a.nodeType){case 1:var g=
+"template"==a.getAttribute("repeat");g&&d++;c=[];a.name&&(c.name=b?b(a.name):a.name);"radio"==a.type&&(c.type=a.type);a.checked&&(c.checked="checked");c=$wf2.createElement(a.nodeName,c);for(e=0;f=a.attributes[e];e++)if((f.specified||$wf2.cloneNode_customAttrs[f.name])&&!$wf2.cloneNode_skippedAttrs[f.name]&&(!g||1<d||!$wf2.cloneNode_rtEventHandlerAttrs[f.name]))if(2>d&&0===f.name.indexOf("on")&&"function"==typeof a[f.name]){var m=b(a[f.name].toString().match(/{((?:.|\n)+)}/)[1]),m=b(m);c[f.name]=new Function("event",
+m)}else m=a.getAttribute(f.name),m=b?b(m):m,c.setAttribute(f.name,m);if(a.className)if(g=b?b(a.className):a.className,c.getAttributeNode("class"))for(e=0;e<c.attributes.length;e++)"class"==c.attributes[e].name&&(c.attributes[e].value=g);else c.setAttribute("class",g);/\bdisabled\b/.test(a.className)||(c.disabled=!1);a.style&&a.style.cssText&&(c.style.cssText=b?b(a.style.cssText):a.style.cssText);a.nodeName&&"label"==a.nodeName.toLowerCase()&&a.htmlFor&&(c.htmlFor=b?b(a.htmlFor):a.htmlFor);"option"==
+c.nodeName.toLowerCase()&&(c.selected=a.selected,c.defaultSelected=a.defaultSelected);for(e=0;e<a.childNodes.length;e++)c.appendChild($wf2.cloneNode(a.childNodes[e],b,d));break;case 3:case 4:c=document.createTextNode(a.data);break;case 8:c=document.createComment(a.data);break;default:c=a.cloneNode(!0)}return c},getFormElements:function(){for(var a=[],b=$wf2.getElementsByTagNames.apply(this,["input","output","select","textarea","button"]),d=0;d<b.length;d++){for(var c=b[d].parentNode;c&&1==c.nodeType&&
+"template"!=c.getAttribute("repeat");)c=c.parentNode;(!c||1!=c.nodeType)&&a.push(b[d])}return a},loadDataURI:function(a){a=a.data||a.getAttribute("data");if(!a)return null;var b=null,d;try{if(d=a.match(/^data:[^,]*xml[^,]*,((?:.|\n)+)/)){var c=decodeURI(d[1].replace(/%3D/ig,"=").replace(/%3A/ig,":").replace(/%2F/ig,"/"));window.DOMParser?b=(new DOMParser).parseFromString(c,"text/xml"):window.ActiveXObject&&(b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(c))}else $wf2.xhr.open("GET",
+a,!1),$wf2.xhr.send(null),b=$wf2.xhr.responseXML}catch(e){return null}return b},getAttributeByName:function(a,b){var d,c=a.attributes;for(d=0;d<c.length;d++){var e=c[d];if(e.nodeName==b&&e.specified)return e}return null},getAttributeValue:function(a,b){var d=$wf2.getAttributeByName(a,b);return null!=d?d.nodeValue:null},setAttributeValue:function(a,b,d){a=$wf2.getAttributeByName(a,b);null!=a&&(a.nodeValue=d)},getDatasetItem:function(a,b){var d=$wf2.getAttributeValue(a,"data-"+b);d||(d=$wf2.getAttributeValue(a,
+"data-"+b.toLowerCase()));d||(d=a["data-"+b.toLowerCase()]);return d},setDatasetItem:function(a,b,d){b="data-"+b.toLowerCase();$wf2.setAttributeValue(a,b,d);null==$wf2.getAttributeValue(a,b)&&(a[b]=d)},getElementsByTagNames:function(){var a,b,d=[];if(document.evaluate){a=[];for(b=0;b<arguments.length;b++)a.push(".//"+arguments[b]);a=document.evaluate(a.join("|"),this,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(b=0;b<a.snapshotLength;b++)d.push(a.snapshotItem(b))}else{for(b=0;b<arguments.length;b++){a=
+this.getElementsByTagName(arguments[b]);for(var c=0;c<a.length;c++)d.push(a[c])}$wf2.sortNodes&&d.sort($wf2.sortNodes)}return d},getElementsByTagNamesAndAttribute:function(a,b,d,c){var e,f,g,m,h=[];if(document.evaluate){e="";b&&(e="[@"+b+(d?(c?"!=":"=")+'"'+d+'"':"")+"]");b=[];for(g=0;g<a.length;g++)b.push(".//"+a[g]+e);e=document.evaluate(b.join("|"),this,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(g=0;g<e.snapshotLength;g++)h.push(e.snapshotItem(g))}else{for(g=0;g<a.length;g++){e=this.getElementsByTagName(a[g]);
+for(m=0;f=e[m];m++){var o=f.getAttributeNode(b),q=f.getAttribute(b);(!b||o&&(void 0===d||(c?q!=d:q==d)))&&h.push(f)}}$wf2.sortNodes&&h.sort($wf2.sortNodes)}return h},arrayHasItem:function(a,b){for(var d=0;d<a.length;d++)if(a[d]==b)return!0;return!1},getElementStyle:function(a,b){return a.currentStyle?a.currentStyle[b]:window.getComputedStyle?getComputedStyle(a,"").getPropertyValue(b):a.style?a.style[b]:""},createElement:function(){try{var a=document.createElement('<div name="foo">');if("div"!=a.tagName.toLowerCase()||
+"foo"!=a.name)throw"create element error";return function(a,b){var e="<"+a,f;for(f in b)e+=" "+f+'="'+b[f]+'"';e+=">";"input"!=a.toLowerCase()&&(e+="</"+a+">");return document.createElement(e)}}catch(b){return function(a,b){var e=document.createElement(a),f;for(f in b)e.setAttribute(f,b[f]);return e}}}(),sortNodes:function(){var a=document.documentElement.firstChild;if(a.sourceIndex)return function(a,d){return a.sourceIndex-d.sourceIndex};if(a.compareDocumentPosition)return function(a,d){return 3-
+(a.compareDocumentPosition(d)&6)}}(),createLI:function(a){var b=document.createElement("li");b.appendChild(document.createTextNode(a));return b},ISO8601RegExp:/^(?:(\d\d\d\d)-(W(0[1-9]|[1-4]\d|5[0-2])|(0\d|1[0-2])(-(0\d|[1-2]\d|3[0-1])(T(0\d|1\d|2[0-4]):([0-5]\d)(:([0-5]\d)(\.(\d+))?)?(Z)?)?)?)|(0\d|1\d|2[0-4]):([0-5]\d)(:([0-5]\d)(\.(\d+))?)?)$/,parseISO8601:function(a,b){var d=$wf2.validateDateTimeType(a,b);if(!d)return null;var c=new Date(0),e=8;if(d[15]){if(b&&"time"!=b)return null;e=15}else{c.setUTCFullYear(d[1]);
+if(d[3]){if(b&&"week"!=b)return null;c.setUTCDate(c.getUTCDate()+(8-c.getUTCDay())%7+7*(d[3]-1));return c}c.setUTCMonth(d[4]-1);d[6]&&c.setUTCDate(d[6])}d[e+0]&&c.setUTCHours(d[e+0]);d[e+1]&&c.setUTCMinutes(d[e+1]);d[e+2]&&c.setUTCSeconds(d[e+3]);d[e+4]&&c.setUTCMilliseconds(Math.round(1E3*Number(d[e+4])));d[4]&&d[e+0]&&!d[e+6]&&c.setUTCMinutes(c.getUTCMinutes()+c.getTimezoneOffset());return c},validateDateTimeType:function(a,b){var d=!1,c=$wf2.ISO8601RegExp.exec(a);if(!c||!b)return c;b=b.toLowerCase();
+if("week"==b)d=0===c[2].toString().indexOf("W");else if("time"==b)d=!!c[15];else if("month"==b)d=!c[5];else if(c[6])if((new Date(c[1],c[4]-1,c[6])).getMonth()!=c[4]-1)d=!1;else switch(b){case "date":d=c[4]&&!c[7];break;case "datetime":d=!!c[14];break;case "datetime-local":d=c[7]&&!c[14]}return d?c:null},zeroPad:function(a,b){b||(b=2);for(var d=a.toString();d.length<b;)d="0"+d;return d},dateToISO8601:function(a,b){var b=(""+b).toLowerCase(),d="";a.getUTCMilliseconds()&&(d="."+$wf2.zeroPad(a.getUTCMilliseconds(),
+3).replace(/0+$/,""));switch(b){case "date":return a.getUTCFullYear()+"-"+$wf2.zeroPad(a.getUTCMonth()+1)+"-"+$wf2.zeroPad(a.getUTCDate());case "datetime-local":return a.getFullYear()+"-"+$wf2.zeroPad(a.getMonth()+1)+"-"+$wf2.zeroPad(a.getDate())+"T"+$wf2.zeroPad(a.getHours())+":"+$wf2.zeroPad(a.getMinutes())+":"+$wf2.zeroPad(a.getMinutes())+d+"Z";case "month":return a.getUTCFullYear()+"-"+$wf2.zeroPad(a.getUTCMonth()+1);case "week":return d=$wf2.parseISO8601(a.getUTCFullYear()+"-W01"),a.getUTCFullYear()+
+"-W"+$wf2.zeroPad((a.valueOf()-d.valueOf())/6048E5+1);case "time":return $wf2.zeroPad(a.getUTCHours())+":"+$wf2.zeroPad(a.getUTCMinutes())+":"+$wf2.zeroPad(a.getUTCMinutes())+d;default:return a.getUTCFullYear()+"-"+$wf2.zeroPad(a.getUTCMonth()+1)+"-"+$wf2.zeroPad(a.getUTCDate())+"T"+$wf2.zeroPad(a.getUTCHours())+":"+$wf2.zeroPad(a.getUTCMinutes())+":"+$wf2.zeroPad(a.getUTCMinutes())+d+"Z"}},fireEvent:function(a,b){if(a)if(document.createEventObject)try{return a.fireEvent("on"+b,$wf2.globalEvent)}catch(d){return window.jQuery?
+jQuery(a).trigger(b):null}else return $wf2.globalEvent.initEvent(b,!0,!0),!a.dispatchEvent($wf2.globalEvent)},DOMException:function(a){var b="DOMException: ";switch(a){case 1:b+="INDEX_SIZE_ERR";break;case 9:b+="NOT_SUPPORTED_ERR";break;case 11:b+="INVALID_STATE_ERR";break;case 12:b+="SYNTAX_ERR";break;case 13:b+="INVALID_MODIFICATION_ERR"}b=Error(b);b.code=a;b.name="DOMException";b.INDEX_SIZE_ERR=1;b.NOT_SUPPORTED_ERR=9;b.INVALID_STATE_ERR=11;b.SYNTAX_ERR=12;b.INVALID_MODIFICATION_ERR=13;return b},
+css:new function(){function a(a){return"\\s"+a+"\\s|^"+a+"\\s|\\s"+a+"$|^"+a+"$"}var b=this,d=/\s/;b.addClass=function(a,e){!d.test(e)&&!b.isMemberOfClass(a,e)&&(a.className+=" "+e)};b.removeClass=function(b,e){if(!d.test(e)){var f=RegExp(a(e),"g"),g=b.className;b.className&&(b.className=g.replace(f," "))}};b.isMemberOfClass=function(b,e){return d.test(e)?!1:RegExp(a(e),"g").test(b.className)}}},document.addEventListener&&(document.addEventListener("DOMNodeInsertedIntoDocument",function(a){1==a.target.nodeType&&
+a.target.hasAttribute("autofocus")&&$wf2.initAutofocusElement(a.target)},!1),document.addEventListener("DOMAttrModified",function(a){"autofocus"==a.attrName&&(a.attrChange==a.ADDITION?$wf2.initAutofocusElement(a.target):a.attrChange==a.REMOVAL&&(a.target.autofocus=!1))},!1)),function(){for(var a,b=document.documentElement.getElementsByTagName("script"),d=0;d<b.length;d++)if(a=b[d].src.match(/^(.*)webforms2[^\/]+$/))$wf2.libpath=a[1];if(document.body)$wf2.onDOMContentLoaded();else{a=0;if(document.addEventListener){document.addEventListener("DOMContentLoaded",
+function(){$wf2.onDOMContentLoaded()},false);window.addEventListener("load",function(){$wf2.onDOMContentLoaded()},false);a=1}if(/WebKit/i.test(navigator.userAgent)){var c=setInterval(function(){if(/loaded|complete/.test(document.readyState)){clearInterval(c);delete c;$wf2.onDOMContentLoaded()}},10);a=1}else if(/MSIE/i.test(navigator.userAgent)&&!document.addEventListener&&window.attachEvent){window.attachEvent("onload",function(){$wf2.onDOMContentLoaded()});document.write("<script defer src='"+$wf2.libpath+
+"webforms2-msie.js'><\/script>");document.write("<script id='__wf2_ie_onload' defer src='//:'><\/script>");a=document.getElementById("__wf2_ie_onload");a.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);$wf2.onDOMContentLoaded();if(window.$wf2Rep&&$wf2.repetitionTemplates.length==0)$wf2.isInitialized=false}};a=null;a=1}if(!a)if(window.onload){var e=window.onload;window.onload=function(){$wf2.onDOMContentLoaded();e()}}else window.onload=function(){$wf2.onDOMContentLoaded()}}}())};
\ No newline at end of file
diff --git a/shared/js/weston.ruter.net/webforms2/webforms2.css b/shared/js/weston.ruter.net/webforms2/webforms2.css
index 1f505cc..f1d4b27 100644
--- a/shared/js/weston.ruter.net/webforms2/webforms2.css
+++ b/shared/js/weston.ruter.net/webforms2/webforms2.css
@@ -1,42 +1,202 @@
-input.wf2_invalid, textarea.wf2_invalid, select.wf2_invalid, div.wf2_errorMsg  { background-color:#FFCCCC; }
-
-div.wf2_errorMsg {
-	position:absolute;
-	border:dotted 1px red;
-	padding:.25em .5em .25em .5em;
-	cursor:default;
-	font-size:smaller;
-	max-width:25%;
-	opacity:0.5;	
-	filter: alpha(opacity=50);
-}
-
-div.wf2_firstErrorMsg,
-div.wf2_errorMsg:hover {
-	opacity:1.0;
-	filter: alpha(opacity=100);
-}
-div.wf2_errorMsg:hover {
-	z-index:100;
-}
-
-div.wf2_errorMsg ol {
-	list-style-position:inside;
-	margin:0;
-	padding:0;
-}
-div.wf2_errorMsg ol.single,
-div.wf2_errorMsg ol.single li {
-	list-style:none;
-	display:inline;
-}
-/*
-@namespace xh url(http://www.w3.org/1999/xhtml);
-:not(xh|*)[xh|repeat="template"],
-xh|*[|repeat="template"] {
-	display: none;
-}*/
-
-*[repeat="template"] {
-	display:none;
-}
\ No newline at end of file
+input.wf2_invalid, textarea.wf2_invalid, select.wf2_invalid, div.wf2_errorMsg  {  }
+
+div.wf2_errorMsg {
+	position:absolute;
+	border:dotted 1px red;
+	padding:.25em .5em .25em .5em;
+	cursor:default;
+	font-size:smaller;
+	max-width:25%;
+	display: none;
+	/* filter: alpha(opacity=50); */
+}
+
+div.wf2_firstErrorMsg,
+div.wf2_errorMsg:hover {
+	display: block;
+	opacity:1.0;
+	/* filter: alpha(opacity=100); */
+}
+div.wf2_errorMsg:hover {
+	z-index:100;
+}
+
+div.wf2_errorMsg ol {
+	list-style-position:inside;
+	margin:0;
+	padding:0;
+}
+div.wf2_errorMsg ol.single,
+div.wf2_errorMsg ol.single li {
+	list-style:none;
+	display:inline;
+}
+/*
+@namespace xh url(http://www.w3.org/1999/xhtml);
+:not(xh|*)[xh|repeat="template"],
+xh|*[|repeat="template"] {
+	display: none;
+}*/
+
+*[repeat="template"] {
+	display:none;
+}
+
+
+
+.wf2_errorMsg {
+	z-index: 10000;
+	border: solid #747474 1px !important;
+	border-radius: 10px;
+	background-image: linear-gradient(top, #535353 50%, #2c2d2e 100%);
+	background-image: -o-linear-gradient(top, #535353 50%, #2c2d2e 100%);
+	background-image:  -moz-linear-gradient(top, #535353 50%, #2c2d2e 100%);
+	background-image: -webkit-linear-gradient(top, #535353 50%, #2c2d2e 100%);
+	background-image: -ms-linear-gradient(top, #535353 50%, #2c2d2e 100%);
+	
+	background-image: -webkit-gradient(
+		linear,
+		left top,
+		left bottom,
+		color-stop(0.5, #535353),
+		color-stop(1, #2c2d2e)
+	);
+	background-color: none !important;
+	padding: 0 !important;
+	zoom: 1;
+	
+	color: white;
+	margin-top: 15px;
+	font-family: "Arial", "Helvetica", sans-serif;
+	
+}
+
+.wf2_errorMsgContainer {
+	padding: 20px 10px !important;
+	filter: progid:DXImageTransform.Microsoft.Gradient(startColorstr='#535353', endColorstr='#2c2d2e', GradientType=0);
+}
+
+
+
+form:not(.wf2-keep-native-style) ::-webkit-validation-bubble-message {
+		display: block;
+	    font: message-box;
+	    min-width: 50px;
+	    max-width: 200px;
+	    
+	    /* don't make this more than 1px wide -- if you do, it will look bad in webkit */
+	    border: 1px solid black;
+	    background: -webkit-gradient(linear, left top, left bottom, from(#535353), to(#2c2d2e));
+	    padding: 18px;
+	    -webkit-border-radius: 8px;
+    	-webkit-box-shadow: 0 0 0 0;
+	    line-height: normal;
+	    color: white;
+	    
+	    
+	    z-index: 10000;
+	    position: relative;
+	    
+    
+}
+
+
+form:not(.wf2-keep-native-style) ::-webkit-validation-bubble-top-outer-arrow {
+    border-bottom-color: #535353;
+}
+
+form:not(.wf2-keep-native-style) ::-webkit-validation-bubble-top-inner-arrow {
+    border-bottom-color: #535353;
+}
+
+form:not(.wf2-keep-native-style) ::-webkit-validation-bubble-arrow {
+	background: #535353;
+    border-color: transparent;
+    -webkit-box-shadow: 0 0 0 0;
+}
+
+form:not(.wf2-keep-native-style) ::-webkit-validation-bubble-icon {
+	display: none;
+}
+
+.wf2_errorMsg:before {
+	content: " ";
+	visibility: visible;
+	display: block;
+	width: 29px;
+	height: 15px;
+	
+	background: url('validationPointer.png');
+	position: absolute;
+	top: -15px;
+	left: 10px;
+
+	
+}
+
+/*
+input:invalid {
+	box-shadow: 0 0 3px rgba(255, 0, 0, 0.7);
+	-webkit-box-shadow: 0 0 3px rgba(255, 0, 0, 0.7);
+	border: solid 1px #999999;
+}
+
+input.wf2_invalid, textarea.wf2_invalid, select.wf2_invalid {
+	box-shadow: 0 0 3px rgba(255, 0, 0, 0.7);
+	-webkit-box-shadow: 0 0 3px rgba(255, 0, 0, 0.7);
+	border: solid 1px #999999;
+}
+
+body.ie7 input.wf2_invalid,
+body.ie8 input.wf2_invalid {
+	border: solid 1px #ff6666;
+}
+*/
+
+/*
+:-moz-submit-invalid {
+	background: red !important;
+}
+*/
+
+
+/* HTML5Widgets Placeholder text */
+.html5-hasPlaceholderText{font-family: "Arial", "Helvetica", sans-serif !important; color: #999999; font-style: italic}
+input::-webkit-input-placeholder {font-family: "Arial", "Helvetica", sans-serif; color: #999999; font-style: italic}
+input:-moz-placeholder {font-family: "Arial", "Helvetica", sans-serif; color: #999999; font-style: italic}
+input:-ms-input-placeholder {font-family: "Arial", "Helvetica", sans-serif; color: #999999; font-style: italic}
+
+
+/* 
+ * Default input invalid states.
+ */
+
+/* @-webkit-keyframes bounce {
+  0% {
+    opacity: 0.5;
+    margin-left: 85px;
+  }
+
+  25% {
+    margin-left: -35px;
+  }
+
+  50% {
+    margin-left: 50px;
+  }
+
+  75% {
+    margin-left: -22px;
+  }
+
+  100% {
+    margin-left: -15px;
+    opacity: 0.9;
+  }
+}
+
+form:not(.wf2-keep-native-style) ::-webkit-validation-bubble {
+  -webkit-animation-timing-function: ease;
+  -webkit-animation: bounce 0.45s 1;
+   
+} */
\ No newline at end of file
diff --git a/shared/js/weston.ruter.net/webforms2/webforms2_src.js b/shared/js/weston.ruter.net/webforms2/webforms2_src.js
index f15d8ee..5a8b110 100644
--- a/shared/js/weston.ruter.net/webforms2/webforms2_src.js
+++ b/shared/js/weston.ruter.net/webforms2/webforms2_src.js
@@ -1,10 +1,11 @@
 /*
  * Web Forms 2.0 Cross-browser Implementation <http://code.google.com/p/webforms2/>
- * Version: 0.6.1 (2010-09-10)
+ * Version: 0.7 (2011-03-01)
  * Copyright: 2007, Weston Ruter <http://weston.ruter.net/> 
  *    with additions by Zoltan Hawryluk <http://www.useragentman.com>
- * License: GNU General Public License, Free Software Foundation
- *          <http://creativecommons.org/licenses/GPL/2.0/>
+ * Licenses (as of Feb 6, 2011)
+ * - MIT License (http://www.opensource.org/licenses/mit-license.php)
+ * - GPL (http://creativecommons.org/licenses/GPL/2.0/)
  * 
  * The comments contained in this code are largely quotations from the 
  * WebForms 2.0 specification: <http://whatwg.org/specs/web-forms/current-work/>
@@ -15,6 +16,10 @@
  * version 0.5.4  - initial release by Weston Ruter
  * version 0.6    - refactored for use with HTML5Widgets by Zoltan Hawryluk (July 27th, 2010)
  * version 0.6.1  - updated to deal with WebKit's half-implemented WebForms 2 Implementation (Sept 10, 2010)
+ * version 0.7    - bug fixes with nested repetition models by Zoltan Hawryluk.
+ * version 0.7.1  - updated to dual MIT/GPL 2.0 license.
+ * version 1.0    - Updated to mimic CSS validation pseudo-classes, support for newer browsers
+ *                  native support (IE10, Firefox 4, Webkit, Opera 11.11)
  */
 
 if(!window.$wf2){
@@ -32,10 +37,14 @@ $wf2 = {
 	hasElementExtensions : (window.HTMLElement && HTMLElement.prototype),
 	hasGettersAndSetters : ($wf2.__defineGetter__ && $wf2.__defineSetter__),
 	
-	hasBadImplementation: navigator.userAgent.indexOf('WebKit'),
+	hasBadImplementation: navigator.userAgent.indexOf('WebKit') > 0,
+	
+	// WebKit less than 534 doesn't show validation UI - we need to check for this (from http://stackoverflow.com/questions/6030522/html5-form-validation-modernizr-safari)
+	hasNativeBubbles: navigator.userAgent.indexOf('WebKit') < 0 || parseInt(navigator.userAgent.match(/AppleWebKit\/([^ ]*)/)[1].split('.')[0])  > 534,
 	
 	callBeforeValidation : new Array(),
 	callAfterValidation : new Array(),
+	callAfterDOMContentLoaded: new Array(),
 	
 	
 	onDOMContentLoaded : function(){
@@ -99,15 +108,16 @@ $wf2 = {
 		//   first, looking for templates so that their initial repetition blocks can be created. ... UAs should not 
 		//   specifically wait for images and style sheets to be loaded before creating initial repetition blocks 
 		//   as described above.
-		$wf2.initRepetitionBlocks();
-		$wf2.initRepetitionTemplates();
-		$wf2.initRepetitionButtons('add');
-		$wf2.initRepetitionButtons('remove');
-		$wf2.initRepetitionButtons('move-up');
-		$wf2.initRepetitionButtons('move-down');
-		$wf2.updateAddButtons();
-		$wf2.updateMoveButtons();
-	
+		if (window.$wf2Rep) {
+			$wf2.initRepetitionBlocks();
+			$wf2.initRepetitionTemplates();
+			$wf2.initRepetitionButtons('add');
+			$wf2.initRepetitionButtons('remove');
+			$wf2.initRepetitionButtons('move-up');
+			$wf2.initRepetitionButtons('move-down');
+			$wf2.updateAddButtons();
+			$wf2.updateMoveButtons();
+		}
 		// Initialize Non-Repetition Behaviors ****************************************
 		if(document.addEventListener){
 			document.addEventListener('mousedown', $wf2.clearInvalidIndicators, false);
@@ -119,8 +129,16 @@ $wf2 = {
 		}
 		
 		$wf2.initNonRepetitionFunctionality();
+		
+		for (var i=0; i<$wf2.callAfterDOMContentLoaded.length; i++) {
+			$wf2.callAfterDOMContentLoaded[i]();
+		}
 	},
 
+	
+	
+
+
 
 	/*##############################################################################################
 	 # Section: Fetching data from external resources
@@ -432,992 +450,7 @@ $wf2 = {
 		}
 	},
 
-	/*##############################################################################################
-	 # Section: Repetition Model
-	 ##############################################################################################*/
-
-	//## REPETITION TEMPLATE #############################################################
-	repetitionTemplates:[],
-	constructRepetitionTemplate : function(){
-		if(this.wf2Initialized)
-			return;
-		this.wf2Initialized = true; //SAFARI needs this to be here for some reason...
-		
-		this.style.display = 'none'; //This is also specified via a stylesheet
-		this.repetitionType = RepetitionElement.REPETITION_TEMPLATE;
-		if(!this.repetitionIndex)
-			this.repetitionIndex = 0;
-		this.repetitionTemplate = null; //IMPLEMENT GETTER
-		if(!this.repetitionBlocks)
-			this.repetitionBlocks = []; //IMPLEMENT GETTER
-		var _attr;
-		this.repeatStart = /^\d+$/.test(_attr = this.getAttribute('repeat-start')) ? parseInt(_attr) : 1;
-		this.repeatMin   = /^\d+$/.test(_attr = this.getAttribute('repeat-min'))   ? parseInt(_attr) : 0;
-		this.repeatMax   = /^\d+$/.test(_attr = this.getAttribute('repeat-max'))   ? parseInt(_attr) : Number.MAX_VALUE; //Infinity;
-		
-		if(!this.addRepetitionBlock) this.addRepetitionBlock = function(refNode, index){
-			return $wf2.addRepetitionBlock.apply(this, [refNode, index]); //wrapper to save memory?
-		};
-		if(!this.addRepetitionBlockByIndex)
-			this.addRepetitionBlockByIndex = this.addRepetitionBlock/*ByIndex*/; //one method implements both algorithms
-		
-		//Any form controls inside a repetition template are associated with their forms' templateElements 
-		//   DOM attributes, and are not present in the forms' elements DOM attributes.
-		
-		//On the HTMLFormElement, the templateElements attribute contains the list of form controls associated 
-		//   with this form that form part of repetition templates. It is defined in more detail in the section 
-		//   on the repetition model. (Image controls are part of this array, when appropriate.) The controls 
-		//   in the elements and templateElements lists must be in document order. 
-		var frm = this;
-		while(frm = frm.parentNode){
-			if(frm.nodeName.toLowerCase() == 'form')
-				break;
-		}
-		
-		var _templateElements;
-		//IMAGE???, fieldset not included
-		if(frm && (_templateElements = $wf2.getElementsByTagNames.apply(this, ['button','input','select','textarea','isindex'])).length){
-			//INCORRECT IMPLEMENTATION: this should append the new elements onto the frm.templateElements array and then sort them in document order?
-			//each time that a nesting repetition block is instantiated, the form's templateElemenents property becomes invalid
-			
-			//frm.templateElements = _templateElements;
-
-			//Controls in the templateElements attribute cannot be successful; controls inside repetition templates can never be submitted.
-			//   Therefore disable all elements in the template; however, due to the issue below, the original disabled state must be stored in the field's class attribute as "disabled"
-			//   this storing of the original disabled state will enable the elements in cloned blocks to be disabled as originally coded in the template
-			//ISSUE: inputs retain disabled (but not defaultDisabled) attribue after returning to page from back button or reload
-			//   see http://weblogs.mozillazine.org/gerv/archives/2006/10/firefox_reload_behaviour.html
-			// As a workaround... this implementation requires that authors, in addition to supplying a DISABLED attribute (for Opera), to include a class name "disabled"
-			for(var el, i = 0; el = _templateElements[i]; i++)
-				el.disabled = true;
-			
-			//IMPLEMENTATION DEFICIENCY: unable to remove frm.templateElements from frm.elements
-		}
-		
-		//Repetition blocks without a repeat-template attribute are associated with their first following sibling 
-		//   that is a repetition template, if there is one.
-		var attr,sibling = this.parentNode.firstChild;
-		while(sibling && sibling != this){
-			if(sibling.nodeType == 1 && (attr = sibling.getAttributeNode('repeat')) && /^-?\d+$/.test(attr.value) && !sibling.getAttribute('repeat-template')){
-			//if(sibling.repetitionType == RepetitionElement.REPETITION_BLOCK && !sibling.getAttribute('repeat-template')){
-			//console.info(sibling)
-				sibling.repetitionTemplate = this;
-				sibling.setAttribute('repeat-template', this.id);
-				this.repetitionBlocks.push(sibling);
-			}
-			sibling = sibling.nextSibling;
-		}
-		//while(sibling = sibling.previousSibling){
-		//	if(sibling.repetitionType == RepetitionElement.REPETITION_BLOCK && !sibling.getAttribute('repeat-template')){
-		//		sibling.repetitionTemplate = this;
-		//		sibling.setAttribute('repeat-template', this.id);
-		//		this.repetitionBlocks.unshift(sibling);
-		//	}
-		//}
-	
-		//the UA must invoke the template's replication behaviour as many times as the repeat-start attribute 
-		//   on the same element specifies (just once, if the attribute is missing or has an invalid value). 
-		//   Then, while the number of repetition blocks associated with the repetition template is less than 
-		//   the template's repeat-min attribute, the template's replication behaviour must be further invoked. 
-		//   (Invoking the template's replication behaviour means calling its addRepetitionBlock() method).
-		//for(var i = 0; i < Math.max(this.repeatStart, this.repeatMin); i++)
-		for(var i = 0; (i < this.repeatStart || this.repetitionBlocks.length < this.repeatMin); i++)
-			this.addRepetitionBlock();
-		
-		$wf2.repetitionTemplates.push(this);
-		this.wf2Initialized = true;
-	},
-	
-	initRepetitionTemplates : function(parentNode){
-		//UAs must iterate through every node in the document, depth first, looking for templates so that their 
-		//   initial repetition blocks can be created. 
-		//var repetitionTemplates = cssQuery("*[repeat=template]", parentNode);
-		var repetitionTemplates = $wf2.getElementsByTagNamesAndAttribute.apply((parentNode || document.documentElement), [['*'], 'repeat', 'template']);
-		for(var i = 0, rt; i < repetitionTemplates.length; i++)
-			$wf2.constructRepetitionTemplate.apply(repetitionTemplates[i]);
-	},
-
-
-	//## REPETITION BLOCK  #############################################################
-	constructRepetitionBlock : function(){
-		if(this.wf2Initialized)
-			return;
-			
-		this.style.display = ''; //This should preferrably be specified via a stylesheet
-		this.repetitionType = RepetitionElement.REPETITION_BLOCK;
-		var _attr;
-		this.repetitionIndex = /^\d+$/.test(_attr = this.getAttribute('repeat')) ? parseInt(_attr) : 0;
-		this.repetitionBlocks = null;
-		
-		//find this block's repetition template
-		this.repetitionTemplate = null; //IMPLEMENT GETTER
-		var node;
-		
-		if((node = document.getElementById(this.getAttribute('repeat-template'))) && 
-		   node.getAttribute('repeat') == 'template')
-		{
-			this.repetitionTemplate = node;
-		}
-		else {
-			node = this;
-			while(node = node.nextSibling){
-				if(node.nodeType == 1 && node.getAttribute('repeat') == 'template'){
-					this.repetitionTemplate = node;
-					break;
-				}
-			}
-		}
-		
-		if(!this.removeRepetitionBlock) this.removeRepetitionBlock = function(){ 
-			return $wf2.removeRepetitionBlock.apply(this); //wrapper to save memory
-		};
-		if(!this.moveRepetitionBlock) this.moveRepetitionBlock = function(distance){ 
-			return $wf2.moveRepetitionBlock.apply(this, [distance]); //wrapper to save memory
-		};
-		this.wf2Initialized = true;
-	},
-
-	initRepetitionBlocks : function(parentNode){
-		//var repetitionBlocks = cssQuery('*[repeat]:not([repeat="template"])', parentNode); //:not([repeat="template"])
-		var repetitionBlocks = $wf2.getElementsByTagNamesAndAttribute.apply((parentNode || document.documentElement), [['*'], 'repeat', 'template', true]);
-		for(var i = 0; i < repetitionBlocks.length; i++)
-			$wf2.constructRepetitionBlock.apply(repetitionBlocks[i]);
-	},
-	
-	
-	//## Repetition buttons #############################################################
-	repetitionButtonDefaultLabels : {
-		'add' : 'Add',
-		'remove' : 'Remove',
-		'move-up' : 'Move-up',
-		'move-down' : 'Move-down'
-	},
-	
-	constructRepetitionButton : function(btnType){
-		if(this.wf2Initialized)
-			return;
-		this.htmlTemplate = $wf2.getHtmlTemplate(this); //IMPLEMENT GETTER
-		if(!this.firstChild)
-			this.appendChild(document.createTextNode($wf2.repetitionButtonDefaultLabels[btnType]));
-		
-		//user agents must automatically disable remove, move-up, and move-down buttons when they are not in a repetition 
-		//   block. [NOT IMPLEMENTED:] This automatic disabling does not affect the DOM disabled  attribute. It is an intrinsic property of these buttons.
-		if(btnType != 'add')
-			this.disabled = !$wf2.getRepetitionBlock(this);
-		//user agents must automatically disable add buttons (irrespective of the value of the disabled 
-		//   DOM attribute [NOT IMPLEMENTED]) when the buttons are not in a repetition block that has an 
-		//   associated template and their template attribute is either not specified or does not have 
-		//   an ID that points to a repetition template...
-		else {
-			var rb;		
-			this.disabled = !(((rb = $wf2.getRepetitionBlock(this)) && rb.repetitionTemplate)
-								||
-								this.htmlTemplate
-							 );
-		}
 
-		if(this.addEventListener)
-			this.addEventListener('click', $wf2.clickRepetitionButton, false);
-		else if(this.attachEvent)
-			this.attachEvent('onclick', $wf2.clickRepetitionButton);
-		else this.onclick = $wf2.clickRepetitionButton;
-		
-		this.wf2Initialized = true;
-	},
-
-	initRepetitionButtons : function(btnType, parent){
-		var i;
-		if(!parent)
-			parent = document.documentElement;
-
-		//change INPUTs to BUTTONs
-		var inpts = $wf2.getElementsByTagNamesAndAttribute.apply(parent, [['input'], 'type', btnType]);
-		for(i = 0; i < inpts.length; i++){
-			var btn = document.createElement('button');
-			for(var j = 0, attr; attr = inpts[i].attributes[j]; j++)
-				btn.setAttribute(attr.nodeName, inpts[i].getAttribute(attr.nodeName)); //MSIE returns correct value with getAttribute but not nodeValue
-			inpts[i].parentNode.replaceChild(btn, inpts[i]);
-			btn = null;
-		}
-
-		//construct all buttons
-		var btns = $wf2.getElementsByTagNamesAndAttribute.apply(parent, [['button'], 'type', btnType]);
-		for(var i = 0; i < btns.length; i++)
-			$wf2.constructRepetitionButton.apply(btns[i], [btnType]);
-	},
-
-	clickRepetitionButton : function(e){
-		if(e && e.preventDefault)
-			e.preventDefault(); //Keep default submission behavior from executing
-
-		//If the event is canceled (btn.returnValue === false, set within onclick handler), then the default action will not occur.
-		var btn;
-		if(e && e.target)
-			btn = e.target;
-		else if(window.event)
-			btn = event.srcElement;
-		else if(this.nodeName.toLowerCase() == 'button')
-			btn = this;
-		var btnType = String(btn.getAttribute('type')).toLowerCase();
-		
-		//Prevent the onclick handler from firing afterwards (would fire after movement action)
-		//  ISSUE: This only works in Firefox
-		if(btn.onclick){
-			btn._onclick = btn.onclick;
-			btn.removeAttribute('onclick');
-			btn.onclick = null; 
-		}
-
-		//Terminate if an onclick handler was called beforehand and returned a false value
-		//   passed via the button's returnValue property. Handlers defined by HTML attributes
-		//   are called before those assigned by onclick DOM properties.
-		if(btn.returnValue !== undefined && !btn.returnValue){
-			btn.returnValue = undefined;
-			return false;
-		}
-		
-		//Ensure that a user-supplied onclick handler is fired before the repetition behavior is executed
-		//  and terminate if this onclick handler returns a false value
-		//  Note that handlers defined in onclick HTML attributes are executed before clickRepetitionButton
-		if(btn._onclick && btn.returnValue === undefined){ //  && !btn.getAttributeNode("onclick") //&& btn.hasAttribute && !btn.hasAttribute("onclick") //NOTE: MSIE fires this afterwards???			btn.returnValue = btn._onclick(e);
-			btn.returnValue = btn._onclick(e);
-			if(btn.returnValue !== undefined && !btn.returnValue){
-				btn.returnValue = undefined;
-				return false;
-			}
-		}
-		btn.returnValue = undefined;
-		
-		//ISSUE: How do we ensure that the MSIE and DOM Level 2 Event handlers are executed beforehand?
-		
-		var block;
-		if(btnType != 'add'){
-			block = $wf2.getRepetitionBlock(btn);
-			
-			//user agents must automatically disable remove, move-up, and move-down buttons when they are not in a repetition 
-			//   block. [NOT IMPLEMENTED:] This automatic disabling does not affect the DOM disabled  attribute. It is an intrinsic property of these buttons.
-			this.disabled = !block;
-			
-			if(block){
-				if(btnType.indexOf('move') === 0){
-					block._clickedMoveBtn = btn;
-					block.moveRepetitionBlock(btnType == 'move-up' ? -1 : 1);
-				}
-				else if(btnType == 'remove'){
-					block.removeRepetitionBlock();
-				}
-			}
-		}
-		else {
-			var rt;
-			//If an add button with a template attribute is activated, and its template attribute gives the ID 
-			//   of an element in the document that is a repetition template as defined above, then that 
-			//   template's replication behaviour is invoked. (Specifically, in scripting-aware environments, 
-			//   the template's addRepetitionBlock() method is called with a null argument.) In the case of 
-			//   duplicate IDs, the behaviour should be the same as with getElementById().
-			if(btn.htmlTemplate)
-				rt = btn.htmlTemplate;
-			else {
-			//If an add button without a template attribute is activated, and it has an ancestor that is a 
-			//   repetition block that is not an orphan repetition block, then the repetition template associated 
-			//   with that repetition block has its template replication behaviour invoked with the respective 
-			//   repetition block as its argument. (Specifically, in scripting-aware environments, the template's 
-			//   addRepetitionBlock() method is called with a reference to the DOM Element node that represents 
-			//   the repetition block.)
-				block = $wf2.getRepetitionBlock(btn);
-				if(block && block.repetitionTemplate)
-					rt = block.repetitionTemplate;
-			}
-			if(rt)
-				rt.addRepetitionBlock();
-			else
-				btn.disabled = true; //NOTE: THIS IS NOT A VALID IMPLEMENTATION
-		}
-		return false;
-	},
-	
-	//## AddRepetitionBlock algorithm #############################################################
-	
-	//Element addRepetitionBlock(in Node refNode);
-	addRepetitionBlock : function(refNode, index){ //addRepetitionBlockByIndex functionalty enabled if @index defined
-		//if(refNode && !refNode.nodeType)
-		//	throw Error("Exception: WRONG_ARGUMENTS_ERR");
-
-		//if(this.repetitionType == RepetitionElement.REPETITION_TEMPLATE)
-		if(this.getAttribute('repeat') != 'template')
-			throw $wf2.DOMException(9); //NOT_SUPPORTED_ERR
-
-		//if addRepetitionBlock called before repetition constructors called (by pre-filling forms)
-		if(!this.repetitionBlocks)
-			this.repetitionBlocks = [];
-		if(!this.repetitionIndex)
-			this.repetitionIndex = 0;
-		if(!this.repeatMin)
-			this.repeatMin = 0;
-		if(!this.repeatMax)
-			this.repeatMax = Number.MAX_VALUE;
-		if(!this.repeatStart)
-			this.repeatStart = 1;
-
-		//1. If the template has no parent node or its parent node is not an element, then the method must abort 
-		//   the steps and do nothing. 
-		if(this.parentNode == null)
-			return null;
-			
-		//[furthermore, if this template is the child of another template (not the child of an instance, a block) return false]
-		var node = this;
-		while(node = node.parentNode){
-			//if(node.repetitionType == RepetitionElement.REPETITION_TEMPLATE)
-			if(node.nodeType == 1 && node.getAttribute('repeat') == 'template')
-				return false;
-		}
-		
-		//2. The template examines its preceding siblings, up to the start of the parent element. For each sibling 
-		//   that is a repetition block whose associated template is this template, if the repetition block's index 
-		//   is greater than or equal to the template's index, then the template's index is increased to the repetition 
-		//   block's index plus one. The total number of repetition blocks associated with this template that were 
-		//   found is used in the next step.
-		//QUESTION: Why not just use this.repetitionBlocks.length????????????
-		var sibling = this.previousSibling;
-		var currentBlockCount = 0;
-		while(sibling != null){
-			if(sibling.nodeType == 1){
-				var repeatAttr,repeatTemplateAttr;
-				repeat = parseInt(sibling.getAttribute('repeat'));
-				repeatTemplateAttr = sibling.getAttributeNode('repeat-template');
-				
-				//if(sibling.repetitionType == RepetitionElement.REPETITION_BLOCK && sibling.repetitionTemplate == this)
-				if(!isNaN(repeat) && (!repeatTemplateAttr || repeatTemplateAttr.value == this.id))
-				{
-					//Old Note: sibling.getAttribute('repeat') is used instead of sibling.repetitionIndex because appearantly
-					//      the sibling is not yet bound to the document and so the getters are not available
-					//this.repetitionIndex = Math.max(this.repetitionIndex, parseInt(sibling.getAttribute('repeat'))+1);
-					this.repetitionIndex = Math.max(this.repetitionIndex, repeat+1);
-					currentBlockCount++;
-				}
-			}
-			sibling = sibling.previousSibling;
-		}
-		
-		//3. If the repetition template has a repeat-max attribute and that attribute's value is less than or equal 
-		//   to the number of repetition blocks associated with this template that were found in the previous step, 
-		//   the UA must stop at this step, returning a null value.
-		if(this.repeatMax <= currentBlockCount)
-			return null;
-			
-		//4. If this algorithm was invoked via the addRepetitionBlockByIndex()  method, and the value of the method's 
-		//   index argument is greater than the template's index, then the template's index is set to the value of the 
-		//   method's index argument.
-		if(index !== undefined && index > this.repetitionIndex)
-			this.repetitionIndex = index;
-
-		//(the following steps are out of order to facilitate a custom cloneNode to cope for MSIE and Gecko issues)
-		
-		//9. If the new repetition block has an ID attribute (that is, an attribute specifying an ID, regardless 
-		//   of the attribute's namespace or name), then that attribute's value is used as the template name in 
-		//   the following steps. Otherwise, the template has no name. (If there is more than one ID attribute, 
-		//   the "first" one in terms of node order is used. [DOM3CORE]) 
-		//   [Since this step was moved here, it uses 'this' and not 'block', which hasn't been created yet]
-		//var IDAttr = block.getAttributeNode('id') ? block.getAttributeNode('id') : block.getAttributeNode('name'); //DETECT ID TYPE For others?
-		var IDAttrName = this.getAttribute('id') ? 'id' : this.getAttribute('name') ? 'name' : ''; //NOTE: hasAttribute not implemented in MSIE
-		var IDAttrValue = this.getAttribute(IDAttrName);
-
-		//5. A clone of the template is made. The resulting element is the new repetition block element.
-		//   [Note that the DOM cloneNode method is not invoked in this implementation due to MSIE 
-		//   errors, such as not being able to modify the name attribute of an existing node and strange Gecko behavior
-		//   regarding the inconsistant correspondence of an input node's value attribute and value property.
-		//   Instead of invoking the native cloneNode method, each element is copied manually when it is iterated over.]
-		//	 [Note: step 11 of the the specification's algorithm has been merged into step 5. See note at step 11 below]
-		//(11). If the template has a name and it is not being ignored (see the previous two steps), then, for every 
-		//      attribute on the new element, and for every attribute in every descendant of the new element: if the 
-		//      attribute starts with a zero-width non-breaking space character (U+FEFF) then that character is 
-		//      removed from the attribute; otherwise, any occurrences of a string consisting of an opening square 
-		//      bracket (U+005B, "[") or a modifier letter half triangular colon (U+02D1), the template's name, 
-		//      and a closing square bracket (U+005D, "]") or a middle dot (U+00B7), are replaced by the new 
-		//      repetition block's index. This is performed regardless of the types, names, or namespaces of attributes, 
-		//      and is done to all descendants, even those inside nested forms, nested repetition templates, and so forth.
-		var block;
-		
-		//(10). If the template has a name (see the previous step), and that name contains either an opening square 
-		//      bracket (U+005B, "[") a modifier letter half triangular colon (U+02D1), a closing square bracket 
-		//      (U+005D, "]") or a middle dot (U+00B7), then the template's name is ignored for the purposes of 
-		//      [this] step.
-		var replaceValue = this.repetitionIndex;
-		var reTemplateName, processAttr;
-		if(IDAttrValue && !/\u005B|\u02D1|\u005D|\u00B7/.test(IDAttrValue)){ //VALID LOGIC?
-			reTemplateName = new RegExp("(\\[|\u02D1)" + IDAttrValue + "(\\]|\u00B7)", 'g'); //new RegExp('(\\u005B|\\u02D1)' + IDAttrValue + '(\\u005D|\\u00B7)', 'g');
-			processAttr = function(attrVal){ //Function that processes an attribute value as defined in step 11
-				if(!attrVal) 
-					return attrVal;
-				attrVal = attrVal.toString();
-				if(attrVal.indexOf("\uFEFF") === 0)
-					return attrVal.replace(/^\uFEFF/, '');
-				return attrVal.replace(reTemplateName, replaceValue);
-			};
-		}
-		block = $wf2.cloneNode(this, processAttr);
-		block.wf2Initialized = false;
-		reTemplateName = null;
-		
-		//6. If this algorithm was invoked via the addRepetitionBlockByIndex()  method, the new repetition block 
-		//   element's index is set to the method's index argument. Otherwise, the new repetition block element's 
-		//   index is set to the template's index. [Note: if called by addRepetitionBlockByIndex() then the 
-		//   template's repetitionIndex has already been set to the index argument. Redundant algorithm step.]
-		//block.repetitionIndex = this.repetitionIndex; //this is set in the constructor for the repetitionBlock
-		//7. If the new repetition block element is in the http://www.w3.org/1999/xhtml namespace, then the 
-		//   repeat attribute in no namespace on the cloned element has its value changed to the new block's 
-		//   index. Otherwise, the repeat attribute in the http://www.w3.org/1999/xhtml namespace has its value 
-		//   changed to the new block's index.
-		//if(block.namespaceURI == 'http://www.w3.org/1999/xhtml')
-			block.setAttribute('repeat', this.repetitionIndex); //when inserted into DOM, constructor sets block.repetitionIndex
-		//else
-		//	block.setAttributeNS('http://www.w3.org/1999/xhtml', 'repeat', this.repetitionIndex);
-		
-		//8. If the new repetition block element is in the http://www.w3.org/1999/xhtml namespace, then any 
-		//   repeat-min, repeat-max, or repeat-start attributes in no namespace are removed from the element. 
-		//   Otherwise, any repeat-min, repeat-max, or repeat-start attributes in the http://www.w3.org/1999/xhtml 
-		//   namespace are removed instead.
-
-		//if(block.namespaceURI == 'http://www.w3.org/1999/xhtml'){
-			block.removeAttribute('repeat-min');
-			block.removeAttribute('repeat-max');
-			block.removeAttribute('repeat-start');
-		//}
-		//else {
-		//	block.removeAttributeNS('http://www.w3.org/1999/xhtml', 'repeat-min');
-		//	block.removeAttributeNS('http://www.w3.org/1999/xhtml', 'repeat-max');
-		//	block.removeAttributeNS('http://www.w3.org/1999/xhtml', 'repeat-start');
-		//}
-		
-		//(steps 9 and 10 moved to before step 5 (operates on this repetition template, and not on cloned block))
-
-
-		//11. (Note: the algorithm below which most closely follows the algorithm as described in the specification,
-		//    this has been merged into the cloning of the template in step 5. This has been done because of MSIE 
-		//    errors, such as not being able to modify the name attribute of an existing node and strange Gecko behavior
-		//    regarding the inconsistant correspondence of an input node's value attribute and value property.)
-		//if(IDAttrValue && !ignoreName){
-		//	var reTemplateName = new RegExp('(?:\\u005B|\\u02D1)' + IDAttrValue + '(?:\\u005D|\\u00B7)', 'g');
-		//	function processAttrs(node){
-		//		var i,attr;
-		//		for(i = 0; node.attributes && i < node.attributes.length; i++){
-		//			if(!(attr = node.attributes[i]).nodeValue)
-		//				continue;
-		//			
-		//			if(String(attr.nodeValue).indexOf("\uFEFF") === 0)
-		//				attr.nodeValue = attr.nodeValue.replace(/^\uFEFF/, '');
-		//				
-		//			else if(reTemplateName.test(attr.nodeValue))
-		//				attr.nodeValue = attr.nodeValue.replace(reTemplateName, block.getAttribute('repeat'));
-		//		}
-		//		for(i = 0; i < node.childNodes.length; i++)
-		//			processAttrs(node.childNodes[i]);
-		//	}
-		//	processAttrs(block);
-		//}
-
-			
-		//12. If the template has a name (see the earlier steps): If the new repetition block element is in the 
-		//    http://www.w3.org/1999/xhtml namespace, then the repeat-template attribute in no namespace on the 
-		//    cloned element has its value set to the template's name. Otherwise, the repeat-template attribute 
-		//    in the http://www.w3.org/1999/xhtml namespace has its value set to the template's name. (This 
-		//    happens even if the name was ignored for the purposes of the previous step.)
-		if(IDAttrName){
-			//if(block.namespaceURI == "http://www.w3.org/1999/xhtml")
-				block.setAttribute('repeat-template', IDAttrValue); //block.setAttributeNS(null, 'repeat-template', IDAttr.nodeValue);
-			//else 
-			//	block.setAttributeNS('http://www.w3.org/1999/xhtml', 'repeat-template', IDAttr.nodeValue);
-			
-			
-			//13. The attribute from which the template's name was derived, if any, and even if it was ignored, is 
-			//    removed from the new repetition block element. (See the previous four steps.)
-			block.removeAttribute(IDAttrName);
-		}
-
-		//14. If the first argument to the method was null, then the template once again crawls through its 
-		//    previous siblings, this time stopping at the first node (possibly the template itself) whose 
-		//    previous sibling is a repetition block (regardless of what that block's template is) or the first 
-		//    node that has no previous sibling, whichever comes first. The new element is the inserted into the 
-		//    parent of the template, immediately before that node. Mutation events are fired if appropriate.
-		if(!refNode){
-			refNode = this;
-			while(refNode.previousSibling && refNode.previousSibling.repetitionType != RepetitionElement.REPETITION_BLOCK)
-				refNode = refNode.previousSibling;
-			this.parentNode.insertBefore(block, refNode);
-			this.repetitionBlocks.push(block);
-		}
-		//15. Otherwise, the new element is inserted into the parent of the node that was passed to the method 
-		//    as the first argument, immediately after that node (before the node's following sibling, if any). 
-		//    Mutation events are fired if appropriate.
-		else {
-			refNode.parentNode.insertBefore(block, refNode.nextSibling);
-			this.repetitionBlocks.push(block);
-			if($wf2.sortNodes)
-				this.repetitionBlocks.sort($wf2.sortNodes);
-		}
-		
-		//16. The template's index is increased by one. 
-		this.repetitionIndex++;
-		
-		//[apply constructors to the new repetition block, and to the new remove buttons, add buttons, etc]
-		$wf2.constructRepetitionBlock.apply(block);
-		$wf2.initRepetitionTemplates(block);
-		
-		$wf2.initRepetitionButtons('add', block);
-		$wf2.initRepetitionButtons('remove', block);
-		$wf2.initRepetitionButtons('move-up', block);
-		$wf2.initRepetitionButtons('move-down', block);
-		
-		//In addition, user agents must automatically disable add buttons (irrespective of the value of the 
-		//   disabled DOM attribute) when the buttons are not in a repetition block that has an associated 
-		//   template and their template attribute is either not specified or does not have an ID that points 
-		//   to a repetition template, and, when the repetition template's repeat-max attribute is less than 
-		//   or equal to the number of repetition blocks that are associated with that template and that have 
-		//   the same parent. This automatic disabling does not affect the DOM disabled attribute. It is an 
-		//   intrinsic property of these buttons.
-		if($wf2.isInitialized){ //if buttons not yet initialized, will initially be called by _init_document
-			$wf2.updateAddButtons(this);
-			$wf2.updateMoveButtons(this.parentNode);
-		}
-		
-		//Setup block with the other WF2 behavior
-		$wf2.initNonRepetitionFunctionality(block);
-		//var els = $wf2.getElementsByTagNamesAndAttribute.apply(block, [['*'], "autofocus"]); //ISSUE: Any form control (except hidden and output controls) can have an autofocus attribute specified. //var elName = els[i].nodeName.toLowerCase(); if(elName == 'output' || (elName == 'input' && els[i].type == 'hidden'))
-		//for(var i = 0; i < els.length; i++)
-		//	$wf2.initAutofocusElement(els[i]);
-
-		//17. An added event with no namespace, which bubbles but is not cancelable and has no default action, 
-		//    must be fired on the repetition template using the RepetitionEvent interface, with the repetition 
-		//    block's DOM node as the context information in the element  attribute.
-		var addEvt;
-		try {
-			if(document.createEvent)
-				addEvt = document.createEvent('UIEvents'); //document.createEvent("RepetitionEvent")
-			else if(document.createEventObject)
-				addEvt = document.createEventObject();
-			RepetitionEvent._upgradeEvent.apply(addEvt);
-			addEvt.initRepetitionEvent('added', true /*canBubble*/, false /*cancelable*/, block);
-			if(this.dispatchEvent)
-				this.dispatchEvent(addEvt);
-			else if(this.fireEvent){
-				//console.warn("fireEvent('onadd') for MSIE is not yet working");
-				//this.fireEvent('onadded', addEvt);
-			}
-		}
-		catch(err){
-			addEvt = new Object();
-			RepetitionEvent._upgradeEvent.apply(addEvt);
-			addEvt.initRepetitionEvent('added', true /*canBubble*/, false /*cancelable*/, block);
-		}
-
-		//Add support for event handler set with HTML attribute 
-		var handlerAttr;
-		if((handlerAttr = this.getAttribute('onadded')) && (!this.onadded || typeof this.onadded != 'function')){  //in MSIE, attribute == property
-			this.onadded = new Function('event', handlerAttr);
-		}
-		//Deprecated
-		else if((handlerAttr = this.getAttribute('onadd')) && (!this.onadd || typeof this.onadd != 'function')){
-			this.onadd = new Function('event', handlerAttr);
-		}
-
-		try {
-			//Dispatch events for the old event model (extension to spec)
-			if(this.onadded){
-				//this.onadded(addEvt); 
-				this.onadded.apply(this, [addEvt]); //for some reason, exceptions cannot be caught if using the method above in MSIE
-			}
-			else if(this.onadd){ //deprecated
-				//this.onadd(addEvt);
-				this.onadd.apply(this, [addEvt]); 
-			}
-		}
-		catch(err){
-			//throw exception within setTimeout so that the current execution will not be aborted
-			setTimeout(function(){
-				throw err;
-			}, 0); //using 0 milliseconds done at <http://novemberborn.net/javascript/threading-quick-tip>
-		}
-
-		//18. The return value is the newly cloned element.
-		return block;
-	},
-	//Element addRepetitionBlockByIndex(in Node refNode, in long index);
-	addRepetitionBlockByIndex : function(refNode, index){
-		$wf2.addRepetitionBlock.apply(this, [refNode, index])
-	},
-	
-	//## RemoveRepetitionBlock algorithm #############################################################
-	
-	//void removeRepetitionBlock();
-	removeRepetitionBlock : function(){
-		if(this.repetitionType != RepetitionElement.REPETITION_BLOCK)
-			throw $wf2.DOMException(9); //NOT_SUPPORTED_ERR
-
-		//1. The node is removed from its parent, if it has one. Mutation events are fired if appropriate. 
-		//   (This occurs even if the repetition block is an orphan repetition block.)
-		var parentNode = this.parentNode; //save for updateMoveButtons
-		var block = parentNode.removeChild(this);
-		$wf2.updateMoveButtons(parentNode);
-		
-		//The following loop used to appear within step #3 below; 
-		//  this caused problems because the program state was incorrect when onremoved was called (repetitionBlocks was not modified)
-		if(this.repetitionTemplate != null){
-			for(var i = 0; i < this.repetitionTemplate.repetitionBlocks.length; i++){
-				if(this.repetitionTemplate.repetitionBlocks[i] == this){
-					this.repetitionTemplate.repetitionBlocks.splice(i,1);
-					break;
-				}
-			}
-		}
-
-		//2. If the repetition block is not an orphan, a removed event with no namespace, which bubbles but 
-		//   is not cancelable and has no default action, must be fired on the element's repetition template, 
-		//   using the RepetitionEvent interface, with the repetition block's DOM node as the context information 
-		//   in the element attribute.
-		if(this.repetitionTemplate != null){
-			var removeEvt;
-			try {
-				if(document.createEvent)
-					removeEvt = document.createEvent('UIEvents'); //document.createEvent("RepetitionEvent")
-				else if(document.createEventObject)
-					removeEvt = document.createEventObject();
-				RepetitionEvent._upgradeEvent.apply(removeEvt);
-				removeEvt.initRepetitionEvent('removed', true /*canBubble*/, false /*cancelable*/, this);
-				if(this.repetitionTemplate.dispatchEvent)
-					this.repetitionTemplate.dispatchEvent(removeEvt);
-				else if(this.repetitionTemplate.fireEvent){
-					//console.warn("fireEvent('onremoved') for MSIE is not yet working");
-					//this.repetitionTemplate.fireEvent('onremoved', removeEvt);
-				}
-			}
-			catch(err){
-				removeEvt = new Object();
-				RepetitionEvent._upgradeEvent.apply(removeEvt);
-				removeEvt.initRepetitionEvent('removed', true /*canBubble*/, false /*cancelable*/, this);
-			}
-			
-			//Add support for event handler set with HTML attribute
-			var handlerAttr;
-			if((handlerAttr = this.repetitionTemplate.getAttribute('onremoved')) &&
-				    (!this.repetitionTemplate.onremoved || typeof this.repetitionTemplate.onremoved != 'function')) //in MSIE, attribute == property
-			{  
-				this.repetitionTemplate.onremoved = new Function('event', handlerAttr);
-			}
-			//Deprecated
-			else if((handlerAttr = this.repetitionTemplate.getAttribute('onremove')) &&
-					 (!this.repetitionTemplate.onremove || typeof this.repetitionTemplate.onremove != 'function'))
-			{
-				this.repetitionTemplate.onremove = new Function('event', handlerAttr);
-			}
-
-			try {
-				//Dispatch events for the old event model (extension to spec)
-				if(this.repetitionTemplate.onremoved){
-					//this.repetitionTemplate.onremoved(removeEvt);	
-					this.repetitionTemplate.onremoved.apply(this, [removeEvt]); //for some reason, exceptions cannot be caught if using the method above in MSIE
-				}
-				else if(this.repetitionTemplate.onremove){ //deprecated
-					//this.repetitionTemplate.onremove(removeEvt);
-					this.repetitionTemplate.onremove.apply(this, [removeEvt]); 
-				}
-			}
-			catch(err){
-				//throw exception within setTimeout so that the current execution will not be aborted
-				setTimeout(function(){
-					throw err;
-				}, 0);
-			}
-		}
-
-		//3. If the repetition block is not an orphan, then while the remaining number of repetition blocks 
-		//   associated with the original element's repetition template and with the same parent as the template 
-		//   is less than the template's repeat-min attribute and less than its repeat-max attribute, the 
-		//   template's replication behaviour is invoked (specifically, its addRepetitionBlock() method is called). 
-		if(this.repetitionTemplate != null){
-//			//BUG: The following needs to be moved before the call to onremoved
-//			var t = this.repetitionTemplate;
-//			for(var i = 0; i < t.repetitionBlocks.length; i++){
-//				if(t.repetitionBlocks[i] == this){
-//					t.repetitionBlocks.splice(i,1);
-//					break;
-//				}
-//			}
-			if(this.repetitionTemplate.repetitionBlocks.length < this.repetitionTemplate.repeatMin 
-			     && this.repetitionTemplate.repetitionBlocks.length < this.repetitionTemplate.repeatMax)
-			{
-				this.repetitionTemplate.addRepetitionBlock();
-			}
-
-			//enable add buttons
-			if(this.repetitionTemplate.repetitionBlocks.length < this.repetitionTemplate.repeatMax){
-				//var addBtns = cssQuery("button[type=add]");
-				var addBtns = $wf2.getElementsByTagNamesAndAttribute.apply(document.documentElement, [['button'], 'type', 'add']);
-				for(i = 0; i < addBtns.length; i++){
-					if(addBtns[i].htmlTemplate == this.repetitionTemplate)
-						addBtns[i].disabled = false;
-				}
-			}
-		}
-	},
-
-	//## MoveRepetitionBlock algorithm #############################################################
-	 
-	//void moveRepetitionBlock(in long distance);
-	moveRepetitionBlock : function(distance){
-		if(this.repetitionType != RepetitionElement.REPETITION_BLOCK)
-			throw $wf2.DOMException(9); //NOT_SUPPORTED_ERR
-		
-		//1. If distance is 0, or if the repetition block has no parent, nothing happens and the algorithm ends here.
-		if(distance == 0 || this.parentNode == null)
-			return;
-		
-		//2. Set target, a reference to a DOM Node, to the repetition block being moved.
-		//   [Furthermore, move the reference to this block in the template's repetitionBlocks HTMLCollection to 
-		//   reflect the new position that it is being moved to.]
-		var target = this;
-		if(this.repetitionTemplate){
-			var pos = 0;
-			var rp = this.repetitionTemplate.repetitionBlocks;
-			while(pos < rp.length && rp[pos] != this)
-				pos++;
-			rp.splice(pos, 1);
-			rp.splice(distance < 0 ? Math.max(pos+distance, 0) : Math.min(pos+distance, rp.length), 0, this);
-		}
-		
-		//3. If distance is negative: while distance is not zero and target's previousSibling is defined and is 
-		//   not a repetition template, set target to this previousSibling and, if it is a repetition block, 
-		//   increase distance by one (make it less negative by one).
-		if(distance < 0){
-			while(distance != 0 && target.previousSibling && 
-			      target.previousSibling.repetitionType != RepetitionElement.REPETITION_TEMPLATE)
-			{
-				target = target.previousSibling;
-				if(target.repetitionType == RepetitionElement.REPETITION_BLOCK)
-					distance++;
-			}
-		}
-		//4. Otherwise, distance is positive: while distance  is not zero and target's nextSibling is defined 
-		//   and is not a repetition template, set target to this nextSibling and, if it is a repetition block, 
-		//   decrease distance by one. After the loop, set target to target's nextSibling (which may be null).
-		else {
-			while(distance != 0 && target.nextSibling && target.nextSibling.repetitionType != RepetitionElement.REPETITION_TEMPLATE){
-				target = target.nextSibling;
-				if(target.repetitionType == RepetitionElement.REPETITION_BLOCK)
-					distance--;
-			}
-			target = target.nextSibling;
-		}
-		
-		//5. Call the repetition block's parent node's insertBefore()  method with the newChild argument 
-		//   being the repetition block and the refChild argument being target (which may be null by this 
-		//   point). Mutation events are fired if appropriate. 
-		this.parentNode.insertBefore(this, target);
-		
-		//Keep focus on the move button which was clicked
-		if(this._clickedMoveBtn){
-			this._clickedMoveBtn.focus();
-			this._clickedMoveBtn = null;
-		}
-		
-		//In addition, user agents must automatically disable move-up buttons (irrespective of the 
-		//   value of the disabled DOM attribute) when their repetition block could not be moved any 
-		//   higher according to the algorithm above, and when the buttons are not in a repetition 
-		//   block. Similarly, user agents must automatically disable move-down buttons when their 
-		//   repetition block could not be moved any lower according to the algorithm above, and 
-		//   when the buttons are not in a repetition block. This automatic disabling does not affect 
-		//   the DOM disabled  attribute. It is an intrinsic property of these buttons.
-		$wf2.updateMoveButtons(this.parentNode);
-		
-		//6. A moved event with no namespace, which bubbles but is not cancelable and has no default action, 
-		//   must be fired on the element's repetition template (if it has one), using the RepetitionEvent 
-		//   interface, with the repetition block's DOM node as the context information in the element  attribute.
-		if(this.repetitionTemplate != null){
-			var moveEvt;
-			try {
-				if(document.createEvent)
-					moveEvt = document.createEvent('UIEvents'); //document.createEvent("RepetitionEvent")
-				else if(document.createEventObject)
-					moveEvt = document.createEventObject();
-				RepetitionEvent._upgradeEvent.apply(moveEvt);
-				moveEvt.initRepetitionEvent('moved', true /*canBubble*/, false /*cancelable*/, this);
-				if(this.repetitionTemplate.dispatchEvent)
-					this.repetitionTemplate.dispatchEvent(moveEvt);
-				else if(this.repetitionTemplate.fireEvent){
-					//console.warn("fireEvent('onmoved') for MSIE is not yet working");
-					//this.fireEvent('onmoved', moveEvt);
-				}
-			}
-			catch(err){
-				moveEvt = new Object();
-				RepetitionEvent._upgradeEvent.apply(moveEvt);
-				moveEvt.initRepetitionEvent('moved', true /*canBubble*/, false /*cancelable*/, this);
-			}
-			
-			//Add support for event handler set with HTML attribute---------------------
-			var handlerAttr;
-			if((handlerAttr = this.repetitionTemplate.getAttribute('onmoved')) &&
-				    (!this.repetitionTemplate.onmoved || typeof this.repetitionTemplate.onmoved != 'function')) //in MSIE, attribute == property
-			{  
-				this.repetitionTemplate.onmoved = new Function('event', handlerAttr);
-			}
-			//Deprecated
-			else if(handlerAttr = this.repetitionTemplate.getAttribute('onmove'))
-			{
-				if(!this.repetitionTemplate.onmove || typeof this.repetitionTemplate.onmove != 'function'){
-					this.repetitionTemplate.onmove = new Function('event', handlerAttr);
-				}
-
-				//For MSIE, onmove is already an event, and attributes are equal to properties, so attribute value can be function.
-				//  The 'event' argument must be added to the function argument list.
-				var funcMatches;
-				if(typeof handlerAttr == 'function' && (funcMatches = handlerAttr.toString().match(/^\s*function\s+anonymous\(\s*\)\s*\{((?:.|\n)+)\}\s*$/))){
-					this.repetitionTemplate.onmove = new Function('event', funcMatches[1]);
-				}
-			}
-			
-			
-//			var onmovedAttr = this.repetitionTemplate.getAttribute('onmoved') 
-//			                   || /* deprecated */ this.repetitionTemplate.getAttribute('onmove');
-			
-			//For MSIE, onmove is already an event, and attributes are equal to properties, so attribute value can be function.
-			//  The 'event' argument must be added to the function argument list.
-//			var funcMatches;
-//			if(typeof onmovedAttr == 'function' && (funcMatches = onmovedAttr.toString().match(/^\s*function\s+anonymous\(\s*\)\s*\{((?:.|\n)+)\}\s*$/))){
-//				this.repetitionTemplate.onmoved = new Function('event', funcMatches[1]);
-//			}
-			
-			//If the onmove attribute has been set but the property (method) has not
-//			if(onmovedAttr && !this.repetitionTemplate.onmoved)
-//				this.repetitionTemplate.onmoved = new Function('event', onmovedAttr);
-			
-			//This need not be done in MSIE since onmove is already an event, and attributes == properties
-			//if(onmoveAttr && typeof onmoveAttr != 'function' /* for MSIE */ && 
-			//      (!this.repetitionTemplate.onmove || typeof this.repetitionTemplate.onmove != 'function')
-			//   ){
-			//	this.repetitionTemplate.onmove = new Function('event', onmoveAttr);
-			//}
-
-			try {
-				//Dispatch events for the old event model (extension to spec)
-				if(this.repetitionTemplate.onmoved){
-					//this.repetitionTemplate.onmoved(moveEvt);
-					this.repetitionTemplate.onmoved.apply(this, [moveEvt]);
-				}
-				else if(this.repetitionTemplate.onmove){ //deprecated
-					//this.repetitionTemplate.onmove(moveEvt);
-					this.repetitionTemplate.onmove.apply(this, [moveEvt]);
-				}
-			}
-			catch(err){
-				//throw exception within setTimeout so that the current execution will not be aborted
-				setTimeout(function(){
-					throw err;
-				}, 0); //using 0 milliseconds done at <http://novemberborn.net/javascript/threading-quick-tip>
-			}
-		}
-	},
-	
-	//## Other helper functions for the repetition model behaviors ##############################
-	getRepetitionBlock : function(node){
-		while(node = node.parentNode){
-			if(node.repetitionType == RepetitionElement.REPETITION_BLOCK){
-				return node;
-			}
-		}
-		return null;
-	},
-
-	getHtmlTemplate : function(button){
-		var attr = button.getAttribute('template');
-		var node;
-		if(attr && (node = document.getElementById(attr)) && node.getAttribute('repeat') == 'template' /*node.repetitionType == RepetitionElement.REPETITION_TEMPLATE*/)
-			return node;
-		return null;
-	},
-	
-	updateAddButtons : function(rt){
-		//In addition, user agents must automatically disable add buttons (irrespective of the value of the 
-		//   disabled DOM attribute) when the buttons are not in a repetition block that has an associated 
-		//   template and their template attribute is either not specified or does not have an ID that points 
-		//   to a repetition template, and, when the repetition template's repeat-max attribute is less than 
-		//   or equal to the number of repetition blocks that are associated with that template and that have 
-		//   the same parent. This automatic disabling does not affect the DOM disabled attribute. It is an 
-		//   intrinsic property of these buttons.
-		
-		var repetitionTemplates = rt ? [rt] : $wf2.repetitionTemplates;
-		
-		//var btns = cssQuery("button[type=add]");
-		var btns = $wf2.getElementsByTagNamesAndAttribute.apply(document.documentElement, [['button'], 'type', 'add']);
-		for(var i = 0; i < btns.length; i++){
-			for(var t, j = 0; t = repetitionTemplates[j]; j++){
-				if(btns[i].htmlTemplate == t && t.repetitionBlocks.length >= t.repeatMax){
-					btns[i].disabled = true;
-				}
-			}
-		}
-	},
-
-	updateMoveButtons : function(parent){
-		//In addition, user agents must automatically disable move-up buttons (irrespective of the value of 
-		//   the disabled DOM attribute) when their repetition block could not be moved any higher according 
-		//   to the algorithm above, and when the buttons are not in a repetition block. Similarly, user agents 
-		//   must automatically disable move-down buttons when their repetition block could not be moved any 
-		//   lower according to the algorithm above, and when the buttons are not in a repetition block. This 
-		//   automatic disabling does not affect the DOM disabled  attribute. It is an intrinsic property of 
-		//   these buttons.
-		
-		var i;
-		var rbs = [];
-		
-		//update all move buttons if a repetition block's parent was not given
-		if(!parent){
-			var visitedParents = [];
-			//var rbs = cssQuery('*[repeat]:not([repeat="template"])');
-			//var rbs = $wf2.getElementsByProperty('repetitionType', RepetitionElement.REPETITION_BLOCK);
-			rbs = $wf2.getElementsByTagNamesAndAttribute.apply(document.documentElement, [['*'], 'repeat', 'template', true]);
-			for(i = 0; block = rbs[i]; i++){
-				//if(!visitedParents.some(function(i){return i == block.parentNode})){
-				if(!$wf2.arrayHasItem(visitedParents, block.parentNode)){
-					$wf2.updateMoveButtons(block.parentNode);
-					visitedParents.push(block.parentNode);
-				}
-			}
-			return;
-		}
-		
-		//get all of the repetition block siblings
-		var j,btn,block;
-		var child = parent.firstChild;
-		while(child){
-			if(child.repetitionType == RepetitionElement.REPETITION_BLOCK)
-				rbs.push(child);
-			child = child.nextSibling;
-		}
-		
-		//disable or enable movement buttons within each block
-		for(i = 0; block = rbs[i]; i++){
-			//var moveUpBtns = cssQuery("button[type=move-up]", block);
-			var moveUpBtns = $wf2.getElementsByTagNamesAndAttribute.apply(block, [['button'], 'type', 'move-up']);
-			for(j = 0; btn = moveUpBtns[j]; j++){
-				btn.disabled = 
-					//if the button is not in a repetition block
-					!(rb = $wf2.getRepetitionBlock(btn))
-					 ||
-					//when their repetition block could not be moved any lower
-					(i == 0);
-			}
-			//var moveDownBtns = cssQuery("button[type=move-down]", block);
-			var moveDownBtns = $wf2.getElementsByTagNamesAndAttribute.apply(block, [['button'], 'type', 'move-down']);
-			for(j = 0; btn = moveDownBtns[j]; j++){
-				btn.disabled = 
-					//if the button is not in a repetition block
-					!(rb = $wf2.getRepetitionBlock(btn))
-					 ||
-					//when their repetition block could not be moved any higher
-					(i == rbs.length-1);
-			}
-		}
-	},
 
 	/*#############################################################################################
 	 # Section: Extensions to the input element
@@ -1426,9 +459,10 @@ $wf2 = {
 	initNonRepetitionFunctionality : function(parent){
 		parent = (parent || document.documentElement);
 		var i,j, frm, frms = parent.getElementsByTagName('form');
-		for(i = 0; frm = frms[i]; i++){
-			if(frm.checkValidity && !$wf2.hasBadImplementation)
+		for(i = 0; frm = frms[i]; i++){
+			if(frm.checkValidity && !$wf2.hasBadImplementation && $wf2.getAttributeValue(frm, 'data-webforms2-force-js-validation') != 'true') {
 				continue;
+			}
 			frm.checkValidity = $wf2.formCheckValidity;
 			
 			if(frm.addEventListener)
@@ -1509,13 +543,31 @@ $wf2 = {
 		var formElements = $wf2.getFormElements.apply(this);
 		//for(i = 0; i < formElements.length; i++)
 		//	_elements.push(formElements[i]);
-		for(i = 0; el = formElements[i]; i++){
+		for(i = 0; el = formElements[i]; i++){ 
 			var type = (el.getAttribute('type') ? el.getAttribute('type').toLowerCase() : el.type);
-			el.willValidate = !(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !el.name || el.disabled)
+			
+			try {
+				el.willValidate = !(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !el.name || el.disabled)
+			} catch (ex) {
+				// do nothing.
+			}
 			//Then, each element in this list whose willValidate DOM attribute is true is checked for validity
 			if(el.checkValidity && el.willValidate){
-				if(!el.checkValidity())
+				if(!el.checkValidity() && el.checkValidity() != undefined) {
 					valid = false;
+					
+					/* var oninvalid = el.getAttribute('oninvalid');
+					if (oninvalid) {
+						oninvalid();
+					} */
+					
+					
+					/* we change this to only show the first error.
+					if (!$wf2.showAllErrors) {
+						break;
+					}
+					*/
+				}
 			}
 		}
 		
@@ -1528,10 +580,13 @@ $wf2 = {
 	hiliteFirstError: function () {
 		
 		if($wf2.invalidIndicators.length){ //second condition needed because modal in oninvalid handler may cause indicators to disappear before this is reached
-			$wf2.invalidIndicators[0].errorMsg.className += " wf2_firstErrorMsg";
-			
+			//$wf2.invalidIndicators[0].errorMsg.className += " wf2_firstErrorMsg";
+			$wf2.css.addClass($wf2.invalidIndicators[0].errorMsg, "wf2_firstErrorMsg");
 			//scroll to near the location where invalid control is
 			el = $wf2.invalidIndicators[0].target;
+			
+			var doScroll = (el.form.getAttribute('data-wf2-no-scroll-on-error') != 'true')
+			
 			if(el.style.display == 'none' || !el.offsetParent){
 				while(el && (el.nodeType != 1 || (el.style.display == 'none' || !el.offsetParent)))
 					el = el.previousSibling;
@@ -1542,7 +597,9 @@ $wf2 = {
 					while (cur = cur.offsetParent)
 						top += cur.offsetTop;
 				}
-				scrollTo(0, top);
+				if (doScroll) {
+					scrollTo(0, top);
+				}
 			}
 			//focus on the first invalid control and make sure error message is visible
 			else {
@@ -1554,15 +611,24 @@ $wf2 = {
 					}
 				, 10)
 				
+				
+				var elPos = $wf2.css.getAbsoluteCoords(el);
+				var maxBottom = $wf2.css.getScrollY() + $wf2.css.getWindowHeight();
+				var errorMsgHeight = $wf2.invalidIndicators[0].errorMsg.offsetHeight;
+				
+				console.log(elPos.y + errorMsgHeight, maxBottom)
 				//NOTE: We should only do this if the control's style.bottom == 0
-				scrollBy(0, $wf2.invalidIndicators[0].errorMsg.offsetHeight);
+				if (doScroll && elPos.y + errorMsgHeight > maxBottom) {
+					
+					scrollBy(0, errorMsgHeight );
+				}
 			}
 		}
 		
 	},
 	
 	controlCheckValidity : function(){
-		$wf2.controlCheckValidityOfElement(this);
+		return $wf2.controlCheckValidityOfElement(this);
 		
 	},
 	
@@ -1617,9 +683,10 @@ $wf2 = {
 			}
 		}
 		catch(err){
+			var myErr = err;
 			//throw exception within setTimeout so that the current execution will not be aborted
 			setTimeout(function(){
-				throw err;
+				throw myErr;
 			}, 0);
 		}
 
@@ -1680,17 +747,19 @@ $wf2 = {
 	getOriginalAttrNode: function (node, attrName) {
 		var r;
 		
-		var dataSetItemName = attrName + 'AttrNode';
+		/* var dataSetItemName = attrName + 'AttrNode';
 		
 		if ($wf2.getDatasetItem(node, dataSetItemName) == null) {
 			r = $wf2.copyOf(node.getAttributeNode(attrName));
-			$wf2.setDatasetItem(node, dataSetItemName, r);
+			$wf2.setDatasetItem(node, dataSetItemName, r.value);
 		} else {
 			r = $wf2.getDatasetItem(node, dataSetItemName);
 			if (r == 'null') {
 				r = null;
 			}
-		}
+		} */
+		
+		r = $wf2.copyOf(node.getAttributeNode(attrName));
 		
 		return r;
 	},
@@ -1699,26 +768,36 @@ $wf2 = {
 	updateValidityState : function(node){
 		//if(node.form && node.form[node.name] && node.form[node.name].wf2HasInvalidIndicator)
 		//	return;
+		var type = (node.getAttribute('type') ? node.getAttribute('type').toLowerCase() : node.type);
+		// for range, we need to make sure this doesn't run
+		if (type == 'range' && node.type == 'range') {
+			return;
+		}
+		
 		
 		var minAttrNode, maxAttrNode, valueAttrNode;
 		
 		minAttrNode = $wf2.getOriginalAttrNode(node, 'min');
 		maxAttrNode = $wf2.getOriginalAttrNode(node, 'max');
+		stepAttrNode = $wf2.getOriginalAttrNode(node, 'step');
 		valueAttrNode = $wf2.getOriginalAttrNode(node, 'value');
-
+		
+		
 		node.min = undefined; //wf2Min
 		node.max = undefined; //wf2Max
 		node.step = undefined; //wf2Step
 		
+		// only do this if node.validity is set, or Opera will complain.
+		if (!node.validity) {
+			node.validity = $wf2.createValidityState();
+		}
 		
-		
-		node.validity = $wf2.createValidityState();
 		node.validity.customError = !!node.validationMessage;
 		
 		//var type = node.type ? node.type.toLowerCase() : 'text';
 		//var type = (node.type ? node.getAttribute('type').toLowerCase() :
 		//                       (node.nodeName.toLowerCase() == 'input' ? 'text' : ''));
-		var type = (node.getAttribute('type') ? node.getAttribute('type').toLowerCase() : node.type);
+		
 		var isTimeRelated = (type == 'datetime' || type == 'datetime-local' || type == 'time'); //datetime, datetime-local, time
 		var isDateRelated = (type == 'date' || type == 'month' || type == 'week'); //date, month, week
 		var isNumberRelated = (type == 'number' || type == 'range'); //number, range
@@ -1748,22 +827,37 @@ $wf2 = {
 		
 		if(type == 'range'){
 			//For this type...min defaults to 0...and value defaults to the min value.
+			
 			node.min = (minAttrNode && $wf2.numberRegExp.test(minAttrNode.value)) ? Number(minAttrNode.value) : 0;
+			node.max = (maxAttrNode && $wf2.numberRegExp.test(maxAttrNode.value)) ? Number(maxAttrNode.value) : 0;
 			if((!valueAttrNode || !valueAttrNode.specified) && node.value === '' && !node.wf2ValueProvided){ //(!valueAttrNode || !valueAttrNode.specified) && 
 				node.setAttribute('value', node.min);
 				node.value = node.min;
 				node.wf2ValueProvided = true;
 			}
+			
+			return;
 		}
 		
-		node.wf2Value = node.value;
+		if ($wf2.css.isMemberOfClass(node, 'html5-hasPlaceholderText')) {
+			node.wf2Value = '';
+		} else {
+			node.wf2Value = node.value;
+		}
+		//console.log("changing:", node.value, ", " , node.wf2Value)
 
 		//valueMissing -- The control has the required attribute set but it has not been satisfied.
 		//The required attribute applies to all form controls except controls with the type hidden,
 		//   image inputs, buttons (submit, move-up, etc), and select and output elements. For
 		//   disabled or readonly controls, the attribute has no effect.
 		var type = (node.getAttribute('type') ? node.getAttribute('type').toLowerCase() : node.type);
-		node.willValidate = !(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !node.name || node.disabled);
+		
+		// do this only when node.willValidate doesn't exist or Opera will complain
+		try {
+			node.willValidate = !(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !node.name || node.disabled);
+		} catch (ex) {
+			// do nothing.
+		}
 		if(doRequiredCheck && node.willValidate){
 			//For checkboxes, the required  attribute shall only be satisfied when one or more of
 			//  the checkboxes with that name in that form are checked.
@@ -1805,13 +899,13 @@ $wf2 = {
 				//For other controls, any non-empty value shall satisfy the required condition,
 				//   including a simple whitespace character.
 				//else
-					node.validity.valueMissing = (node.value == '');
+					node.validity.valueMissing = (node.wf2Value == '');
 			}
 			//if(node.options ? node.selectedIndex == -1 : node.value === '')
 			//	node.validity.valueMissing = true;
 			//
 		}
-		if(!node.validity.valueMissing && node.value){
+		if(!node.validity.valueMissing && node.wf2Value){
 			//patternMismatch -- The value of the control with a pattern attribute doesn't match the pattern. 
 			//   If the control is empty, this flag must not be set.
 			//If the pattern attribute is present but empty, it doesn't match any value, and thus the
@@ -1828,20 +922,21 @@ $wf2 = {
 				//When the pattern is not a valid regular expression, it is ignored for the purposes of
 				//   validation, as if it wasn't specified.
 				if(rePattern)
-					node.validity.patternMismatch = !rePattern.test(node.value);
+					node.validity.patternMismatch = !rePattern.test(node.wf2Value);
 			}
 			
 			//typeMismatch -- The data entered does not match the type of the control. For example, if the UA 
 			//   allows uninterpreted arbitrary text entry for month controls, and the user has entered SEP02, 
 			//   then this flag would be set. This code is also used when the selected file in a file upload 
 			//   control does not have an appropriate MIME type. If the control is empty, this flag must not be set.
-			if(isDateRelated || isTimeRelated)
-				node.validity.typeMismatch = ((node.wf2Value = $wf2.parseISO8601(node.value, type)) == null);
-			else {
+			if(isDateRelated || isTimeRelated) {
+				//node.validity.typeMismatch = ((node.value = $wf2.parseISO8601(node.wf2Value, type)) == null);
+				//node.wf2Value = node.value;
+			} else {
 				switch(type){
 					case 'number':
 					case 'range':
-						node.validity.typeMismatch = !$wf2.numberRegExp.test(node.value);
+						node.validity.typeMismatch = !$wf2.numberRegExp.test(node.wf2Value);
 	//						if(!node.validity.typeMismatch && node.getAttribute("step") != 'any'){
 	//							if(node.step == undefined)
 	//								node.step = 1;
@@ -1855,7 +950,7 @@ $wf2 = {
 						//   subtoken everywhere except in the quoted-string subtoken. UAs could, for example, offer
 						//   e-mail addresses from the user's address book. (See below for notes on IDN.)
 						//http://www.ietf.org/rfc/rfc2822						
-						node.validity.typeMismatch = !$wf2.emailRegExp.test(node.value);
+						node.validity.typeMismatch = !$wf2.emailRegExp.test(node.wf2Value);
 						break;
 					case 'url':
 						//An IRI, as defined by [RFC3987] (the IRI token, defined in RFC 3987 section 2.2). UAs could,
@@ -1864,7 +959,7 @@ $wf2 = {
 						//   generally felt authors are more familiar with the term "URL" than the other, more technically
 						//   correct terms.
 						//http://www.ietf.org/rfc/rfc3987
-						node.validity.typeMismatch = !$wf2.urlRegExp.test(node.value);
+						node.validity.typeMismatch = !$wf2.urlRegExp.test(node.wf2Value);
 						break;
 				}
 			}
@@ -1885,6 +980,8 @@ $wf2 = {
 						if(type == 'range'){
 							//For this type...max defaults to 100
 							node.max = (maxAttrNode && $wf2.numberRegExp.test(maxAttrNode.value)) ? Number(maxAttrNode.value) : 100;
+							
+							
 							//node.min is set at the beginning of this function so that the min value can be set as the default value
 						}
 						else {
@@ -1892,9 +989,13 @@ $wf2 = {
 								node.min = Number(minAttrNode.value);
 							if(maxAttrNode && $wf2.numberRegExp.test(maxAttrNode.value))
 								node.max = Number(maxAttrNode.value);
+							if(stepAttrNode && $wf2.numberRegExp.test(stepAttrNode.value))
+								node.step = Number(stepAttrNode.value);
 						}
-						node.validity.rangeUnderflow = (node.min != undefined && Number(node.value) < node.min);
-						node.validity.rangeOverflow  = (node.max != undefined && Number(node.value) > node.max);
+						node.validity.rangeUnderflow = (node.min != undefined && Number(node.wf2Value) < node.min);
+						node.validity.rangeOverflow  = (node.max != undefined && Number(node.wf2Value) > node.max);
+						node.validity.stepMismatch = !$wf2.isValidNumber(node);
+						//console.log('first: ', node.validity.stepMismatch, ',', node.getAttribute('type'))
 					}
 					//For file types it must be a sequence of digits 0-9, treated as a base ten integer.
 					else if(type == 'file'){
@@ -1928,12 +1029,15 @@ $wf2 = {
 					}
 				}
 				//The step attribute controls the precision allowed for the date-related, time-related, and numeric types.
-				if(doCheckPrecision && !node.validity.rangeUnderflow && !node.validity.rangeOverflow){
+				
+				//Note: webforms2 as of March 6, 2012 does not support step for time related inputs.  Will revisit later.
+				if(!(isDateRelated || isTimeRelated) && doCheckPrecision && !node.validity.rangeUnderflow && !node.validity.rangeOverflow){
 					//stepMismatch -- The value is not one of the values allowed by the step attribute, and the UA will 
 					//   not be rounding the value for submission. Empty values and values that caused the typeMismatch 
 					//   flag to be set must not cause this flag to be set.
 					
 					var stepAttrNode = $wf2.getOriginalAttrNode(node, 'step'); //node.getAttributeNode('step');
+					
 					if(!stepAttrNode){
 						//The step attribute [for types datetime, datetime-local, and time] ... defaulting to 60 (one minute).
 						//For time controls, the value of the step attribute is in seconds, although it may be a fractional
@@ -1975,9 +1079,9 @@ $wf2 = {
 						//   and for time controls is 00:00.
 						var _step = node.step;
 						if(type == 'month' && node.wf2StepDatum && node.wf2StepDatum.getUTCFullYear){
-							var month1 = node.wf2StepDatum.getUTCFullYear()*12 + node.wf2StepDatum.getUTCMonth();
-							var month2 = node.wf2Value.getUTCFullYear()*12 + node.wf2Value.getUTCMonth();
-							node.validity.stepMismatch = (month2 - month1)%_step != 0;
+							//var month1 = node.wf2StepDatum.getUTCFullYear()*12 + node.wf2StepDatum.getUTCMonth();
+							//var month2 = node.wf2Value.getUTCFullYear()*12 + node.wf2Value.getUTCMonth();
+							//node.validity.stepMismatch = (month2 - month1)%_step != 0;
 						}
 						else {
 							switch(type){
@@ -2007,13 +1111,13 @@ $wf2 = {
 			//   and the value of the control doesn't exactly match the control's default value. 
 			//[The maxlength] attribute must not affect the initial value (the DOM defaultValue attribute). It must only
 			//   affect what the user may enter and whether a validity error is flagged during validation.
-			if(doMaxLengthCheck && node.maxLength >= 0 && node.value != node.defaultValue){
+			if(doMaxLengthCheck && node.maxLength >= 0 && node.wf2Value != node.defaultValue){
 				//A newline in a textarea's value must count as two code points for maxlength processing (because
 				//   newlines in textareas are submitted as U+000D U+000A). [[NOT IMPLEMENTED: This includes the
 				//   implied newlines that are added for submission when the wrap attribute has the value hard.]]
 				//var matches = node.value.match(/((?<!\x0D|^)\x0A|\x0D(?!^\x0A|$))/g); //no negative lookbehind
 				var shortNewlines = 0;
-				var v = node.value;
+				var v = node.wf2Value;
 				node.wf2ValueLength = v.length;
 				for(var i = 1; i < v.length; i++){
 					if(v[i] === "\x0A" && v[i-1] !== "\x0D" || v[i] == "\x0D" && (v[i+1] && v[i+1] !== "\x0A"))
@@ -2024,12 +1128,29 @@ $wf2 = {
 				//   has more than the specified number of code points and the value doesn't match the control's default value.
 				node.validity.tooLong = node.wf2ValueLength > node.maxLength;
 			}
+		} else {
+			if(minAttrNode && $wf2.numberRegExp.test(minAttrNode.value))
+				node.min = Number(minAttrNode.value);
+			if(maxAttrNode && $wf2.numberRegExp.test(maxAttrNode.value))
+				node.max = Number(maxAttrNode.value);
+			if(stepAttrNode && $wf2.numberRegExp.test(stepAttrNode.value))
+				node.step = Number(stepAttrNode.value);
 		}
 
 		//customError -- The control was marked invalid from script. See the definition of the setCustomValiditiy() method.
-		
+		//console.log('second: ', node.validity.stepMismatch)
 		node.validity.valid = !$wf2.hasInvalidState(node.validity);
-		
+		if (node.validity.valid) {
+			$wf2.css.removeClass(node, 'wf2_invalid');
+			$wf2.css.addClass(node, 'wf2_valid');
+			//node.className = node.className.replace(/\s?wf2_invalid/g, "") + ' wf2_valid';
+			//console.log('valid: ', node.className)
+		} else { 
+			$wf2.css.removeClass(node, 'wf2_valid');
+			$wf2.css.addClass(node, 'wf2_invalid');
+			//node.className = node.className.replace(/\s?wf2_valid/g, "") + ' wf2_invalid';
+			//console.log('not valid: ', node.className, 'value:', node.value, 'wtfValue:', node.wf2Value)
+		}
 		//This is now done onmousedown or onkeydown, just as Opera does
 		//if(node.validity.valid){
 		//	node.className = node.className.replace(/\s*\binvalid\b\s*/g, " "); //substitute for :invalid pseudo class
@@ -2042,12 +1163,20 @@ $wf2 = {
 		//		errMsg.parentNode.removeChild(errMsg);
 		//}
 	},
+	
+	// checks to see if a number node has a value that is valid.
+	isValidNumber: function (node) {
+		//console.log(node.wf2Value + ", " + node.min + ", " + node.max + ", " + node.step);
+		var n = (parseFloat(node.wf2Value) - parseFloat(node.min))/parseFloat(node.step);
+		//console.log('!' , n == parseInt(n))
+		return (n == parseInt(n));
+	},
 
 	applyValidityInterface : function(node){
 		
 		/* Webkit browsers need this */
-		if ($wf2.hasBadImplementation) {
-			
+		if (!$wf2.hasNativeBubbles || (node.form && $wf2.getAttributeValue(node.form, 'data-webforms2-force-js-validation') == 'true')) {
+			console.log(node.name)
 			if (node.type == 'submit' || node.type == 'button') {
 				
 				node.formNoValidate=true;
@@ -2055,18 +1184,22 @@ $wf2 = {
 			}
 		}
 	
-		/* ZOLTAN made a change here to ensure Google's unfinished native implementation is not used. */
+		/* Made a change here to ensure Google's unfinished native implementation is not used. */
 		else if((node.validity && node.validity.typeMismatch !== undefined)) {//MSIE needs the second test for some reason
 			//	console.log('bad implementation!! ' + node.id);
 			
 			return node;
 		}
+		
+		try {
 		node.validationMessage = "";
 		
 		//ValidityState interface
 		node.validity = $wf2.createValidityState();
 		node.willValidate = true;
-		
+		} catch (ex) {
+			// do nothing.
+		}
 		var nodeName = node.nodeName.toLowerCase();
 		if(nodeName == 'button' || nodeName == 'fieldset'){
 			node.setCustomValidity = function(error){
@@ -2090,39 +1223,58 @@ $wf2 = {
 		//var type = (node.type ? node.type.toLowerCase() : (nodeName == 'input' ? 'text' : ''));
 		var type = (node.getAttribute('type') ? node.getAttribute('type').toLowerCase() : node.type);
 		
-		if(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !node.name || node.disabled)
-			node.willValidate = false;
+		if(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !node.name || node.disabled) {
+			try {
+				node.willValidate = false;
+			} catch (ex) {
+				// do nothing.
+			}
+		}
 		else if(window.RepetitionElement) {
 			var parent = node;
 			while(parent = parent.parentNode){
 				if(parent.repetitionType == RepetitionElement.REPETITION_TEMPLATE){
-					node.willValidate = false;
+					try {
+						node.willValidate = false;
+					} catch (ex) {
+						// do nothing.
+					}
 					break;
 				}
 			}
 		}
 		
-		//var handler = function(event){
-		//	return (event.currentTarget || event.srcElement)._updateValidityState();
-		//};
 		
-		////attempt to check validity live
-		//if(document.addEventListener){
-		//	node.addEventListener('change', handler, false);
-		//	node.addEventListener('blur', handler, false);
-		//	node.addEventListener('keyup', handler, false);
-		//}
-		//else if(window.attachEvent){
-		//	node.attachEvent('onchange', handler);
-		//	node.attachEvent('onblur', handler);
-		//	node.attachEvent('onkeyup', handler);
-		//}
-		//else {
-		//
-		//}
+		
+		var handler = function(event){
+			return $wf2.updateValidityState(event.currentTarget || event.srcElement);
+		};
+		
+		//attempt to check validity live
+		if(document.addEventListener){
+			node.addEventListener('change', handler, false);
+			node.addEventListener('blur', handler, false);
+			node.addEventListener('keyup', handler, false);
+		}
+		else if(window.attachEvent){
+			node.attachEvent('onchange', handler);
+			node.attachEvent('onblur', handler);
+			node.attachEvent('onkeyup', handler);
+		}
+		else {
+		
+		}
 		
 		return node;
 	},
+	
+	/* updateValidityState: function (node) {
+		if (node.checkValidity()){
+			node.className = node.className.replace(/\s?wf2_invalid/, "");
+		} else {
+			node.className += ' wf2_invalid';
+		}
+	}, */
 
 	onsubmitValidityHandler : function(event){
 		var frm = event.currentTarget || event.srcElement;
@@ -2134,7 +1286,7 @@ $wf2 = {
 			$wf2.callBeforeValidation[i](event);
 		}
 		
-		/* ZOLTAN */
+		
 		if(!frm.checkValidity()){
 			if(event.preventDefault)
 				event.preventDefault();
@@ -2207,13 +1359,13 @@ $wf2 = {
 	},
 
 	invalidMessages : {
-		valueMissing   : 'A value must be supplied or selected.',
-		typeMismatch   : 'The value is invalid for %s type.',
+		valueMissing   : 'Please fill out this field.',
+		typeMismatch   : 'Please enter a valid %s.',
 		rangeUnderflow : 'The value must be equal to or greater than %s.',
 		rangeOverflow  : 'The value must be equal to or less than %s.',
 		stepMismatch   : 'The value has a step mismatch; it must be a certain number multiples of %s from %s.',
 		tooLong        : 'The value is too long. The field may have a maximum of %s characters but you supplied %s. Note that each line-break counts as two characters.',
-		patternMismatch: 'The value is not in the format required.'
+		patternMismatch: 'Please match the requested format.'
 	},
 	
 	valueToWF2Type : function(value, type){
@@ -2233,7 +1385,14 @@ $wf2 = {
 	addInvalidIndicator : function(target){
 		//show contextual help message
 		var msg = document.createElement('div');
-		msg.className = 'wf2_errorMsg';
+		msg.className = 'wf2_errorMsg wf2_fromForm_' + (target.form.id || target.form.name);
+		
+		/* Let's put in a container in here so IE9- can put a gradient filter in here. */
+		var msgContainer = document.createElement('div');
+		msgContainer.className = 'wf2_errorMsgContainer';
+		msg.appendChild(msgContainer);
+		
+		
 		//msg.title = "Close";
 		msg.id = (target.id || target.name) + '_wf2_errorMsg'; //QUESTION: does this work for MSIE?
 		msg.onmousedown = function(){
@@ -2245,27 +1404,29 @@ $wf2 = {
 		var isDateTimeRelated = (type == 'datetime' || type == 'datetime-local' || type == 'time' || type == 'date' || type == 'month' || type == 'week');
 
 		var ol = document.createElement('ol');
-		if(target.validity.valueMissing)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.valueMissing));
-		if(target.validity.typeMismatch)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.typeMismatch.replace(/%s/, type)));
-		if(target.validity.rangeUnderflow)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeUnderflow.replace(/%s/, $wf2.valueToWF2Type(target.min, type))));
-		if(target.validity.rangeOverflow)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeOverflow.replace(/%s/, $wf2.valueToWF2Type(target.max, type))));
-		if(target.validity.stepMismatch)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.stepMismatch.replace(/%s/, target.step + ($wf2.stepUnits[type] ? ' ' + $wf2.stepUnits[type] + '(s)' : '')).replace(/%s/, $wf2.valueToWF2Type(target.wf2StepDatum, type))));
-		if(target.validity.tooLong)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.tooLong.replace(/%s/, target.maxLength).replace(/%s/, target.wf2ValueLength ? target.wf2ValueLength : target.value.length)));
-		if(target.validity.patternMismatch)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.patternMismatch.replace(/%s/, target.title ? target.title : ' "' + target.getAttribute('pattern') + '"')));
-		if(target.validity.customError)
+		if(target.validity.customError) {
 			ol.appendChild($wf2.createLI(target.validationMessage));
+		} else {
+			if(target.validity.valueMissing)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.valueMissing));
+			if(target.validity.typeMismatch)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.typeMismatch.replace(/%s/, type)));
+			if(target.validity.rangeUnderflow)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeUnderflow.replace(/%s/, $wf2.valueToWF2Type(target.min, type))));
+			if(target.validity.rangeOverflow)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeOverflow.replace(/%s/, $wf2.valueToWF2Type(target.max, type))));
+			if(target.validity.stepMismatch)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.stepMismatch.replace(/%s/, target.step + ($wf2.stepUnits[type] ? ' ' + $wf2.stepUnits[type] + '(s)' : '')).replace(/%s/, $wf2.valueToWF2Type(target.wf2StepDatum, type))));
+			if(target.validity.tooLong)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.tooLong.replace(/%s/, target.maxLength).replace(/%s/, target.wf2ValueLength ? target.wf2ValueLength : target.value.length)));
+			if(target.validity.patternMismatch)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.patternMismatch.replace(/%s/, target.title ? target.title : ' "' + target.getAttribute('pattern') + '"')));
+		}
 		
 		if(ol.childNodes.length == 1)
 			ol.className = 'single';
 		
-		msg.appendChild(ol);
+		msgContainer.appendChild(ol);
 		////remove existing error message
 		//if(document.getElementById(msg.id))
 		//	document.documentElement.removeChild(document.getElementById(msg.id));
@@ -2294,15 +1455,13 @@ $wf2 = {
 		
 		var top = left = 0;
 		var cur = el;
-		if(cur && cur.offsetParent){
-			left = cur.offsetLeft;
-			top = cur.offsetTop;
-			while(cur = cur.offsetParent){
-				left += cur.offsetLeft;
-				top += cur.offsetTop;
-			}
-			top += el.offsetHeight;
-		}
+		
+		
+		var s = $wf2.css.getAbsoluteCoords(el);	
+		top = s.y + el.offsetHeight;
+		left = s.x;	
+		
+		
 		msg.style.top = top + 'px';
 		msg.style.left = left + 'px';
 		
@@ -2314,23 +1473,34 @@ $wf2 = {
 		//	target.form[target.name].wf2HasInvalidIndicator = true;
 		//	console.info('set')
 		//}
-		if(!target.className.match(/\bwf2_invalid\b/))
-			target.className += " wf2_invalid";
+		/* if(!target.className.match(/\bwf2_invalid\b/))
+			target.className += " wf2_invalid"; */
+		$wf2.css.addClass(target, 'wf2_invalid');
 			
 		if($wf2.indicatorIntervalId == null){
 			//var i = $wf2.invalidIndicators.length - 1;
 			$wf2.indicatorIntervalId = setInterval(function(){
 				var invalidIndicator;
 				for(var i = 0; invalidIndicator = $wf2.invalidIndicators[i]; i++){
+					
+					if (!$wf2.css.isMemberOfClass(invalidIndicator.target, 'wf2_invalid')) {
+						$wf2.css.addClass(invalidIndicator.target, 'wf2_invalid')
+					} else {
+						$wf2.css.removeClass(invalidIndicator.target, 'wf2_invalid');
+					}
+					
+					
+					/* 
 					if(!invalidIndicator.target.className.match(/\bwf2_invalid\b/)){
 						invalidIndicator.target.className += " wf2_invalid";
 					}
 					else {
 						invalidIndicator.target.className = invalidIndicator.target.className.replace(/\s?wf2_invalid/, "");
-					}
+					} */
 				}
 				
 			}, 500);
+			return;
 			// call routines other libraries have set to be run before
 			// validation.
 			setTimeout(function() {
@@ -2355,9 +1525,9 @@ $wf2 = {
 				invalidIndicator.errorMsg.parentNode.removeChild(invalidIndicator.errorMsg);
 			//clearInterval(insts[0].intervalId);
 			var target = invalidIndicator.target;
-			//if(target.form && target.form[target.name])
-			//	target.form[target.name].wf2HasInvalidIndicator = false;
-			target.className = target.className.replace(/\s?wf2_invalid/, ""); //([^\b]\s)?
+			
+			// Removed
+			// target.className = target.className.replace(/\s?wf2_invalid/, ""); //([^\b]\s)?
 			$wf2.invalidIndicators.shift();
 		}
 		
@@ -2422,6 +1592,7 @@ $wf2 = {
 				//	  : document.createElement(node.nodeName);
 						
 				for(i = 0; attr = node.attributes[i]; i++){
+					
 					//MSIE ISSUE: Custom attributes specified do not have .specified property set to true?
 					//ISSUE: VALUE IS REPEATED IN MSIE WHEN VALUE ATTRIBUTE SET?
 					//if(attr.specified || node.getAttribute(attr.nodeName)) //$wf2.cloneNode_customAttrs[attr.nodeName] || 
@@ -2435,6 +1606,7 @@ $wf2 = {
 								(!isTemplate || (rtNestedDepth > 1 || !$wf2.cloneNode_rtEventHandlerAttrs[attr.name])) // && 
 							))
 					{
+						
 						//MSIE BUG: when button[type=add|remove|move-up|move-down], then (attr.nodeValue and attr.value == 'button') but node.getAttribute(attr.nodeName) == 'add|remove|move-up|move-down' (as desired)
 						
 						//clone and process an event handler property (attribute);
@@ -2450,6 +1622,7 @@ $wf2 = {
 							attrValue = (processAttr ? processAttr(attrValue) : attrValue);
 							clone.setAttribute(attr.name, attrValue);
 						}
+						//console.log(StringHelpers.sprintf("AFTER attr: %s val: %s (%s)", attr.name, attr.value, processAttr(attrValue)))
 					}
 				}
 				//MSIE BUG: setAttribute('class') creates duplicate value attribute in MSIE; 
@@ -2917,91 +2090,234 @@ $wf2 = {
 		//};
 	
 		return err;
-	}
-}; //End $wf2 = {
-
-
-/*##############################################################################################
- # Section: Repetition Model Definitions
- ##############################################################################################*/
-
-var RepetitionElement = {
-	REPETITION_NONE:0,
-	REPETITION_TEMPLATE:1,
-	REPETITION_BLOCK:2
-};
-
-var RepetitionEvent = {
-	//the following takes a UIEvent and adds the required properties for a RepetitionEvent
-	_upgradeEvent : function(){
-		this.initRepetitionEvent = RepetitionEvent.initRepetitionEvent;
-		this.initRepetitionEventNS = RepetitionEvent.initRepetitionEventNS;
 	},
-	initRepetitionEvent : function(typeArg, canBubbleArg, cancelableArg, elementArg){
-		if(this.initEvent)
-			this.initEvent(typeArg, canBubbleArg, cancelableArg);
-		else { //manually initialize event (i.e., for MSIE)
-			this.type = typeArg;
-	//		switch(typeArg.toLowerCase()){
-	//			case 'added':
-	//				this.type = 'add';
-	//				break;
-	//			case 'removed':
-	//				this.type = 'remove';
-	//				break;
-	//			case 'moved':
-	//				this.type = 'move';
-	//				break;
-	//		}
-			//this.srcElement = elementArg.repetitionTemplate;
-			//this.cancelBubble = false;
-			//this.cancelable = cancelableArg;
-			//this.returnValue = false;
+	
+	css: new function () {
+		var me = this;
+		
+		var blankRe = new RegExp('\\s');
+
+		/**
+		 * Generates a regular expression string that can be used to detect a class name
+		 * in a tag's class attribute.  It is used by a few methods, so I 
+		 * centralized it.
+		 * 
+		 * @param {String} className - a name of a CSS class.
+		 */
+		
+		function getClassReString(className) {
+			return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
+		}
+		
+		function getClassPrefixReString(className) {
+			return '\\s'+className+'-[0-9a-zA-Z_]+\\s|^' + className + '[0-9a-zA-Z_]+\\s|\\s' + className + '[0-9a-zA-Z_]+$|' + '^' + className +'[0-9a-zA-Z_]+$';
+		}
+		
+		
+		/**
+		 * Make an HTML object be a member of a certain class.
+		 * 
+		 * @param {Object} obj - an HTML object
+		 * @param {String} className - a CSS class name.
+		 */
+		me.addClass = function (obj, className) {
 			
-			if(!this.preventDefault)
-			this.preventDefault = function(){
-				this.returnValue = false;
-			};
-			if(!this.stopPropagation)
-			this.stopPropagation = function(){
-				this.cancelBubble = true;
+			if (blankRe.test(className)) {
+				return;
+			}
+			
+			// only add class if the object is not a member of it yet.
+			if (!me.isMemberOfClass(obj, className)) {
+				obj.className += " " + className;
+			}
+			
+		}
+		
+		/**
+		 * Make an HTML object *not* be a member of a certain class.
+		 * 
+		 * @param {Object} obj - an HTML object
+		 * @param {Object} className - a CSS class name.
+		 */
+		me.removeClass = function (obj, className) {
+			
+			if (blankRe.test(className)) {
+				return; 
+			}
+			
+			
+			var re = new RegExp(getClassReString(className) , "g");
+			
+			var oldClassName = obj.className;
+		
+		
+			if (obj.className) {
+				obj.className = oldClassName.replace(re, ' ');
+			}
+		
+			
+		}
+		
+		/**
+		 * Determines if an HTML object is a member of a specific class.
+		 * @param {Object} obj - an HTML object.
+		 * @param {Object} className - the CSS class name.
+		 */
+		me.isMemberOfClass = function (obj, className) {
+			
+			if (blankRe.test(className))
+				return false;
+			
+			var re = new RegExp(getClassReString(className) , "g");
+		
+			return (re.test(obj.className));
+		
+		
+		}
+		
+		me.getAbsoluteCoords = function(obj) {
+		
+			var curleft = obj.offsetLeft;
+			var curtop = obj.offsetTop;
+			
+			/*
+			 * IE and Gecko
+			 */
+			if (obj.getBoundingClientRect) {
+				var temp = obj.getBoundingClientRect();
+				
+				curleft = temp.left + me.getScrollX();
+				curtop = temp.top + me.getScrollY();
+			} else {
+			
+				/* Everything else must do the quirkmode.org way */
+			
+				if (obj.offsetParent) {
+				
+					while (obj = obj.offsetParent) {
+						curleft += obj.offsetLeft - obj.scrollLeft;
+						curtop += obj.offsetTop - obj.scrollTop;
+					}
+				}
+			}
+			return {
+				x: curleft,
+				y: curtop
 			};
 		}
-		this.element = elementArg;
-		this.relatedNode = elementArg; //for Opera (deprecated?)
-	},
-	initRepetitionEventNS : function(namespaceURIArg, typeArg, canBubbleArg, cancelableArg, elementArg){
-		throw Error("NOT IMPLEMENTED: RepetitionEvent.initRepetitionEventNS");
-		//this.initEvent(namespaceURIArg, typeArg, canBubbleArg, cancelableArg);
-		//this.element = elementArg;
-		//this.relatedNode = elementArg; //for Opera (deprecated?)
+		
+		/**
+		 * Get the the amount of pixels the window has been scrolled from the top.  If there is no
+		 * vertical scrollbar, this function return 0.
+		 *
+		 * @return {int} - the amount of pixels the window has been scrolled to the right, in pixels.
+		 */
+		me.getScrollX = function (myWindow)
+		{
+			var myDocument;
+			
+			if (myWindow) {
+				myDocument = myWindow.document;
+			} else {
+				myWindow = window;
+				myDocument = document;
+			}
+			
+			// All except that I know of except IE
+			if (myWindow.pageXOffset != null) {
+				return myWindow.pageXOffset;
+			// IE 6.x strict
+			} else if (myDocument.documentElement != null 
+					&& myDocument.documentElement.scrollLeft !="0px" 
+						&& myDocument.documentElement.scrollLeft !=0)  {
+				return myDocument.documentElement.scrollLeft;
+			// all other IE
+			} else if (myDocument.body != null && 
+				myDocument.body.scrollLeft != null) {
+				return myDocument.body.scrollLeft;
+			// if for some reason none of the above work, this should.
+			} else if (myWindow.scrollX != null) {
+				return myWindow.scrollX;
+			} else {
+				return null;
+			}
+		}
+		
+		/**
+		 * Get the the amount of pixels the window has been scrolled to the right.  If there is no
+		 * horizontal scrollbar, this function return 0.
+		 * 
+		 * @return {int} - the amount of pixels the window has been scrolled to the right, in pixels.
+		 */
+		me.getScrollY = function(myWindow)
+		{
+			var myDocument;
+			
+			if (myWindow) {
+				myDocument = myWindow.document;
+			} else {
+				myWindow = window;
+				myDocument = document;
+			}
+			
+			// All except that I know of except IE
+			if (myWindow.pageYOffset != null) {
+				return myWindow.pageYOffset;
+			// IE 6.x strict
+			} else if (myDocument.documentElement != null
+					&& myDocument.documentElement.scrollTop !="0px" 
+						&& myDocument.documentElement.scrollTop !=0) {
+				return myDocument.documentElement.scrollTop;
+			// all other IE
+			} else if (myDocument.body && myDocument.body.scrollTop != null) { 
+				return myDocument.body.scrollTop;
+			// if for some reason none of the above work, this should.
+			} else if (myWindow.scrollY != null) { 
+				return myWindow.scrollY;
+			} else {
+				return null;
+			}
+		}
+		
+		/**
+		 * gets the current window's height.  
+		 * 
+		 * @author Peter-Paul Koch - http://www.quirksmode.org
+		 * @license see http://www.quirksmode.org/about/copyright.html
+		 * @return {int} - the window's height in pixels.
+		 */
+		me.getWindowHeight = function  (theWindow)
+		{
+			if (!theWindow) {
+				theWindow = window;
+			}
+				
+			var theDocument = theWindow.document;
+			
+			// all except IE
+			if (theWindow.innerHeight != null) {
+				return theWindow.innerHeight;
+			// IE6 Strict mode
+			} else if (theDocument.documentElement && 
+					theDocument.documentElement.clientHeight ) {
+				return theDocument.documentElement.clientHeight;
+			// IE strictly less than 6
+			} else if (theDocument.body != null) {
+				return theDocument.body.clientHeight;
+			} else {
+				return null;
+			}
+		}
 	}
-};
+}; //End $wf2 = {
+
+
+
 
 /*##############################################################################################
  # Change the prototypes of HTML elements
  ##############################################################################################*/
 
-//RepetitionElement interface must be implemented by all elements.
-if(window.Element && Element.prototype){
-	Element.prototype.REPETITION_NONE     = RepetitionElement.REPETITION_NONE;
-	Element.prototype.REPETITION_TEMPLATE = RepetitionElement.REPETITION_TEMPLATE;
-	Element.prototype.REPETITION_BLOCK    = RepetitionElement.REPETITION_BLOCK;
-	
-	Element.prototype.repetitionType      = RepetitionElement.REPETITION_NONE;
-	Element.prototype.repetitionIndex     = 0;
-	Element.prototype.repetitionTemplate  = null; /*readonly*/
-	Element.prototype.repetitionBlocks    = null; /*readonly*/
-
-	Element.prototype.repeatStart = 1;
-	Element.prototype.repeatMin   = 0;
-	Element.prototype.repeatMax   = Number.MAX_VALUE; //Infinity;
-	
-	Element.prototype.addRepetitionBlock        = $wf2.addRepetitionBlock;
-	Element.prototype.addRepetitionBlockByIndex = $wf2.addRepetitionBlockByIndex;
-	Element.prototype.moveRepetitionBlock       = $wf2.moveRepetitionBlock;
-	Element.prototype.removeRepetitionBlock     = $wf2.removeRepetitionBlock;
-}
 
 /*##############################################################################################
  # Set mutation event handlers to automatically add WF2 behaviors
@@ -3111,8 +2427,10 @@ else if(/MSIE/i.test(navigator.userAgent) && !document.addEventListener && windo
 			
 			//See issue #3 <http://code.google.com/p/repetitionmodel/issues/detail?id=3>
 			//Sometimes cssQuery doesn't find all repetition templates from here within this DOMContentLoaded substitute
-			if($wf2.repetitionTemplates.length == 0)
-				$wf2.isInitialized = false;
+			if (window.$wf2Rep) {
+				if($wf2.repetitionTemplates.length == 0)
+					$wf2.isInitialized = false;
+			}
 		}
 	};
 	script = null;
@@ -3135,51 +2453,12 @@ if(!eventSet){
 })();
 } //End If(!document.implementation...
 
-/*##############################################################################################
- # Extensions for existing Web Forms 2.0 Implementations
- ##############################################################################################*/
-else if(document.addEventListener && ($wf2.oldRepetitionEventModelEnabled === undefined || $wf2.oldRepetitionEventModelEnabled)){
-	$wf2.oldRepetitionEventModelEnabled = true;
-	(function(){
-		
-	var deprecatedAttrs = {
-		added   : 'onadd',
-		removed : 'onremove',
-		moved   : 'onmove'
-	};
-	
-	function handleRepetitionEvent(evt){
-		if(!$wf2.oldRepetitionEventModelEnabled)
-			return;
-		if(!evt.element && evt.relatedNode) //Opera uses evt.relatedNode instead of evt.element as the specification dictates
-			evt.element = evt.relatedNode;
-		if(!evt.element || !evt.element.repetitionTemplate)
-			return;
-		
-		var rt = evt.element.repetitionTemplate;
-		var attrName = 'on' + evt.type;
-		
-		//Add support for event handler set with HTML attribute
-		var handlerAttr = rt.getAttribute(attrName) || /* deprecated */ rt.getAttribute(deprecatedAttrs[evt.type]);
-		if(handlerAttr && (!rt[attrName] || typeof rt[attrName] != 'function')) //in MSIE, attribute == property
-			rt[attrName] = new Function('event', handlerAttr);
-		
-		if(evt.element.repetitionTemplate[attrName])
-			evt.element.repetitionTemplate[attrName](evt);
-		else if(evt.element.repetitionTemplate[deprecatedAttrs[evt.type]]) //deprecated
-			evt.element.repetitionTemplate[deprecatedAttrs[evt.type]](evt);
-	}
-	
-	document.addEventListener('added', handleRepetitionEvent, false);
-	document.addEventListener('removed', handleRepetitionEvent, false);
-	document.addEventListener('moved', handleRepetitionEvent, false);
-	
-	})();
-}
+
 
 } //end if(!window.$wf2)
 
 
+
 //if(!window.ValidityState){
 	//var ValidityState = {
 	//	
@@ -3204,6 +2483,6 @@ else if(document.addEventListener && ($wf2.oldRepetitionEventModelEnabled === un
 	
 //}
 
-//if(!window.HTMLOutputElement){
+//if(!window.HTMLOutputElement){ 
 	
 //}
diff --git a/shared/js/weston.ruter.net/webforms2/webforms2_src.js.new b/shared/js/weston.ruter.net/webforms2/webforms2_withRep_src.js
similarity index 90%
rename from shared/js/weston.ruter.net/webforms2/webforms2_src.js.new
rename to shared/js/weston.ruter.net/webforms2/webforms2_withRep_src.js
index 7948f15..0b35eac 100644
--- a/shared/js/weston.ruter.net/webforms2/webforms2_src.js.new
+++ b/shared/js/weston.ruter.net/webforms2/webforms2_withRep_src.js
@@ -1,14 +1,23 @@
 /*
  * Web Forms 2.0 Cross-browser Implementation <http://code.google.com/p/webforms2/>
- * Version: 0.5.4 (2008-07-29)
- * Copyright: 2007, Weston Ruter <http://weston.ruter.net/>
- * License: GNU General Public License, Free Software Foundation
- *          <http://creativecommons.org/licenses/GPL/2.0/>
+ * Version: 0.7 (2011-03-01)
+ * Copyright: 2007, Weston Ruter <http://weston.ruter.net/> 
+ *    with additions by Zoltan Hawryluk <http://www.useragentman.com>
+ * Licenses (as of Feb 6, 2011)
+ * - MIT License (http://www.opensource.org/licenses/mit-license.php)
+ * - GPL (http://creativecommons.org/licenses/GPL/2.0/)
  * 
  * The comments contained in this code are largely quotations from the 
  * WebForms 2.0 specification: <http://whatwg.org/specs/web-forms/current-work/>
  *
  * Usage: <script type="text/javascript" src="webforms2_src.js"></script>
+ * 
+ * Changelog:
+ * version 0.5.4  - initial release by Weston Ruter
+ * version 0.6    - refactored for use with HTML5Widgets by Zoltan Hawryluk (July 27th, 2010)
+ * version 0.6.1  - updated to deal with WebKit's half-implemented WebForms 2 Implementation (Sept 10, 2010)
+ * version 0.7    - bug fixes with nested repetition models by Zoltan Hawryluk.
+ * version 0.7.1  - updated to dual MIT/GPL 2.0 license.
  */
 
 if(!window.$wf2){
@@ -26,10 +35,11 @@ $wf2 = {
 	hasElementExtensions : (window.HTMLElement && HTMLElement.prototype),
 	hasGettersAndSetters : ($wf2.__defineGetter__ && $wf2.__defineSetter__),
 	
-	hasBadImplementation: navigator.userAgent.indexOf('Chrome'),
+	hasBadImplementation: navigator.userAgent.indexOf('WebKit') > 0,
 	
 	callBeforeValidation : new Array(),
 	callAfterValidation : new Array(),
+	callAfterDOMContentLoaded: new Array(),
 	
 	
 	onDOMContentLoaded : function(){
@@ -113,6 +123,10 @@ $wf2 = {
 		}
 		
 		$wf2.initNonRepetitionFunctionality();
+		
+		for (var i=0; i<$wf2.callAfterDOMContentLoaded.length; i++) {
+			$wf2.callAfterDOMContentLoaded[i]();
+		}
 	},
 
 
@@ -516,7 +530,9 @@ $wf2 = {
 		//   (Invoking the template's replication behaviour means calling its addRepetitionBlock() method).
 		//for(var i = 0; i < Math.max(this.repeatStart, this.repeatMin); i++)
 		for(var i = 0; (i < this.repeatStart || this.repetitionBlocks.length < this.repeatMin); i++)
-			this.addRepetitionBlock();
+			if (!this.addRepetitionBlock()) {
+				break;
+			}
 		
 		$wf2.repetitionTemplates.push(this);
 		this.wf2Initialized = true;
@@ -1420,9 +1436,7 @@ $wf2 = {
 	initNonRepetitionFunctionality : function(parent){
 		parent = (parent || document.documentElement);
 		var i,j, frm, frms = parent.getElementsByTagName('form');
-		
 		for(i = 0; frm = frms[i]; i++){
-			
 			if(frm.checkValidity && !$wf2.hasBadImplementation)
 				continue;
 			frm.checkValidity = $wf2.formCheckValidity;
@@ -1433,7 +1447,7 @@ $wf2 = {
 				frm.attachEvent('onsubmit', $wf2.onsubmitValidityHandler);
 		}
 		
-		var ctrl, ctrls = $wf2.getElementsByTagNames.apply(parent, ['input','select','textarea']);//parent.getElementsByTagName([i]);
+		var ctrl, ctrls = $wf2.getElementsByTagNames.apply(parent, ['input','select','textarea', 'button']);//parent.getElementsByTagName([i]);
 		for(i = 0; ctrl = ctrls[i]; i++){
 			$wf2.applyValidityInterface(ctrl);
 			$wf2.updateValidityState(ctrl); //ctrl._updateValidityState();
@@ -1510,16 +1524,35 @@ $wf2 = {
 			el.willValidate = !(/(hidden|button|reset|add|remove|move-up|move-down)/.test(type) || !el.name || el.disabled)
 			//Then, each element in this list whose willValidate DOM attribute is true is checked for validity
 			if(el.checkValidity && el.willValidate){
-				if(!el.checkValidity())
+				if(!el.checkValidity() && el.checkValidity() != undefined) {
 					valid = false;
+					
+					
+					/* we change this to only show the first error.
+					if (!$wf2.showAllErrors) {
+						break;
+					}
+					*/
+				}
 			}
 		}
 		
-		if(!valid && $wf2.invalidIndicators.length){ //second condition needed because modal in oninvalid handler may cause indicators to disappear before this is reached
-			$wf2.invalidIndicators[0].errorMsg.className += " wf2_firstErrorMsg";
-			
+		if (!valid) {
+			$wf2.hiliteFirstError();
+		}
+		return valid;
+	},
+	
+	hiliteFirstError: function () {
+		
+		if($wf2.invalidIndicators.length){ //second condition needed because modal in oninvalid handler may cause indicators to disappear before this is reached
+			//$wf2.invalidIndicators[0].errorMsg.className += " wf2_firstErrorMsg";
+			$wf2.css.addClass($wf2.invalidIndicators[0].errorMsg, "wf2_firstErrorMsg");
 			//scroll to near the location where invalid control is
 			el = $wf2.invalidIndicators[0].target;
+			
+			var doScroll = (el.form.getAttribute('data-wf2-no-scroll-on-error') != 'true')
+			
 			if(el.style.display == 'none' || !el.offsetParent){
 				while(el && (el.nodeType != 1 || (el.style.display == 'none' || !el.offsetParent)))
 					el = el.previousSibling;
@@ -1530,7 +1563,9 @@ $wf2 = {
 					while (cur = cur.offsetParent)
 						top += cur.offsetTop;
 				}
-				scrollTo(0, top);
+				if (doScroll) {
+					scrollTo(0, top);
+				}
 			}
 			//focus on the first invalid control and make sure error message is visible
 			else {
@@ -1543,14 +1578,16 @@ $wf2 = {
 				, 10)
 				
 				//NOTE: We should only do this if the control's style.bottom == 0
-				scrollBy(0, $wf2.invalidIndicators[0].errorMsg.offsetHeight);
+				if (doScroll) {
+					scrollBy(0, $wf2.invalidIndicators[0].errorMsg.offsetHeight);
+				}
 			}
 		}
-		return valid;
+		
 	},
 	
 	controlCheckValidity : function(){
-		$wf2.controlCheckValidityOfElement(this);
+		return $wf2.controlCheckValidityOfElement(this);
 		
 	},
 	
@@ -1560,8 +1597,10 @@ $wf2 = {
 		
 		$wf2.updateValidityState(el);
 		
-		if(el.validity.valid)
+		if (el.validity.valid) {
+			
 			return true;
+		}
 		
 		var canceled = false;
 		
@@ -1666,17 +1705,19 @@ $wf2 = {
 	getOriginalAttrNode: function (node, attrName) {
 		var r;
 		
-		var dataSetItemName = attrName + 'AttrNode';
+		/* var dataSetItemName = attrName + 'AttrNode';
 		
 		if ($wf2.getDatasetItem(node, dataSetItemName) == null) {
 			r = $wf2.copyOf(node.getAttributeNode(attrName));
-			$wf2.setDatasetItem(node, dataSetItemName, r);
+			$wf2.setDatasetItem(node, dataSetItemName, r.value);
 		} else {
 			r = $wf2.getDatasetItem(node, dataSetItemName);
 			if (r == 'null') {
 				r = null;
 			}
-		}
+		} */
+		
+		r = $wf2.copyOf(node.getAttributeNode(attrName));
 		
 		return r;
 	},
@@ -1690,8 +1731,9 @@ $wf2 = {
 		
 		minAttrNode = $wf2.getOriginalAttrNode(node, 'min');
 		maxAttrNode = $wf2.getOriginalAttrNode(node, 'max');
+		stepAttrNode = $wf2.getOriginalAttrNode(node, 'step');
 		valueAttrNode = $wf2.getOriginalAttrNode(node, 'value');
-
+		
 		node.min = undefined; //wf2Min
 		node.max = undefined; //wf2Max
 		node.step = undefined; //wf2Step
@@ -1740,9 +1782,15 @@ $wf2 = {
 				node.value = node.min;
 				node.wf2ValueProvided = true;
 			}
+			return;
 		}
 		
-		node.wf2Value = node.value;
+		if ($wf2.css.isMemberOfClass(node, 'html5-hasPlaceholderText')) {
+			node.wf2Value = '';
+		} else {
+			node.wf2Value = node.value;
+		}
+		//console.log("changing:", node.value, ", " , node.wf2Value)
 
 		//valueMissing -- The control has the required attribute set but it has not been satisfied.
 		//The required attribute applies to all form controls except controls with the type hidden,
@@ -1791,13 +1839,13 @@ $wf2 = {
 				//For other controls, any non-empty value shall satisfy the required condition,
 				//   including a simple whitespace character.
 				//else
-					node.validity.valueMissing = (node.value == '');
+					node.validity.valueMissing = (node.wf2Value == '');
 			}
 			//if(node.options ? node.selectedIndex == -1 : node.value === '')
 			//	node.validity.valueMissing = true;
 			//
 		}
-		if(!node.validity.valueMissing && node.value){
+		if(!node.validity.valueMissing && node.wf2Value){
 			//patternMismatch -- The value of the control with a pattern attribute doesn't match the pattern. 
 			//   If the control is empty, this flag must not be set.
 			//If the pattern attribute is present but empty, it doesn't match any value, and thus the
@@ -1814,20 +1862,21 @@ $wf2 = {
 				//When the pattern is not a valid regular expression, it is ignored for the purposes of
 				//   validation, as if it wasn't specified.
 				if(rePattern)
-					node.validity.patternMismatch = !rePattern.test(node.value);
+					node.validity.patternMismatch = !rePattern.test(node.wf2Value);
 			}
 			
 			//typeMismatch -- The data entered does not match the type of the control. For example, if the UA 
 			//   allows uninterpreted arbitrary text entry for month controls, and the user has entered SEP02, 
 			//   then this flag would be set. This code is also used when the selected file in a file upload 
 			//   control does not have an appropriate MIME type. If the control is empty, this flag must not be set.
-			if(isDateRelated || isTimeRelated)
-				node.validity.typeMismatch = ((node.wf2Value = $wf2.parseISO8601(node.value, type)) == null);
-			else {
+			if(isDateRelated || isTimeRelated) {
+				//node.validity.typeMismatch = ((node.value = $wf2.parseISO8601(node.wf2Value, type)) == null);
+				//node.wf2Value = node.value;
+			} else {
 				switch(type){
 					case 'number':
 					case 'range':
-						node.validity.typeMismatch = !$wf2.numberRegExp.test(node.value);
+						node.validity.typeMismatch = !$wf2.numberRegExp.test(node.wf2Value);
 	//						if(!node.validity.typeMismatch && node.getAttribute("step") != 'any'){
 	//							if(node.step == undefined)
 	//								node.step = 1;
@@ -1841,7 +1890,7 @@ $wf2 = {
 						//   subtoken everywhere except in the quoted-string subtoken. UAs could, for example, offer
 						//   e-mail addresses from the user's address book. (See below for notes on IDN.)
 						//http://www.ietf.org/rfc/rfc2822						
-						node.validity.typeMismatch = !$wf2.emailRegExp.test(node.value);
+						node.validity.typeMismatch = !$wf2.emailRegExp.test(node.wf2Value);
 						break;
 					case 'url':
 						//An IRI, as defined by [RFC3987] (the IRI token, defined in RFC 3987 section 2.2). UAs could,
@@ -1850,7 +1899,7 @@ $wf2 = {
 						//   generally felt authors are more familiar with the term "URL" than the other, more technically
 						//   correct terms.
 						//http://www.ietf.org/rfc/rfc3987
-						node.validity.typeMismatch = !$wf2.urlRegExp.test(node.value);
+						node.validity.typeMismatch = !$wf2.urlRegExp.test(node.wf2Value);
 						break;
 				}
 			}
@@ -1878,9 +1927,13 @@ $wf2 = {
 								node.min = Number(minAttrNode.value);
 							if(maxAttrNode && $wf2.numberRegExp.test(maxAttrNode.value))
 								node.max = Number(maxAttrNode.value);
+							if(stepAttrNode && $wf2.numberRegExp.test(stepAttrNode.value))
+								node.step = Number(stepAttrNode.value);
 						}
-						node.validity.rangeUnderflow = (node.min != undefined && Number(node.value) < node.min);
-						node.validity.rangeOverflow  = (node.max != undefined && Number(node.value) > node.max);
+						node.validity.rangeUnderflow = (node.min != undefined && Number(node.wf2Value) < node.min);
+						node.validity.rangeOverflow  = (node.max != undefined && Number(node.wf2Value) > node.max);
+						node.validity.stepMismatch = !$wf2.isValidNumber(node);
+						//console.log('first: ', node.validity.stepMismatch, ',', node.getAttribute('type'))
 					}
 					//For file types it must be a sequence of digits 0-9, treated as a base ten integer.
 					else if(type == 'file'){
@@ -1914,12 +1967,15 @@ $wf2 = {
 					}
 				}
 				//The step attribute controls the precision allowed for the date-related, time-related, and numeric types.
-				if(doCheckPrecision && !node.validity.rangeUnderflow && !node.validity.rangeOverflow){
+				
+				//Note: webforms2 as of March 6, 2012 does not support step for time related inputs.  Will revisit later.
+				if(!(isDateRelated || isTimeRelated) && doCheckPrecision && !node.validity.rangeUnderflow && !node.validity.rangeOverflow){
 					//stepMismatch -- The value is not one of the values allowed by the step attribute, and the UA will 
 					//   not be rounding the value for submission. Empty values and values that caused the typeMismatch 
 					//   flag to be set must not cause this flag to be set.
 					
 					var stepAttrNode = $wf2.getOriginalAttrNode(node, 'step'); //node.getAttributeNode('step');
+					
 					if(!stepAttrNode){
 						//The step attribute [for types datetime, datetime-local, and time] ... defaulting to 60 (one minute).
 						//For time controls, the value of the step attribute is in seconds, although it may be a fractional
@@ -1961,9 +2017,9 @@ $wf2 = {
 						//   and for time controls is 00:00.
 						var _step = node.step;
 						if(type == 'month' && node.wf2StepDatum && node.wf2StepDatum.getUTCFullYear){
-							var month1 = node.wf2StepDatum.getUTCFullYear()*12 + node.wf2StepDatum.getUTCMonth();
-							var month2 = node.wf2Value.getUTCFullYear()*12 + node.wf2Value.getUTCMonth();
-							node.validity.stepMismatch = (month2 - month1)%_step != 0;
+							//var month1 = node.wf2StepDatum.getUTCFullYear()*12 + node.wf2StepDatum.getUTCMonth();
+							//var month2 = node.wf2Value.getUTCFullYear()*12 + node.wf2Value.getUTCMonth();
+							//node.validity.stepMismatch = (month2 - month1)%_step != 0;
 						}
 						else {
 							switch(type){
@@ -1993,13 +2049,13 @@ $wf2 = {
 			//   and the value of the control doesn't exactly match the control's default value. 
 			//[The maxlength] attribute must not affect the initial value (the DOM defaultValue attribute). It must only
 			//   affect what the user may enter and whether a validity error is flagged during validation.
-			if(doMaxLengthCheck && node.maxLength >= 0 && node.value != node.defaultValue){
+			if(doMaxLengthCheck && node.maxLength >= 0 && node.wf2Value != node.defaultValue){
 				//A newline in a textarea's value must count as two code points for maxlength processing (because
 				//   newlines in textareas are submitted as U+000D U+000A). [[NOT IMPLEMENTED: This includes the
 				//   implied newlines that are added for submission when the wrap attribute has the value hard.]]
 				//var matches = node.value.match(/((?<!\x0D|^)\x0A|\x0D(?!^\x0A|$))/g); //no negative lookbehind
 				var shortNewlines = 0;
-				var v = node.value;
+				var v = node.wf2Value;
 				node.wf2ValueLength = v.length;
 				for(var i = 1; i < v.length; i++){
 					if(v[i] === "\x0A" && v[i-1] !== "\x0D" || v[i] == "\x0D" && (v[i+1] && v[i+1] !== "\x0A"))
@@ -2010,12 +2066,29 @@ $wf2 = {
 				//   has more than the specified number of code points and the value doesn't match the control's default value.
 				node.validity.tooLong = node.wf2ValueLength > node.maxLength;
 			}
+		} else {
+			if(minAttrNode && $wf2.numberRegExp.test(minAttrNode.value))
+				node.min = Number(minAttrNode.value);
+			if(maxAttrNode && $wf2.numberRegExp.test(maxAttrNode.value))
+				node.max = Number(maxAttrNode.value);
+			if(stepAttrNode && $wf2.numberRegExp.test(stepAttrNode.value))
+				node.step = Number(stepAttrNode.value);
 		}
 
 		//customError -- The control was marked invalid from script. See the definition of the setCustomValiditiy() method.
-		
+		//console.log('second: ', node.validity.stepMismatch)
 		node.validity.valid = !$wf2.hasInvalidState(node.validity);
-		
+		if (node.validity.valid) {
+			$wf2.css.removeClass(node, 'wf2_invalid');
+			$wf2.css.addClass(node, 'wf2_valid');
+			//node.className = node.className.replace(/\s?wf2_invalid/g, "") + ' wf2_valid';
+			//console.log('valid: ', node.className)
+		} else { 
+			$wf2.css.removeClass(node, 'wf2_valid');
+			$wf2.css.addClass(node, 'wf2_invalid');
+			//node.className = node.className.replace(/\s?wf2_valid/g, "") + ' wf2_invalid';
+			//console.log('not valid: ', node.className, 'value:', node.value, 'wtfValue:', node.wf2Value)
+		}
 		//This is now done onmousedown or onkeydown, just as Opera does
 		//if(node.validity.valid){
 		//	node.className = node.className.replace(/\s*\binvalid\b\s*/g, " "); //substitute for :invalid pseudo class
@@ -2028,16 +2101,31 @@ $wf2 = {
 		//		errMsg.parentNode.removeChild(errMsg);
 		//}
 	},
+	
+	// checks to see if a number node has a value that is valid.
+	isValidNumber: function (node) {
+		//console.log(node.wf2Value + ", " + node.min + ", " + node.max + ", " + node.step);
+		var n = (parseFloat(node.wf2Value) - parseFloat(node.min))/parseFloat(node.step);
+		//console.log('!' , n == parseInt(n))
+		return (n == parseInt(n));
+	},
 
 	applyValidityInterface : function(node){
-		console.log('applying' + $wf2.hasBadImplementation)
-		//alert(node.validity.typeMismatch)
+		
+		/* Webkit browsers need this */
+		if ($wf2.hasBadImplementation) {
+			
+			if (node.type == 'submit' || node.type == 'button') {
+				
+				node.formNoValidate=true;
+				
+			}
+		}
 	
 		/* ZOLTAN made a change here to ensure Google's unfinished native implementation is not used. */
-		if ($wf2.hasBadImplementation) {
-			console.log(node.id)
-		} else if((node.validity && node.validity.typeMismatch !== undefined) || !$wf2.hasBadImplementation) {//MSIE needs the second test for some reason
-			console.log('bad implementation!!');
+		else if((node.validity && node.validity.typeMismatch !== undefined)) {//MSIE needs the second test for some reason
+			//	console.log('bad implementation!! ' + node.id);
+			
 			return node;
 		}
 		node.validationMessage = "";
@@ -2057,15 +2145,13 @@ $wf2 = {
 			return node;
 		}
 		//node._updateValidityState = $wf2._updateValidityState;
-		//alert(node.checkValidity)
 		
 		if (!node.setCustomValidity) {
 			node.setCustomValidity = $wf2.controlSetCustomValidity;
 		}
 		
-		if (!node.checkValidity) {
-			node.checkValidity = $wf2.controlCheckValidity;
-		}
+		
+		node.checkValidity = $wf2.controlCheckValidity;
 		
 		
 		//var type = (node.type ? node.type.toLowerCase() : (nodeName == 'input' ? 'text' : ''));
@@ -2083,37 +2169,40 @@ $wf2 = {
 			}
 		}
 		
-		//var handler = function(event){
-		//	return (event.currentTarget || event.srcElement)._updateValidityState();
-		//};
 		
-		////attempt to check validity live
-		//if(document.addEventListener){
-		//	node.addEventListener('change', handler, false);
-		//	node.addEventListener('blur', handler, false);
-		//	node.addEventListener('keyup', handler, false);
-		//}
-		//else if(window.attachEvent){
-		//	node.attachEvent('onchange', handler);
-		//	node.attachEvent('onblur', handler);
-		//	node.attachEvent('onkeyup', handler);
-		//}
-		//else {
-		//
-		//}
+		/* ZOLTAN: validity */
+		var handler = function(event){
+			return $wf2.updateValidityState(event.currentTarget || event.srcElement);
+		};
+		
+		//attempt to check validity live
+		if(document.addEventListener){
+			node.addEventListener('change', handler, false);
+			node.addEventListener('blur', handler, false);
+			node.addEventListener('keyup', handler, false);
+		}
+		else if(window.attachEvent){
+			node.attachEvent('onchange', handler);
+			node.attachEvent('onblur', handler);
+			node.attachEvent('onkeyup', handler);
+		}
+		else {
+		
+		}
 		
 		return node;
 	},
+	
+	/* updateValidityState: function (node) {
+		if (node.checkValidity()){
+			node.className = node.className.replace(/\s?wf2_invalid/, "");
+		} else {
+			node.className += ' wf2_invalid';
+		}
+	}, */
 
 	onsubmitValidityHandler : function(event){
-		
 		var frm = event.currentTarget || event.srcElement;
-		
-		if (frm.nodeType != "FORM") {
-			frm = frm.form;
-		}
-		
-		
 		var r;
 		
 		// call routines other libraries have set to be run before
@@ -2195,13 +2284,13 @@ $wf2 = {
 	},
 
 	invalidMessages : {
-		valueMissing   : 'A value must be supplied or selected.',
-		typeMismatch   : 'The value is invalid for %s type.',
+		valueMissing   : 'Please fill out this field.',
+		typeMismatch   : 'Please enter a valid %s.',
 		rangeUnderflow : 'The value must be equal to or greater than %s.',
 		rangeOverflow  : 'The value must be equal to or less than %s.',
 		stepMismatch   : 'The value has a step mismatch; it must be a certain number multiples of %s from %s.',
 		tooLong        : 'The value is too long. The field may have a maximum of %s characters but you supplied %s. Note that each line-break counts as two characters.',
-		patternMismatch: 'The value is not in the format required.'
+		patternMismatch: 'Please match the requested format.'
 	},
 	
 	valueToWF2Type : function(value, type){
@@ -2222,6 +2311,13 @@ $wf2 = {
 		//show contextual help message
 		var msg = document.createElement('div');
 		msg.className = 'wf2_errorMsg';
+		
+		/* Let's put in a container in here so IE9- can put a gradient filter in here. */
+		var msgContainer = document.createElement('div');
+		msgContainer.className = 'wf2_errorMsgContainer';
+		msg.appendChild(msgContainer);
+		
+		
 		//msg.title = "Close";
 		msg.id = (target.id || target.name) + '_wf2_errorMsg'; //QUESTION: does this work for MSIE?
 		msg.onmousedown = function(){
@@ -2233,27 +2329,29 @@ $wf2 = {
 		var isDateTimeRelated = (type == 'datetime' || type == 'datetime-local' || type == 'time' || type == 'date' || type == 'month' || type == 'week');
 
 		var ol = document.createElement('ol');
-		if(target.validity.valueMissing)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.valueMissing));
-		if(target.validity.typeMismatch)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.typeMismatch.replace(/%s/, type)));
-		if(target.validity.rangeUnderflow)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeUnderflow.replace(/%s/, $wf2.valueToWF2Type(target.min, type))));
-		if(target.validity.rangeOverflow)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeOverflow.replace(/%s/, $wf2.valueToWF2Type(target.max, type))));
-		if(target.validity.stepMismatch)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.stepMismatch.replace(/%s/, target.step + ($wf2.stepUnits[type] ? ' ' + $wf2.stepUnits[type] + '(s)' : '')).replace(/%s/, $wf2.valueToWF2Type(target.wf2StepDatum, type))));
-		if(target.validity.tooLong)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.tooLong.replace(/%s/, target.maxLength).replace(/%s/, target.wf2ValueLength ? target.wf2ValueLength : target.value.length)));
-		if(target.validity.patternMismatch)
-			ol.appendChild($wf2.createLI($wf2.invalidMessages.patternMismatch.replace(/%s/, target.title ? target.title : ' "' + target.getAttribute('pattern') + '"')));
-		if(target.validity.customError)
+		if(target.validity.customError) {
 			ol.appendChild($wf2.createLI(target.validationMessage));
+		} else {
+			if(target.validity.valueMissing)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.valueMissing));
+			if(target.validity.typeMismatch)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.typeMismatch.replace(/%s/, type)));
+			if(target.validity.rangeUnderflow)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeUnderflow.replace(/%s/, $wf2.valueToWF2Type(target.min, type))));
+			if(target.validity.rangeOverflow)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.rangeOverflow.replace(/%s/, $wf2.valueToWF2Type(target.max, type))));
+			if(target.validity.stepMismatch)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.stepMismatch.replace(/%s/, target.step + ($wf2.stepUnits[type] ? ' ' + $wf2.stepUnits[type] + '(s)' : '')).replace(/%s/, $wf2.valueToWF2Type(target.wf2StepDatum, type))));
+			if(target.validity.tooLong)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.tooLong.replace(/%s/, target.maxLength).replace(/%s/, target.wf2ValueLength ? target.wf2ValueLength : target.value.length)));
+			if(target.validity.patternMismatch)
+				ol.appendChild($wf2.createLI($wf2.invalidMessages.patternMismatch.replace(/%s/, target.title ? target.title : ' "' + target.getAttribute('pattern') + '"')));
+		}
 		
 		if(ol.childNodes.length == 1)
 			ol.className = 'single';
 		
-		msg.appendChild(ol);
+		msgContainer.appendChild(ol);
 		////remove existing error message
 		//if(document.getElementById(msg.id))
 		//	document.documentElement.removeChild(document.getElementById(msg.id));
@@ -2302,23 +2400,34 @@ $wf2 = {
 		//	target.form[target.name].wf2HasInvalidIndicator = true;
 		//	console.info('set')
 		//}
-		if(!target.className.match(/\bwf2_invalid\b/))
-			target.className += " wf2_invalid";
+		/* if(!target.className.match(/\bwf2_invalid\b/))
+			target.className += " wf2_invalid"; */
+		$wf2.css.addClass(target, 'wf2_invalid');
 			
 		if($wf2.indicatorIntervalId == null){
 			//var i = $wf2.invalidIndicators.length - 1;
 			$wf2.indicatorIntervalId = setInterval(function(){
 				var invalidIndicator;
 				for(var i = 0; invalidIndicator = $wf2.invalidIndicators[i]; i++){
+					
+					if (!$wf2.css.isMemberOfClass(invalidIndicator.target, 'wf2_invalid')) {
+						$wf2.css.addClass(invalidIndicator.target, 'wf2_invalid')
+					} else {
+						$wf2.css.removeClass(invalidIndicator.target, 'wf2_invalid');
+					}
+					
+					
+					/* 
 					if(!invalidIndicator.target.className.match(/\bwf2_invalid\b/)){
 						invalidIndicator.target.className += " wf2_invalid";
 					}
 					else {
 						invalidIndicator.target.className = invalidIndicator.target.className.replace(/\s?wf2_invalid/, "");
-					}
+					} */
 				}
 				
 			}, 500);
+			return;
 			// call routines other libraries have set to be run before
 			// validation.
 			setTimeout(function() {
@@ -2343,9 +2452,9 @@ $wf2 = {
 				invalidIndicator.errorMsg.parentNode.removeChild(invalidIndicator.errorMsg);
 			//clearInterval(insts[0].intervalId);
 			var target = invalidIndicator.target;
-			//if(target.form && target.form[target.name])
-			//	target.form[target.name].wf2HasInvalidIndicator = false;
-			target.className = target.className.replace(/\s?wf2_invalid/, ""); //([^\b]\s)?
+			
+			// Removed by ZOLTAN.
+			// target.className = target.className.replace(/\s?wf2_invalid/, ""); //([^\b]\s)?
 			$wf2.invalidIndicators.shift();
 		}
 		
@@ -2410,6 +2519,7 @@ $wf2 = {
 				//	  : document.createElement(node.nodeName);
 						
 				for(i = 0; attr = node.attributes[i]; i++){
+					
 					//MSIE ISSUE: Custom attributes specified do not have .specified property set to true?
 					//ISSUE: VALUE IS REPEATED IN MSIE WHEN VALUE ATTRIBUTE SET?
 					//if(attr.specified || node.getAttribute(attr.nodeName)) //$wf2.cloneNode_customAttrs[attr.nodeName] || 
@@ -2423,6 +2533,7 @@ $wf2 = {
 								(!isTemplate || (rtNestedDepth > 1 || !$wf2.cloneNode_rtEventHandlerAttrs[attr.name])) // && 
 							))
 					{
+						
 						//MSIE BUG: when button[type=add|remove|move-up|move-down], then (attr.nodeValue and attr.value == 'button') but node.getAttribute(attr.nodeName) == 'add|remove|move-up|move-down' (as desired)
 						
 						//clone and process an event handler property (attribute);
@@ -2438,6 +2549,7 @@ $wf2 = {
 							attrValue = (processAttr ? processAttr(attrValue) : attrValue);
 							clone.setAttribute(attr.name, attrValue);
 						}
+						//console.log(StringHelpers.sprintf("AFTER attr: %s val: %s (%s)", attr.name, attr.value, processAttr(attrValue)))
 					}
 				}
 				//MSIE BUG: setAttribute('class') creates duplicate value attribute in MSIE; 
@@ -2905,6 +3017,90 @@ $wf2 = {
 		//};
 	
 		return err;
+	},
+	
+	css: new function () {
+		var me = this;
+		
+		var blankRe = new RegExp('\\s');
+
+		/**
+		 * Generates a regular expression string that can be used to detect a class name
+		 * in a tag's class attribute.  It is used by a few methods, so I 
+		 * centralized it.
+		 * 
+		 * @param {String} className - a name of a CSS class.
+		 */
+		
+		function getClassReString(className) {
+			return '\\s'+className+'\\s|^' + className + '\\s|\\s' + className + '$|' + '^' + className +'$';
+		}
+		
+		function getClassPrefixReString(className) {
+			return '\\s'+className+'-[0-9a-zA-Z_]+\\s|^' + className + '[0-9a-zA-Z_]+\\s|\\s' + className + '[0-9a-zA-Z_]+$|' + '^' + className +'[0-9a-zA-Z_]+$';
+		}
+		
+		
+		/**
+		 * Make an HTML object be a member of a certain class.
+		 * 
+		 * @param {Object} obj - an HTML object
+		 * @param {String} className - a CSS class name.
+		 */
+		me.addClass = function (obj, className) {
+			
+			if (blankRe.test(className)) {
+				return;
+			}
+			
+			// only add class if the object is not a member of it yet.
+			if (!me.isMemberOfClass(obj, className)) {
+				obj.className += " " + className;
+			}
+			
+		}
+		
+		/**
+		 * Make an HTML object *not* be a member of a certain class.
+		 * 
+		 * @param {Object} obj - an HTML object
+		 * @param {Object} className - a CSS class name.
+		 */
+		me.removeClass = function (obj, className) {
+			
+			if (blankRe.test(className)) {
+				return; 
+			}
+			
+			
+			var re = new RegExp(getClassReString(className) , "g");
+			
+			var oldClassName = obj.className;
+		
+		
+			if (obj.className) {
+				obj.className = oldClassName.replace(re, ' ');
+			}
+		
+			
+		}
+		
+		/**
+		 * Determines if an HTML object is a member of a specific class.
+		 * @param {Object} obj - an HTML object.
+		 * @param {Object} className - the CSS class name.
+		 */
+		me.isMemberOfClass = function (obj, className) {
+			
+			if (blankRe.test(className))
+				return false;
+			
+			var re = new RegExp(getClassReString(className) , "g");
+		
+			return (re.test(obj.className));
+		
+		
+		}
 	}
 }; //End $wf2 = {
 
diff --git a/tests/html5Widgets/24ways.org/amex.gif b/tests/html5Forms/24ways.org/amex.gif
similarity index 100%
rename from tests/html5Widgets/24ways.org/amex.gif
rename to tests/html5Forms/24ways.org/amex.gif
diff --git a/tests/html5Widgets/24ways.org/index.html b/tests/html5Forms/24ways.org/index.html
similarity index 86%
rename from tests/html5Widgets/24ways.org/index.html
rename to tests/html5Forms/24ways.org/index.html
index 851ad12..6021d18 100644
--- a/tests/html5Widgets/24ways.org/index.html
+++ b/tests/html5Forms/24ways.org/index.html
@@ -13,19 +13,15 @@
 		<!-- This CSS file is not necessary to use html5Widgets -->
 		<link type="text/css" rel="stylesheet" href="../../../shared/css/useragentmanExample.css">
 		
-		<script type="text/javascript" src="../../../shared/js/EventHelpers.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
-		<script type="text/javascript" src="../../../shared/js/weston.ruter.net/webforms2/webforms2.js">
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../shared/js/html5Forms.js" data-webforms2-support="validation,placeholder" data-webforms2-force-js-validation="true">
 		</script>
 		
 		
-		<script type="text/javascript" src="../../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		
-		<script type="text/javascript" src="../../../shared/js/html5Widgets.js">
-		</script>
-		
 		
 			
 	</head>
diff --git a/tests/html5Widgets/24ways.org/mastercard.gif b/tests/html5Forms/24ways.org/mastercard.gif
similarity index 100%
rename from tests/html5Widgets/24ways.org/mastercard.gif
rename to tests/html5Forms/24ways.org/mastercard.gif
diff --git a/tests/html5Widgets/24ways.org/style.css b/tests/html5Forms/24ways.org/style.css
similarity index 100%
rename from tests/html5Widgets/24ways.org/style.css
rename to tests/html5Forms/24ways.org/style.css
diff --git a/tests/html5Widgets/24ways.org/visa.gif b/tests/html5Forms/24ways.org/visa.gif
similarity index 100%
rename from tests/html5Widgets/24ways.org/visa.gif
rename to tests/html5Forms/24ways.org/visa.gif
diff --git a/tests/html5Widgets/CHANGELOG b/tests/html5Forms/CHANGELOG
similarity index 100%
rename from tests/html5Widgets/CHANGELOG
rename to tests/html5Forms/CHANGELOG
diff --git a/tests/html5Widgets/autofocus.html b/tests/html5Forms/autofocus.html
similarity index 83%
rename from tests/html5Widgets/autofocus.html
rename to tests/html5Forms/autofocus.html
index 6b44c83..aee41cc 100644
--- a/tests/html5Widgets/autofocus.html
+++ b/tests/html5Forms/autofocus.html
@@ -8,9 +8,16 @@
 		
 		<title>HTML5 autofocus Attribute Test</title>
 		
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
+		
 		<!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="autofocus" data-webforms2-force-js-validation="true">
 		</script>
+		 
+	
+		
 		
 	</head>
 	<body id="myExample">
@@ -23,7 +30,7 @@
 		</div>
 		
 		
-		<form>
+		<form action="/testForm.php">
 			<fieldset>
 			<legend>Personal Information</legend>
 		
diff --git a/tests/html5Widgets/bradshawenterprises.com/asterisk_orange.png b/tests/html5Forms/bradshawenterprises.com/asterisk_orange.png
similarity index 100%
rename from tests/html5Widgets/bradshawenterprises.com/asterisk_orange.png
rename to tests/html5Forms/bradshawenterprises.com/asterisk_orange.png
diff --git a/tests/html5Widgets/bradshawenterprises.com/cancel.png b/tests/html5Forms/bradshawenterprises.com/cancel.png
similarity index 100%
rename from tests/html5Widgets/bradshawenterprises.com/cancel.png
rename to tests/html5Forms/bradshawenterprises.com/cancel.png
diff --git a/tests/html5Widgets/bradshawenterprises.com/index.html b/tests/html5Forms/bradshawenterprises.com/index.html
similarity index 69%
rename from tests/html5Widgets/bradshawenterprises.com/index.html
rename to tests/html5Forms/bradshawenterprises.com/index.html
index fb9deaa..52dd16d 100644
--- a/tests/html5Widgets/bradshawenterprises.com/index.html
+++ b/tests/html5Forms/bradshawenterprises.com/index.html
@@ -34,7 +34,7 @@
 			font-size:20px;
 			width:300px;
 			min-height:30px;
-			display:block;
+			display:block;	
 			margin-bottom:16px;
 			margin-top:8px;
 			
@@ -44,11 +44,14 @@
 			
 			-webkit-transition: all 0.5s ease-in-out;
 			-moz-transition: all 0.5s ease-in-out;
+			-ms-transition: all 0.5s ease-in-out;
+			-o-transition: all 0.5s ease-in-out;
 			transition: all 0.5s ease-in-out;
 		}
 		
 		textarea {
 				min-height:200px;
+				overflow: hidden;
 		}
 
 		input:focus, textarea:focus {
@@ -58,25 +61,45 @@
 			
 			-webkit-transform: scale(1.05);
 			-moz-transform: scale(1.05);
+			-ms-transform: scale(1.05);
+			-o-transform: scale(1.05);
 			transform: scale(1.05);
 		}
 		
+		input[type="number"]:focus {
+			-o-transform: none !important;
+		}
+		
 		/* The interesting bit */
 		
 		input:not(:focus), textarea:not(:focus) {
 			opacity:0.5;
 		}
 		
-		input:required, textarea:required {
-			background:url("asterisk_orange.png") no-repeat 280px 7px;						
+		input:required, textarea:required{
+			background:url("asterisk_orange.png") no-repeat right 7px;						
+		}
+		
+		[required] {
+			background:url("asterisk_orange.png") no-repeat right 7px;		
 		}
 
 		input:valid, textarea:valid {
-			background:url("tick.png") no-repeat 280px 5px;			
+			
+			/* Make this important if you want IE10 to work right. */
+			background:url("tick.png") no-repeat right 5px !important;			
+		}
+		
+		.wf2_valid {
+			background:url("tick.png") no-repeat right 5px;			
 		}		
 
 		input:focus:invalid, textarea:focus:invalid {
-			background:url("cancel.png") no-repeat 280px 7px;						
+			background:url("cancel.png") no-repeat right 7px;						
+		}
+		
+		input.wf2_invalid:focus {
+			background:url("cancel.png") no-repeat right 7px;						
 		}
 
 		input[type=submit] {
@@ -87,30 +110,21 @@
 		
 		</style>
 		
-		<link type="text/css" rel="stylesheet" href="../../../shared/css/slider.css">
+			<!-- What glues all the above together -->
 		
-		<!-- Needed for Range Element -->
-		<script type="text/javascript" src=
-		"../../../shared/js/frequency-decoder.com/slider.js">
+		<script type="text/javascript" src="../../../shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
 		<!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
+		<script type="text/javascript" src="../../../shared/js/html5Forms.js" data-webforms2-support="validation,number,range">
 		</script>
 		 
-		<!-- What glues all the above together -->
-		
-		<script type="text/javascript" src="../../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
+	
 		
 		
-		<script type="text/javascript" src="../../../shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="../../../shared/js/EventHelpers.js">
-		</script>
+	
 		
-		<script type="text/javascript" src="../../../shared/js/html5Widgets.js">
-		</script>
+		<!--[if (gt IE 9) ]> <script>alert('x')</script><![endif]-->
 		
 	</head>
 	<body>
@@ -133,7 +147,7 @@ <h1>HTML5 Form Demo</h1>
 		<input type="url" name="website" required placeholder="http://www.example.com" />
 
 		<label for="number">Number:</label> 
-		<input type="number" name="number" min="0" max="10" step="2" required placeholder="Even num < 10">
+		<input type="number" name="number" min="0" max="20" step="3" required placeholder="Even num < 10">
 
 		<label for="range">Range:</label> 
 		<input type="range" name="range" min="0" max="10" step="2" />
diff --git a/tests/html5Widgets/bradshawenterprises.com/tick.png b/tests/html5Forms/bradshawenterprises.com/tick.png
similarity index 100%
rename from tests/html5Widgets/bradshawenterprises.com/tick.png
rename to tests/html5Forms/bradshawenterprises.com/tick.png
diff --git a/tests/html5Widgets/brucelawson.co.uk/index.html b/tests/html5Forms/brucelawson.co.uk/index.html
similarity index 73%
rename from tests/html5Widgets/brucelawson.co.uk/index.html
rename to tests/html5Forms/brucelawson.co.uk/index.html
index d010ff7..245cd7b 100644
--- a/tests/html5Widgets/brucelawson.co.uk/index.html
+++ b/tests/html5Forms/brucelawson.co.uk/index.html
@@ -47,45 +47,13 @@
 }
 </style>
 
-		<link type="text/css" rel="stylesheet" href="../../../shared/css/slider.css">
-		<link type="text/css" rel="stylesheet" href="css/form.css" />
-		<link type="text/css" rel="stylesheet" href="../../../shared/js/jscalendar-1.0/calendar-win2k-1.css" />
-		
-		<!--[if lte IE 6]>
-        <link type="text/css" rel="stylesheet" href="../../../shared/css/slider_ie.css" />
-        <![endif]-->
-		
-		
-		<script type="text/javascript" src="../../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		<script type="text/javascript" src="../../../shared/js/html5.js">
-		</script>
-		<script type="text/javascript" src="../../../shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="../../../shared/js/EventHelpers.js">
-		</script>
-		
-		
-		
-		<!-- replacements for html5 tags -->
-		<script type="text/javascript" src=
-		"../../../shared/js/frequency-decoder.com/slider.js">
-		</script>
-		
-		<script type="text/javascript" src="../../../shared/js/jscolor/jscolor.js">
-		</script>
-		
-		<script type="text/javascript" src="../../../shared/js/jscalendar-1.0/calendar.js"></script>
-		<script type="text/javascript" src="../../../shared/js/jscalendar-1.0/lang/calendar-en.js"></script>
-		<script type="text/javascript" src="../../../shared/js/jscalendar-1.0/calendar-setup.js"></script>
+<!-- Needed for Forms Feature Detection -->
+<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+</script>
 
-         
-	<script type="text/javascript" src="../../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
-	</script>
-	
-	
-	<script type="text/javascript" src="../../../shared/js/html5Widgets.js">
-	</script>
+<!-- Needed for Validation --> 
+<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="all" >
+</script>
 	
 
 
@@ -95,7 +63,7 @@ <h1><abbr>HTML</abbr> 5 Forms  Demo</h1>
 
 <p>A word on validation. There is a bug in the <abbr>HTML</abbr> 5 validator that protests at my use of <code>datalist</code>. It's not a bug in my code. On the <code>output</code> element, I'm telling it to update everytime the slider input is changed, via <code>onforminput</code> which hasn't yet been formally added to the spec or the validator.</p>
 <p><strong>Fields with red borders are required.</strong></p>
-<form>
+<form action="http://www.useragentman.com/testForm.php">
     <!-- entry end -->
 
     <div class="entry">
diff --git a/tests/html5Widgets/color.html b/tests/html5Forms/color.html
similarity index 73%
rename from tests/html5Widgets/color.html
rename to tests/html5Forms/color.html
index 261bbc7..7cd0cdb 100644
--- a/tests/html5Widgets/color.html
+++ b/tests/html5Forms/color.html
@@ -19,23 +19,12 @@
 		
 		
 		
-		<!-- Needed for Color Element -->
-		<script type="text/javascript" src="../../shared/js/jscolor/jscolor.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
-		
-		<!-- What glues all the above together -->
-		
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		
-		<script type="text/javascript" src="../../shared/js/html5.js">
-		</script>
-		
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
-		</script>
-		
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="color" data-webforms2-force-js-validation="true">
 		</script>
 		
 	
@@ -50,7 +39,7 @@
 			<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article.</a></p>
     	</div>
 		
-        <form method="get" action="result.html"  >
+        <form method="get" action="http://www.useragentman.com/testForm.php"  >
         	<fieldset>
 				<legend>Fashion Profile</legend>
             <table class="formTable">
diff --git a/tests/html5Widgets/css/form.css b/tests/html5Forms/css/basicForm.css
similarity index 50%
rename from tests/html5Widgets/css/form.css
rename to tests/html5Forms/css/basicForm.css
index e5daf5e..1db0fe1 100644
--- a/tests/html5Widgets/css/form.css
+++ b/tests/html5Forms/css/basicForm.css
@@ -1,78 +1,48 @@
-@import url("/shared/css/useragentmanExample.css");
-
-body {
-	font-family: "Arial", sans-serif;
-}
-
-table.formTable {
-	
-	width: 40em;
-	margin: 0 auto;
-	overflow: none;
-}
-
-table.formTable input, table.formTable .description {
-	width: 15em;	
-}
-
-table.formTable input.range {
-	
-	width: 11em !important;
-}
-
-output.withRange {
-	display: block;
-	float: left;
-	margin-right: 0em;
-	width: 3em;
-	
-}
-
-table.formTable th, table.formTable td {
-	padding: 0.4em 0.1em;
-	vertical-align: top;	
-}
-
-table.formTable th {
-	text-align: right;
-	width: 20em;
-}
-
-table.formTable .description {
-	color: #999999;
-	font-size: 0.8em;
-	text-align: justify;
-}
-
-table.formTable input.check {
-	width: auto;
-}
-
-input[required], select[required] {
-	background: #ffffee url("../images/asterix.gif")  no-repeat left 2px !important;
-	padding-left: 1.5em;
-	width: 13.5em !important;
-}
-
-input[type="radio"], input[type="checkbox"] {
-	background-image: none !important;
-	padding-left: 0;
-}
-
-select[required] {
-	width: 15.2em !important;
-}
-
-input[type="radio"], input[type="checkbox"] {
-	width: auto !important;
-}
-
-
-input:invalid {
-		
-}
-
-table.formTable input[type="submit"] {
-	width: auto;	
-}
-
+
+body {
+	font-family: "Arial", sans-serif;
+}
+
+table.formTable {
+	
+	width: 40em;
+	margin: 0 auto;
+	overflow: none;
+}
+
+table.formTable input, table.formTable .description {
+	width: 15em;	
+}
+
+table.formTable input.range {
+	
+	width: 11em !important;
+}
+
+output.withRange {
+	display: block;
+	float: left;
+	margin-right: 0em;
+	width: 3em;
+	
+}
+
+table.formTable th, table.formTable td {
+	padding: 0.4em 0.1em;
+	vertical-align: top;	
+}
+
+table.formTable th {
+	text-align: right;
+	width: 20em;
+}
+
+table.formTable .description {
+	color: #999999;
+	font-size: 0.8em;
+	text-align: justify;
+}
+
+table.formTable input.check {
+	width: auto;
+}
\ No newline at end of file
diff --git a/tests/html5Forms/css/form.css b/tests/html5Forms/css/form.css
new file mode 100644
index 0000000..a0aa0ac
--- /dev/null
+++ b/tests/html5Forms/css/form.css
@@ -0,0 +1,31 @@
+@import url("http://www.useragentman.com/shared/css/useragentmanExample.css");
+@import url("basicForm.css");
+
+input[required], select[required] {
+	background: #ffffee url("../images/asterix.gif")  no-repeat left 2px !important;
+	padding-left: 1.5em;
+	width: 13.5em !important;
+}
+
+input[type="radio"], input[type="checkbox"] {
+	background-image: none !important;
+	padding-left: 0;
+}
+
+select[required] {
+	width: 15.2em !important;
+}
+
+input[type="radio"], input[type="checkbox"] {
+	width: auto !important;
+}
+
+
+input:invalid {
+		
+}
+
+table.formTable input[type="submit"] {
+	width: auto;	
+}
+
diff --git a/tests/html5Widgets/dateTime.html b/tests/html5Forms/dateTime.html
similarity index 67%
rename from tests/html5Widgets/dateTime.html
rename to tests/html5Forms/dateTime.html
index 862dfcf..7b0ff19 100644
--- a/tests/html5Widgets/dateTime.html
+++ b/tests/html5Forms/dateTime.html
@@ -12,43 +12,16 @@
 		
 		
        
-		<link type="text/css" rel="stylesheet" href="../../shared/js/jscalendar-1.0/calendar-win2k-1.css" />
-		<link type="text/css" rel="stylesheet" href="css/form.css" />
-		
-		
-		<!-- These style fixes are needed for IE6 -->
-		<!--[if lte IE 6]>
-        <link type="text/css" rel="stylesheet" href="../../shared/css/slider_ie.css" />
-		<style type="text/css">
-		output {
-			display: block;
-			position: absolute;
-			margin-left: 11em;
-			margin-top: -1.2em;
-		}
-		</style>
 		
-        <![endif]-->
-		
-		<!-- Needed for Date/Time Elements -->
-		<script type="text/javascript" src="../../shared/js/jscalendar-1.0/calendar.js"></script>
-		<script type="text/javascript" src="../../shared/js/jscalendar-1.0/lang/calendar-en.js"></script>
-		<script type="text/javascript" src="../../shared/js/jscalendar-1.0/calendar-setup.js"></script>
-
-        <!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
-		</script>
-		
-		<!-- What glues all the above together -->
-		
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
+		<link type="text/css" rel="stylesheet" href="css/form.css" />
 		
 		
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
-		
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
+		 
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="date" data-webforms2-force-js-validation="true" data-lang="qq">
 		</script>
 		
 	
@@ -59,13 +32,13 @@
     <body id="myExample" class="html5Widgets-debug">
     	<div id="exampleBlurb">
     		<p>The following shows the various HTML5 date/time widgets in action.
-			Note that at the time of this writing, Opera is the only browser
+			Note that at the time of this writing, Opera and some Webkit browsers are the only browser
 			that renders the calendars natively - all the other browsers
 			require <code>html5Widgets</code>.
 			<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article.</a></p>
     	</div>
 		
-        <form method="get" action="result.html">
+        <form method="get" action="http://www.useragentman.com/testForm.php">
         	<fieldset>
 				<legend>Internet Explorer 6 Retirement Timeline</legend>
 				
diff --git a/tests/html5Widgets/dev.opera.com/index.html b/tests/html5Forms/dev.opera.com/index.html
similarity index 83%
rename from tests/html5Widgets/dev.opera.com/index.html
rename to tests/html5Forms/dev.opera.com/index.html
index 01ffec0..e88a845 100644
--- a/tests/html5Widgets/dev.opera.com/index.html
+++ b/tests/html5Forms/dev.opera.com/index.html
@@ -12,9 +12,11 @@
   <!-- This CSS file is not necessary to use html5Widgets -->
 		<link type="text/css" rel="stylesheet" href="../../../shared/css/useragentmanExample.css">
           <!-- Needed for Validation --> 
-		  <script type="text/javascript" src="../../../shared/js/EventHelpers.js">
+		<script type="text/javascript" src="../../../shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
-		<script type="text/javascript" src="../../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
+		
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../../shared/js/html5Forms.js" data-webforms2-support="validation">
 		</script>
  </head>
  <body>
@@ -39,12 +41,12 @@ <h1>Examples for the article "Improve your forms using HTML5!"</h1>
 	   your forms using HTML5!</a> Have fun! (To play with the examples you need to
 	   use <a href="http://www.opera.com/download/">Opera 9 or newer</a>.</p>
 	  <p>The "search" control below should be focused:</p>
-	  <form>
+	  <form action="http://www.useragentman.com/testForm.php">
 	   <p><label>Search: <input autofocus name=search></label></p>
 	   <p><input type=submit value=Go!></p>
 	  </form>
 	  <p>The control below can be used to test "validation" of form controls:</p>
-	  <form id="validation">
+	  <form id="validation" action="http://www.useragentman.com/testForm.php">
 	   <p><label>Name: <input required name=name></label></p>
 	   <p><label>E-mail: <input type=email required name=email></label></p>
 	   <p><label>URL: <input type=url name=url></label></p>
diff --git a/tests/html5Forms/errorMessageStyling.html b/tests/html5Forms/errorMessageStyling.html
new file mode 100644
index 0000000..c47907a
--- /dev/null
+++ b/tests/html5Forms/errorMessageStyling.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		
+		<link type="text/css" rel="stylesheet" href="css/form.css" />
+		
+		<style type="text/css">
+		<!--
+		
+		/*
+		 * Styling the "Full Name" error message.
+		 */
+		
+		/*
+		 *  The background color of the main box 
+		 */
+		
+		/* Webkit */
+		input[name="fullName"]::-webkit-validation-bubble-message {
+			color: green !important;
+			background: white;
+			border: 1px solid black;
+			padding: 18px;
+			
+		}
+		
+		input[name="fullName"]::-webkit-validation-bubble-icon {
+			display: none;
+		}
+		
+		/* Polyfill */
+		#fullName_wf2_errorMsg {
+			color: green !important;
+			background: white;
+		}
+		
+		/* Needed for IE to get rid of gradient background, or to replace it with another gradient */
+		#fullName_wf2_errorMsg .wf2_errorMsgContainer {
+			filter: none !important;
+		}
+		
+		
+		/*
+		 * Step 2: The arrow
+		 */
+		
+		[name="fullName"]::-webkit-validation-bubble-arrow {
+			background: white;
+		    border: solid black 1px;
+		}
+		
+		/* Polyfill */
+		#fullName_wf2_errorMsg:before {
+			/* By default, the image is 29x15, but you can change it and position it with CSS */
+			background: url('images/whiteValidationPointer.png');
+		}
+		
+		#companyName_wf2_errorMsg {
+			color: yellow !important;
+		}
+		
+		
+		-->
+		</style>
+		<script type="text/javascript" src="../../shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
+		
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../shared/js/html5Forms.js" data-webforms2-support="validation" data-webforms2-force-js-validation="true">
+		</script>
+		
+		
+		
+		<title>HTML5 placeholder Attribute Test</title>
+		
+		
+		
+	</head>
+	<body id="myExample">
+		<div id="exampleBlurb">
+		<p>
+				This is an example of a HTML5 form which has a different error message style for each of its form <elements class=""></elements>
+					<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article </a>
+			</p>
+		</div>
+		
+		
+		<form  action="http://www.useragentman.com/testForm.php" data-webforms2-force-js-validation="true" >
+			<fieldset>
+				<legend>Personal Information</legend>
+		
+				<p>It is important you fill out <strong>all</strong> of the information in this form.</p>
+				
+			<table class="formTable">
+				<tr>
+					<th>Full Name :</th>
+					<td><input type="text" name="fullName" value="" required="required" placeholder="Required information" 
+						oninvalid="this.setCustomValidity('Yo, Bro! You forgot to fill out this field!')" 
+						onkeydown="this.setCustomValidity('')"/>
+					<div class="description"></div>
+					</td>
+				</tr>
+				
+				<tr>
+					<th>Company Name :</th>
+					<td><input type="text" name="companyName" required="required" value="" 
+						oninvalid="this.setCustomValidity('Don\'t forget this field either, Holmes!')"
+						onkeydown="this.setCustomValidity('')"
+						 />
+					<div class="description"></div>
+					</td>
+				</tr>
+				
+				
+				<tr>
+					<td></td>
+					<td><input type="submit" value="Submit Information"/></td>
+				</tr>
+			</table>
+			</fieldset>
+		</form>
+	</body>
+</html>
diff --git a/tests/html5Widgets/customValidity2.html b/tests/html5Forms/example.html
similarity index 75%
rename from tests/html5Widgets/customValidity2.html
rename to tests/html5Forms/example.html
index c866c35..2c5794c 100644
--- a/tests/html5Widgets/customValidity2.html
+++ b/tests/html5Forms/example.html
@@ -8,20 +8,20 @@
         <title>html5Widgets Test Form</title>
 		
 		<!-- This CSS file is not necessary to use html5Widgets -->
-		<link type="text/css" rel="stylesheet" href="/shared/css/useragentmanExample.css">
+		<link type="text/css" rel="stylesheet" href="../../shared/css/useragentmanExample.css">
 		
 		
-        
 		<link type="text/css" rel="stylesheet" href="css/form.css" />
 		
 		
+       <!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
 		
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="all" data-webforms2-force-js-validation="true">
+		</script>
 		
-		
-		<script type="text/javascript" src="../../shared/js/dean.edward.name/html5-now/html5-now.js"></script>
-		
-		
-
     </head>
 
     <body id="myExample" class="html5Widgets-debug">
@@ -34,7 +34,7 @@
 			<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article </a></p>
     	</div>
 		
-        <form method="get" action="result.html" >
+        <form method="get" action="http://www.useragentman.com/testForm.php" >
         	
 			<fieldset>
 				<legend>HTML5Widgets Test Form</legend>
@@ -61,20 +61,20 @@
 						</td>
 					</tr>
 					
-	                    <tr>
-	                        <th>Age:</th>
-	
-	                        <td>
-	                        
-	                        <output class="withRange" onforminput="value = rangeEl.value" 
-								>-</output>	
-								
-							<input type="range"  name="rangeEl" value="" 
-	                        min="0" max="150" class="range" />
-							
+                    <tr>
+                        <th>Age:</th>
+
+                        <td>
+                        
+                        <output class="withRange" onforminput="this.value = parseInt(rangeEl.value)" 
+							>-</output>	
 							
-							</td>
-	                    </tr>
+						<input type="range"  name="rangeEl" value="" 
+                        min="0" max="150" class="range" />
+						
+						
+						</td>
+                    </tr>
 
                     
 
@@ -141,7 +141,8 @@
 					
 					<tr>
 						<th>Test validity</th>
-						<td><input type="text" id="validityTest" name="safasfas" value="" pattern="[0-9]*" required="required" placeholder="Required Field"  />
+						<td><input type="text" name="safasfas" value="" pattern="[0-9]*" required="required" placeholder="Required Field"
+							data-errormessage="You must enter a number here." />
 						<div class="description">To test the <strong>required</strong> and <strong>pattern</strong>
 						attributes, this field only accepts numbers.</div>
 						
@@ -155,7 +156,8 @@
 							in return for a free iPad.
 							<br />
 							<br />
-							<label><input type="checkbox" class="check" name="iAgree" value="yesDammitYes" required="required"  />I submit to my new evil overlord</label>
+							<label><input type="checkbox" class="check" name="iAgree" value="yesDammitYes" required="required"  
+								data-errormessage="Sorry, but you must submit to your new evil overlord in order to continue."/>I submit to my new evil overlord</label>
 							
 						
 						</td>
diff --git a/tests/html5Forms/images/asterisk_orange.png b/tests/html5Forms/images/asterisk_orange.png
new file mode 100644
index 0000000..1ebebde
Binary files /dev/null and b/tests/html5Forms/images/asterisk_orange.png differ
diff --git a/tests/html5Widgets/images/asterix.gif b/tests/html5Forms/images/asterix.gif
similarity index 100%
rename from tests/html5Widgets/images/asterix.gif
rename to tests/html5Forms/images/asterix.gif
diff --git a/tests/html5Forms/images/cancel.png b/tests/html5Forms/images/cancel.png
new file mode 100644
index 0000000..c149c2b
Binary files /dev/null and b/tests/html5Forms/images/cancel.png differ
diff --git a/tests/html5Forms/images/tick.png b/tests/html5Forms/images/tick.png
new file mode 100644
index 0000000..a9925a0
Binary files /dev/null and b/tests/html5Forms/images/tick.png differ
diff --git a/tests/html5Forms/images/whiteValidationPointer.png b/tests/html5Forms/images/whiteValidationPointer.png
new file mode 100644
index 0000000..294db42
Binary files /dev/null and b/tests/html5Forms/images/whiteValidationPointer.png differ
diff --git a/tests/html5Widgets/index.html b/tests/html5Forms/index.html
similarity index 79%
rename from tests/html5Widgets/index.html
rename to tests/html5Forms/index.html
index 594f895..f414422 100644
--- a/tests/html5Widgets/index.html
+++ b/tests/html5Forms/index.html
@@ -2,16 +2,16 @@
 <html lang="en">
     <head>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-        <title>HTML5 Widgets</title>
+        <title>HTML5Forms.js Test Cases</title>
 		<link rel="stylesheet" href="../../shared/css/useragentmanExample.css" type="text/css" media="all" />
     </head>
     <body id="myExample">
         <fieldset>
-        	<legend>HTML5 Form Examples</legend>
+        	<legend>HTML5Forms.js Test Cases</legend>
        
         <ul class="exampleList">
             <li>
-                <strong>My Examples that show html5Widgets and webforms2 in action:</strong>
+                <strong>My Examples that show html5Forms.js in action:</strong>
                 
 				<ul>
 					<li><a href="patternRequired.html"><code>required</code> and <code>pattern</code> validation</a></li>
@@ -20,9 +20,7 @@
 					<li><a href="placeholder.html"><code>placeholder</code> example</a></li>
 					<li><a href="range.html"><code>range</code> example</a></li>
 					<li><a href="datetime.html">the various <code>date</code> related widgets</a></li>
-					<li><a href="output.html"><code>output</code> tag with <code>onforminput</code> event</a></li>
-					<li><a href="outputWithOninput.html"><code>output</code> tag with <code>oninput</code> event</a></li>
-					<li><a href="outputWithBothOnforminputAndOninput.html"><code>output</code> tag with both <code>onforminput</code> and <code>oninput</code> events</a></li>
+						<li><a href="outputWithOninput.html"><code>output</code> tag with <code>oninput</code> event</a></li>
 					<li><a href="color.html"><code>color</code> example</a></li>
 					<li><a href="example.html">And now ... everything together.</a></li>
 				</ul>
diff --git a/tests/html5Widgets/miketaylr.com/index.html b/tests/html5Forms/miketaylr.com/index.html
similarity index 81%
rename from tests/html5Widgets/miketaylr.com/index.html
rename to tests/html5Forms/miketaylr.com/index.html
index ca20131..f836489 100644
--- a/tests/html5Widgets/miketaylr.com/index.html
+++ b/tests/html5Forms/miketaylr.com/index.html
@@ -19,43 +19,12 @@
     input:invalid {border:3px solid orange;}
   </style>
   
- 		<link type="text/css" rel="stylesheet" href="../../../shared/css/slider.css">
-		
-		<!--[if lte IE 6]>
-        <link type="text/css" rel="stylesheet" href="../../../shared/css/slider_ie.css" />
-        <![endif]-->
-		
-		<link type="text/css" rel="stylesheet" href="../../../shared/js/jscalendar-1.0/calendar-win2k-1.css" />
-		<link type="text/css" rel="stylesheet" href="css/form.css" />
-		
-		
-		<script type="text/javascript" src="../../../shared/js/html5.js">
+ 		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
-		<script type="text/javascript" src="../../../shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="../../../shared/js/EventHelpers.js">
-		</script>
-		
-		
-		<!-- replacements for html5 tags -->
-		<script type="text/javascript" src=
-		"../../../shared/js/frequency-decoder.com/slider.js">
-		</script>
-		
-		<script type="text/javascript" src="../../../shared/js/jscolor/jscolor.js">
-		</script>
-		
-		<script type="text/javascript" src="../../../shared/js/jscalendar-1.0/calendar.js"></script>
-		<script type="text/javascript" src="../../../shared/js/jscalendar-1.0/lang/calendar-en.js"></script>
-		<script type="text/javascript" src="../../../shared/js/jscalendar-1.0/calendar-setup.js"></script>
-
-         
-		<script type="text/javascript" src="../../../shared/js/jslog.js">
-		</script>  
 		
-		<script type="text/javascript" src="../../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>     
-		<script type="text/javascript" src="../../../shared/js/html5Widgets.js">
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="all">
 		</script>
   
   
@@ -81,7 +50,7 @@ <h1>Notes:</h1>
   </section>
   <section>
     <h1>Demo:</h1>
-    <form>
+    <form action="http://www.useragentman.com/testForm.php">
       <div>
         <label>Text:
           <input type="text" maxlength="6"/>
diff --git a/tests/html5Widgets/output.html b/tests/html5Forms/output.html
similarity index 63%
rename from tests/html5Widgets/output.html
rename to tests/html5Forms/output.html
index 04317ab..77f38f8 100644
--- a/tests/html5Widgets/output.html
+++ b/tests/html5Forms/output.html
@@ -11,28 +11,26 @@
 		
 		
 		
-		<!-- What powers html5Widgets -->
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/html5.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="output" data-webforms2-force-js-validation="true">
 		</script>
 		
 	</head>
 	<body id="myExample" class="html5Widgets-debug">
     	<div id="exampleBlurb">
     		<p>The following is an example of using the HTML5 <code>output</code> tag with the 
-			deprecated <code>onforminput</code> event to do
+			deprecated <code>oninput</code> event to do
 			some calculations on the data within the form.  <a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article.</a></p>
     	</div>
 		
-        <form method="get" action="result.html"  >
+        <form method="get" action="http://www.useragentman.com/testForm.php" oninput="
+        	document.getElementById('taxes').innerHTML = Math.round(price.value * 0.15 * 100) / 100;
+        	document.getElementById('total').innerHTML = Math.round(price.value * 1.15 * 100) / 100
+        " >
         	
 			<fieldset>
 				<legend>Money You Owe</legend>
@@ -50,14 +48,14 @@
 						
 						<tr>
 							<th>Taxes:</th>
-							<td><output name="taxes" onforminput="this.value = Math.round(price.value * 0.15 * 100) / 100" >0</output>
+							<td><output id="taxes" oninput="this.value = Math.round(price.value * 0.15 * 100) / 100" >0</output>
 							<div class="description">This is how much you have to give to The Man, whether you like it or not.</div>
 							</td>
 						</tr>
 						
 						<tr>
 							<th>Total:</th>
-							<td><output name="total" onforminput="this.value = Math.round(price.value * 1.15 * 100) / 100" >0</output>
+							<td><output id="total" oninput="this.value = Math.round(price.value * 1.15 * 100) / 100" >0</output>
 							<div class="description">This is how much you have to shell out in total.  Have a nice day!</div>
 							
 							</td>
diff --git a/tests/html5Widgets/outputWithBothOnforminputAndOninput.html b/tests/html5Forms/outputWithBothOnforminputAndOninput.html
similarity index 93%
rename from tests/html5Widgets/outputWithBothOnforminputAndOninput.html
rename to tests/html5Forms/outputWithBothOnforminputAndOninput.html
index 0675c26..e9a23be 100644
--- a/tests/html5Widgets/outputWithBothOnforminputAndOninput.html
+++ b/tests/html5Forms/outputWithBothOnforminputAndOninput.html
@@ -32,7 +32,7 @@
 			to it's form.   <a href="http://www.useragentman.com/blog/?p=3174">Back to the User Agent Man <code>oninput</code> article</a>.</p>
     	</div>
 		
-        <form method="get" action="result.html" 
+        <form method="get" action="http://www.useragentman.com/testForm.php" 
 			oninput="document.getElementById('output').innerHTML = 'oninput fired at ' + new Date().getTime();">
         		
 			<fieldset>
diff --git a/tests/html5Widgets/outputWithOnInput.html b/tests/html5Forms/outputWithOnInput.html
similarity index 79%
rename from tests/html5Widgets/outputWithOnInput.html
rename to tests/html5Forms/outputWithOnInput.html
index debbd35..51cb4f6 100644
--- a/tests/html5Widgets/outputWithOnInput.html
+++ b/tests/html5Forms/outputWithOnInput.html
@@ -12,17 +12,12 @@
 		
 		
 		
-		<!-- What powers html5Widgets -->
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/html5.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="output" data-webforms2-force-js-validation="true">
 		</script>
 		
 	</head>
@@ -32,7 +27,7 @@
 			some calculations on the data within the form.  It uses html5Widgets to fix IE9's slightly misbehaved implementation of <code>oninput</code>. <a href="http://www.useragentman.com/blog/?p=3174">Back to the User Agent Man <code>oninput</code> article</a>.</p>
     	</div>
 		
-        <form method="get" action="result.html" 
+        <form method="get" action="http://www.useragentman.com/testForm.php" 
 			oninput="document.getElementById('taxes').innerHTML = Math.round(price.value * 0.15 * 100) / 100;
 					 document.getElementById('total').innerHTML = Math.round(price.value * 1.15 * 100) / 100">
         	
diff --git a/tests/html5Widgets/patternRequired-styleError.html b/tests/html5Forms/patternRequired-styleError.html
similarity index 94%
rename from tests/html5Widgets/patternRequired-styleError.html
rename to tests/html5Forms/patternRequired-styleError.html
index 378e906..3dcc293 100644
--- a/tests/html5Widgets/patternRequired-styleError.html
+++ b/tests/html5Forms/patternRequired-styleError.html
@@ -40,7 +40,7 @@
 		beer when they would otherwise do without.</p>
 		
 		<p>Form fields labelled <img src="images/asterix.gif" alt="*"/> are mandatory</p>
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<table class="formTable">
 				<tr>
 					<th>Full Name: </th>
diff --git a/tests/html5Widgets/patternRequired.html b/tests/html5Forms/patternRequired.html
similarity index 79%
rename from tests/html5Widgets/patternRequired.html
rename to tests/html5Forms/patternRequired.html
index c866e5c..0fe1326 100644
--- a/tests/html5Widgets/patternRequired.html
+++ b/tests/html5Forms/patternRequired.html
@@ -9,8 +9,12 @@
 		<title>HTML5 pattern and required Attribute Test</title>
 		
 		
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
+		
 		<!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="validation">
 		</script>
 		
 	</head>
@@ -32,7 +36,7 @@
 		beer when they would otherwise do without.</p>
 		
 		<p>Form fields labelled <img src="images/asterix.gif" alt="*"/> are mandatory</p>
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<table class="formTable">
 				<tr>
 					<th>Full Name: </th>
@@ -54,7 +58,7 @@
 				<tr>
 					<th>Zip Code</th>
 					<td><input type="text" name="postalCode" value="" required="required" 
-						pattern="(\d{5}([\-]\d{4})?)"
+						pattern="(\d{5}([\-]\d{4})?)" data-errormessage="This must be a valid postal code."
 					/>
 					<div class="description">Please enter a valid American postal code. 
 					Valid format is <strong>nnnnn</strong> or <strong>nnnnn-nnnn</strong>
diff --git a/tests/html5Widgets/patternRequiredWithVisibleIf.html b/tests/html5Forms/patternRequiredWithVisibleIf.html
similarity index 88%
rename from tests/html5Widgets/patternRequiredWithVisibleIf.html
rename to tests/html5Forms/patternRequiredWithVisibleIf.html
index 20b6c70..57b427a 100644
--- a/tests/html5Widgets/patternRequiredWithVisibleIf.html
+++ b/tests/html5Forms/patternRequiredWithVisibleIf.html
@@ -13,8 +13,12 @@
 		<script type="text/javascript" src="../../shared/js/EventHelpers.js"></script>
 		<script type="text/javascript" src="../../shared/js/visibleIf.js"></script>
 		
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
+		
 		<!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="validation" data-webforms2-force-js-validation="true">
 		</script>
 		
 		
@@ -35,7 +39,7 @@
 		</div>
 		
 		
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<fieldset>
 			<legend>Personal Information</legend>
 			
diff --git a/tests/html5Widgets/placeholder.html b/tests/html5Forms/placeholder.html
similarity index 81%
rename from tests/html5Widgets/placeholder.html
rename to tests/html5Forms/placeholder.html
index bcb10ba..f74f39d 100644
--- a/tests/html5Widgets/placeholder.html
+++ b/tests/html5Forms/placeholder.html
@@ -8,20 +8,13 @@
 		
 		<title>HTML5 placeholder Attribute Test</title>
 		
-		<!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
-		</script>
-		
-		<!-- Need for placeholder -->
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/html5.js">
-		</script>
 		
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="validation, placeholder" data-webforms2-force-js-validation="true">
 		</script>
 		
 	</head>
@@ -36,7 +29,7 @@
 		</div>
 		
 		
-		<form>
+		<form action="http://www.useragentman.com/testForm.php">
 			<fieldset>
 				<legend>Personal Information</legend>
 		
diff --git a/tests/html5Widgets/range.html b/tests/html5Forms/range.html
similarity index 77%
rename from tests/html5Widgets/range.html
rename to tests/html5Forms/range.html
index 1ac5b1b..ea51a00 100644
--- a/tests/html5Widgets/range.html
+++ b/tests/html5Forms/range.html
@@ -8,28 +8,15 @@
 		
 		<title>HTML5 range input type</title>
 		
-		<!-- Needed for Range Element -->
-		<link type="text/css" rel="stylesheet" href="../../shared/css/slider.css">
-		<!--[if lte IE 6]>
-        <link type="text/css" rel="stylesheet" href="../../shared/css/slider_ie.css" />
-        <![endif]-->
-		<script type="text/javascript" src="../../shared/js/frequency-decoder.com/slider.js">
-		</script>
 		
 		
-		<!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
-		</script>
 		
-		<!-- Need for range -->
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
+		<!-- Needed for Forms Feature Detection -->
+		<script type="text/javascript" src="../../html5Forms/shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
 		</script>
 		
-		<script type="text/javascript" src="../../shared/js/html5.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js" >
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../html5Forms/shared/js/html5Forms.js" data-webforms2-support="validation,range" data-webforms2-force-js-validation="true">
 		</script>
 		
 	</head>
diff --git a/tests/html5Forms/styleValidation.html b/tests/html5Forms/styleValidation.html
new file mode 100644
index 0000000..7010f38
--- /dev/null
+++ b/tests/html5Forms/styleValidation.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta name="generator" content="HTML Tidy, see www.w3.org">
+        <meta http-equiv="Content-Type" content=
+        "text/html; utf-8">
+
+        <title>html5Widgets Test Form</title>
+		
+		<!-- This CSS file is not necessary to use html5Widgets -->
+		<link type="text/css" rel="stylesheet" href="../../shared/css/useragentmanExample.css">
+		
+		
+       
+		<link type="text/css" rel="stylesheet" href="css/form.css" />
+		
+		
+		
+		
+		
+
+        <!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2_src.js">
+		</script>
+		
+		<!-- What glues all the above together -->
+		
+		<script type="text/javascript" src="../../shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
+
+		<script type="text/javascript" src="../../shared/js/html5.js">
+		</script>
+		
+		
+		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
+		</script>
+		
+		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
+		</script>
+		
+	
+		
+
+    </head>
+
+    <body id="myExample" class="html5Widgets-debug">
+    	<div id="exampleBlurb">
+    		<p>The following shows a variety of HTML5 form elements, including 
+			<code>color</code>.  The form uses <code>HTML5Widgets</code> and
+			Weston Ruter's  <code>webforms2</code> to add HTML5 Forms support to 
+			browsers that don't currently support it.  Browsers that partially
+			support the specification will use native functionality where applicable.
+			<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article </a></p>
+
+    	</div>
+		
+        <form method="get" action="http://www.useragentman.com/testForm.php" >
+        	
+			<fieldset>
+				<legend>HTML5Widgets Test Form</legend>
+				<p>Form fields labelled <img src="images/asterix.gif" alt="*"/> are mandatory</p>
+            <table class="formTable">
+                <tbody>
+
+                	
+					
+					<tr>
+						<th>Test validity</th>
+						<td><input type="text" name="safasfas" value="" pattern="[0-9]*" required="required" placeholder="Required Field" />
+						<div class="description">To test the <strong>required</strong> and <strong>pattern</strong>
+						attributes, this field only accepts numbers.</div>
+
+						
+						</td>
+					</tr>
+					
+					<tr>
+						<th>Terms and Conditions:</th>
+						<td>
+							I promise to give my first born to The Evil Corporation
+							in return for a free iPad.
+							<br />
+							<br />
+							<label><input type="checkbox" class="check" name="iAgree" value="yesDammitYes" required="required"  />I submit to my new evil overlord</label>
+
+							
+						
+						</td>
+						
+					</tr>
+					<tr>
+						<th></th>
+						<td >
+							<input type="submit" name="submit me" value="Submit" />
+						</td>
+					</tr>
+					
+                </tbody>
+
+            </table>
+            </fieldset>
+        </form>
+		
+		<div id="supports">
+			
+		</div>
+    </body>
+</html>
+
diff --git a/tests/html5Forms/test.js b/tests/html5Forms/test.js
new file mode 100644
index 0000000..9682758
--- /dev/null
+++ b/tests/html5Forms/test.js
@@ -0,0 +1 @@
+alert('test')
diff --git a/tests/html5Forms/validityStyling.html b/tests/html5Forms/validityStyling.html
new file mode 100644
index 0000000..5d4d66f
--- /dev/null
+++ b/tests/html5Forms/validityStyling.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+		
+		<link type="text/css" rel="stylesheet" href="css/basicForm.css" />
+		
+		<style type="text/css">
+		<!--
+		
+		input:focus, textarea:focus {
+			-webkit-box-shadow:0 0 25px #ccc;
+			-moz-box-shadow:0 0 25px #ccc;
+			box-shadow:0 0 25px #ccc;
+			
+			-webkit-transform: scale(1.05);
+			-moz-transform: scale(1.05);
+			-ms-transform: scale(1.05);
+			-o-transform: scale(1.05);
+			transform: scale(1.05);
+		}
+		
+		input[type="number"]:focus {
+			-o-transform: none !important;
+		}
+		
+		/* The interesting bit */
+		
+		input:not(:focus), textarea:not(:focus) {
+			opacity:0.5;
+		}
+		
+		input:required, textarea:required{
+			background:url("images/asterisk_orange.png") no-repeat right 0px;						
+		}
+		
+		[required] {
+			background:url("images/asterisk_orange.png") no-repeat right 0px;		
+		}
+
+		input:valid, textarea:valid {
+			/* Make this important if you want IE10 to work right. */
+			background:url("images/tick.png") no-repeat right 0px !important;			
+		}
+		
+		.wf2_valid {
+			background:url("images/tick.png") no-repeat right 0px;			
+		}		
+
+		input:focus:invalid, textarea:focus:invalid {
+			background:url("images/cancel.png") no-repeat right 0px;						
+		}
+		
+		input.wf2_invalid:focus {
+			background:url("images/cancel.png") no-repeat right 0px;						
+		}
+
+		input[type=submit] {
+			padding:10px;
+			background:none !important;
+			opacity:1.0;
+		}
+		
+		-->
+		</style>
+		<script type="text/javascript" src="../../shared/js/modernizr.com/Modernizr-2.5.3.forms.js">
+		</script>
+		
+		<!-- Needed for Validation --> 
+		<script type="text/javascript" src="../../shared/js/html5Forms.js" data-webforms2-support="validation">
+		</script>
+		
+		
+		
+		<title>HTML5 placeholder Attribute Test</title>
+		
+		
+		
+	</head>
+	<body id="myExample">
+		<div id="exampleBlurb">
+		<p>
+				This is an example of a HTML5 form which has a different error message style for each of its form <elements class=""></elements>
+					<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article </a>
+			</p>
+		</div>
+		
+		
+		<form >
+			<fieldset>
+				<legend>Personal Information</legend>
+		
+				<p>It is important you fill out <strong>all</strong> of the information in this form.</p>
+				
+			<table class="formTable">
+				<tr>
+					<th>Full Name :</th>
+					<td><input type="text" name="fullName" value="" required="required" placeholder="Required information" 
+						oninvalid="this.setCustomValidity('Yo, Bro! You forgot to fill out this field!')" 
+						onkeydown="this.setCustomValidity('');"/>
+					<div class="description"></div>
+					</td>
+				</tr>
+				
+				<tr>
+					<th>Company Name :</th>
+					<td><input type="text" name="companyName" required="required" value="" 
+						oninvalid="this.setCustomValidity('Don\'t forget this field either, Holmes!')"
+						onkeydown="this.setCustomValidity('');"
+						 />
+					<div class="description"></div>
+					</td>
+				</tr>
+				
+				
+				
+				
+				<tr>
+					<td></td>
+					<td><input type="submit" value="Submit Information"/></td>
+				</tr>
+			</table>
+			</fieldset>
+		</form>
+	</body>
+</html>
diff --git a/tests/html5Widgets/customValidity.html b/tests/html5Widgets/customValidity.html
deleted file mode 100644
index 063dee9..0000000
--- a/tests/html5Widgets/customValidity.html
+++ /dev/null
@@ -1,234 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-    <head>
-        <meta name="generator" content="HTML Tidy, see www.w3.org">
-        <meta http-equiv="Content-Type" content=
-        "text/html; utf-8">
-
-        <title>html5Widgets Test Form</title>
-		
-		<!-- This CSS file is not necessary to use html5Widgets -->
-		<link type="text/css" rel="stylesheet" href="/shared/css/useragentmanExample.css">
-		
-		
-        <link type="text/css" rel="stylesheet" href="/shared/css/slider.css">
-		<link type="text/css" rel="stylesheet" href="/shared/js/jscalendar-1.0/calendar-win2k-1.css" />
-		<link type="text/css" rel="stylesheet" href="css/form.css" />
-		
-		
-		<!-- These style fixes are needed for IE6 -->
-		<!--[if lte IE 6]>
-        <link type="text/css" rel="stylesheet" href="/shared/css/slider_ie.css" />
-		<style type="text/css">
-		output {
-			display: block;
-			position: absolute;
-			margin-left: 11em;
-			margin-top: -1.2em;
-		}
-		</style>
-		
-        <![endif]-->
-		
-		<!-- Needed for Range Element -->
-		<script type="text/javascript" src=
-		"/shared/js/frequency-decoder.com/slider.js">
-		</script>
-		
-		<!-- Needed for Color Element -->
-		<script type="text/javascript" src="/shared/js/jscolor/jscolor.js">
-		</script>
-		
-		<!-- Needed for Date/Time Elements -->
-		<script type="text/javascript" src="/shared/js/jscalendar-1.0/calendar.js"></script>
-		<script type="text/javascript" src="/shared/js/jscalendar-1.0/lang/calendar-en.js"></script>
-		<script type="text/javascript" src="/shared/js/jscalendar-1.0/calendar-setup.js"></script>
-
-        <!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2-p.js">
-		</script>
-		
-		<!-- What glues all the above together -->
-		
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		<script type="text/javascript" src="/shared/js/html5.js">
-		</script>
-		
-		<script type="text/javascript" src="/shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="/shared/js/EventHelpers.js">
-		</script>
-		
-		<script type="text/javascript" src="/shared/js/html5Widgets.js">
-		</script>
-		
-	
-		<script type="text/javascript">
-			function setValidity(){
-				// test customValidity
-				document.getElementById('validityTest').setCustomValidity('This is only supposed to be number, fool!  Can\'t you read?');
-				
-			}
-			
-			EventHelpers.addPageLoadEvent('setValidity');
-		</script>
-		
-
-    </head>
-
-    <body id="myExample" class="html5Widgets-debug">
-    	<div id="exampleBlurb">
-    		<p>The following shows a variety of HTML5 form elements, including 
-			<code>color</code>.  The form uses <code>HTML5Widgets</code> and
-			Weston Ruter's  <code>webforms2</code> to add HTML5 Forms support to 
-			browsers that don't currently support it.  Browsers that partially
-			support the specification will use native functionality where applicable.
-			<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article </a></p>
-    	</div>
-		
-        <form method="get" action="result.html" >
-        	
-			<fieldset>
-				<legend>HTML5Widgets Test Form</legend>
-				<p>Form fields labelled <img src="images/asterix.gif" alt="*"/> are mandatory</p>
-            <table class="formTable">
-                <tbody>
-                	<tr>
-                		<th>Legal Name:</th>
-						<td><input type="text" name="name" value="" autofocus="autofocus" />
-						<div class="description">This field has focus when the page
-						first loads because it has it's <code>autofocus</code>
-						attribute set to <code>true</code>.
-						</td>
-					</tr>
-					
-                	<tr>
-                		<th>Company Name:</th>
-						<td><input type="text" name="placeholderEl" value=""
-						placeholder="Leave blank if unemployed" />
-						<div class="description">This field has it's 
-						<code>placeholder</code> attribute set to 
-						<code>"Leave blank if unemployed"</code>
-						
-						</td>
-					</tr>
-					
-                    <tr>
-                        <th>Age:</th>
-
-                        <td>
-                        
-                        <output class="withRange" onforminput="this.value = rangeEl.value" 
-							>-</output>	
-							
-						<input type="range"  name="rangeEl" value="" 
-                        min="0" max="150" class="range" />
-						
-						
-						</td>
-                    </tr>
-
-                    
-
-                    <tr>
-                        <th>Date/Time (Local)</th>
-
-                        <td><input type="datetime-local" name="DateTimeLocalTest" value=
-                        "">
-						<div class="description">The <code>datetime</code>,
-						<code>date</code>, <code>week</code> and <code>month</code>
-						input fields all show a calendar when clicked on.  When 
-						the user chooses a date, each input shows the date in
-						a slightly different format.
-						</div>
-						
-						</td>
-                    </tr>
-					
-					<tr>
-                        <th>Date/Time (UTC)</th>
-
-                        <td><input type="datetime" name="DateTimeTest" value=
-                        "">
-						<div class="description">The <code>datetime</code>,
-						<code>date</code>, <code>week</code> and <code>month</code>
-						input fields all show a calendar when clicked on.  When 
-						the user chooses a date, each input shows the date in
-						a slightly different format.
-						</div>
-						
-						</td>
-                    </tr>
-
-                    <tr>
-                        <th>Date</th>
-
-                        <td><input type="date" name="DateTest" value=
-                        ""></td>
-                    </tr>
-
-                    <tr>
-                        <th>Month</th>
-
-                        <td><input type="month" name="MonthTest" value=
-                        ""></td>
-                    </tr>
-
-                    <tr>
-                        <th>Week</th>
-
-                        <td><input type="week" name="WeekTest" value=
-                        ""></td>
-                    </tr>
-
-                  
-
-
-                    <tr>
-                        <th>Colour</th>
-
-                        <td><input type="color" name="ColorTest" value=
-                        "" ></td>
-                    </tr>
-					
-					<tr>
-						<th>Test validity</th>
-						<td><input type="text" id="validityTest" name="safasfas" value="" pattern="[0-9]*" required="required" placeholder="Required Field"  />
-						<div class="description">To test the <strong>required</strong> and <strong>pattern</strong>
-						attributes, this field only accepts numbers.</div>
-						
-						</td>
-					</tr>
-					
-					<tr>
-						<th>Terms and Conditions:</th>
-						<td>
-							I promise to give my first born to The Evil Corporation
-							in return for a free iPad.
-							<br />
-							<br />
-							<label><input type="checkbox" class="check" name="iAgree" value="yesDammitYes" required="required"  />I submit to my new evil overlord</label>
-							
-						
-						</td>
-						
-					</tr>
-					<tr>
-						<th></th>
-						<td >
-							<input type="submit" name="submit me" value="Submit" />
-						</td>
-					</tr>
-					
-                </tbody>
-            </table>
-            </fieldset>
-        </form>
-		
-		<div id="supports">
-			
-		</div>
-    </body>
-</html>
-
diff --git a/tests/html5Widgets/example.html b/tests/html5Widgets/example.html
deleted file mode 100644
index 72defb8..0000000
--- a/tests/html5Widgets/example.html
+++ /dev/null
@@ -1,225 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-    <head>
-        <meta name="generator" content="HTML Tidy, see www.w3.org">
-        <meta http-equiv="Content-Type" content=
-        "text/html; utf-8">
-
-        <title>html5Widgets Test Form</title>
-		
-		<!-- This CSS file is not necessary to use html5Widgets -->
-		<link type="text/css" rel="stylesheet" href="../../shared/css/useragentmanExample.css">
-		
-		
-        <link type="text/css" rel="stylesheet" href="../../shared/css/slider.css">
-		<link type="text/css" rel="stylesheet" href="../../shared/js/jscalendar-1.0/calendar-win2k-1.css" />
-		<link type="text/css" rel="stylesheet" href="css/form.css" />
-		
-		
-		<!-- These style fixes are needed for IE6 -->
-		<!--[if lte IE 6]>
-        <link type="text/css" rel="stylesheet" href="../../shared/css/slider_ie.css" />
-		<style type="text/css">
-		output {
-			display: block;
-			position: absolute;
-			margin-left: 11em;
-			margin-top: -1.2em;
-		}
-		</style>
-		
-        <![endif]-->
-		
-		<!-- Needed for Range Element -->
-		<script type="text/javascript" src=
-		"../../shared/js/frequency-decoder.com/slider.js">
-		</script>
-		
-		<!-- Needed for Color Element -->
-		<script type="text/javascript" src="../../shared/js/jscolor/jscolor.js">
-		</script>
-		
-		<!-- Needed for Date/Time Elements -->
-		<script type="text/javascript" src="../../shared/js/jscalendar-1.0/calendar.js"></script>
-		<script type="text/javascript" src="../../shared/js/jscalendar-1.0/lang/calendar-en.js"></script>
-		<script type="text/javascript" src="../../shared/js/jscalendar-1.0/calendar-setup.js"></script>
-
-        <!-- Needed for Validation --> 
-		<script type="text/javascript" src="../../shared/js/weston.ruter.net/webforms2/webforms2.js">
-		</script>
-		
-		<!-- What glues all the above together -->
-		
-		<script type="text/javascript" src="../../shared/js/modernizr.com/modernizr-1.5.min.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/html5.js">
-		</script>
-		
-		<script type="text/javascript" src="../../shared/js/Timer.js">
-		</script>
-		<script type="text/javascript" src="../../shared/js/EventHelpers.js">
-		</script>
-		
-		<script type="text/javascript" src="../../shared/js/html5Widgets.js">
-		</script>
-		
-	
-		
-
-    </head>
-
-    <body id="myExample" class="html5Widgets-debug">
-    	<div id="exampleBlurb">
-    		<p>The following shows a variety of HTML5 form elements, including 
-			<code>color</code>.  The form uses <code>HTML5Widgets</code> and
-			Weston Ruter's  <code>webforms2</code> to add HTML5 Forms support to 
-			browsers that don't currently support it.  Browsers that partially
-			support the specification will use native functionality where applicable.
-			<a href="http://www.useragentman.com/blog/?p=1110">Back to User Agent Man HTML5 Forms article </a></p>
-    	</div>
-		
-        <form method="get" action="result.html" >
-        	
-			<fieldset>
-				<legend>HTML5Widgets Test Form</legend>
-				<p>Form fields labelled <img src="images/asterix.gif" alt="*"/> are mandatory</p>
-            <table class="formTable">
-                <tbody>
-                	<tr>
-                		<th>Legal Name:</th>
-						<td><input type="text" name="name" value="" autofocus="autofocus" />
-						<div class="description">This field has focus when the page
-						first loads because it has it's <code>autofocus</code>
-						attribute set to <code>true</code>.
-						</td>
-					</tr>
-					
-                	<tr>
-                		<th>Company Name:</th>
-						<td><input type="text" name="placeholderEl" value=""
-						placeholder="Leave blank if unemployed" />
-						<div class="description">This field has it's 
-						<code>placeholder</code> attribute set to 
-						<code>"Leave blank if unemployed"</code>
-						
-						</td>
-					</tr>
-					
-                    <tr>
-                        <th>Age:</th>
-
-                        <td>
-                        
-                        <output class="withRange" onforminput="this.value = rangeEl.value" 
-							>-</output>	
-							
-						<input type="range"  name="rangeEl" value="" 
-                        min="0" max="150" class="range" />
-						
-						
-						</td>
-                    </tr>
-
-                    
-
-                    <tr>
-                        <th>Date/Time (Local)</th>
-
-                        <td><input type="datetime-local" name="DateTimeLocalTest" value=
-                        "">
-						<div class="description">The <code>datetime</code>,
-						<code>date</code>, <code>week</code> and <code>month</code>
-						input fields all show a calendar when clicked on.  When 
-						the user chooses a date, each input shows the date in
-						a slightly different format.
-						</div>
-						
-						</td>
-                    </tr>
-					
-					<tr>
-                        <th>Date/Time (UTC)</th>
-
-                        <td><input type="datetime" name="DateTimeTest" value=
-                        "">
-						<div class="description">The <code>datetime</code>,
-						<code>date</code>, <code>week</code> and <code>month</code>
-						input fields all show a calendar when clicked on.  When 
-						the user chooses a date, each input shows the date in
-						a slightly different format.
-						</div>
-						
-						</td>
-                    </tr>
-
-                    <tr>
-                        <th>Date</th>
-
-                        <td><input type="date" name="DateTest" value=
-                        ""></td>
-                    </tr>
-
-                    <tr>
-                        <th>Month</th>
-
-                        <td><input type="month" name="MonthTest" value=
-                        ""></td>
-                    </tr>
-
-                    <tr>
-                        <th>Week</th>
-
-                        <td><input type="week" name="WeekTest" value=
-                        ""></td>
-                    </tr>
-
-                  
-
-
-                    <tr>
-                        <th>Colour</th>
-
-                        <td><input type="color" name="ColorTest" value=
-                        "" ></td>
-                    </tr>
-					
-					<tr>
-						<th>Test validity</th>
-						<td><input type="text" name="safasfas" value="" pattern="[0-9]*" required="required" placeholder="Required Field" />
-						<div class="description">To test the <strong>required</strong> and <strong>pattern</strong>
-						attributes, this field only accepts numbers.</div>
-						
-						</td>
-					</tr>
-					
-					<tr>
-						<th>Terms and Conditions:</th>
-						<td>
-							I promise to give my first born to The Evil Corporation
-							in return for a free iPad.
-							<br />
-							<br />
-							<label><input type="checkbox" class="check" name="iAgree" value="yesDammitYes" required="required"  />I submit to my new evil overlord</label>
-							
-						
-						</td>
-						
-					</tr>
-					<tr>
-						<th></th>
-						<td >
-							<input type="submit" name="submit me" value="Submit" />
-						</td>
-					</tr>
-					
-                </tbody>
-            </table>
-            </fieldset>
-        </form>
-		
-		<div id="supports">
-			
-		</div>
-    </body>
-</html>
-
